Merge pull request #3066 from alexanderkyte/pedump_sgen
[mono.git] / mcs / class / referencesource / mscorlib / system / exception.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 //
6 // <OWNER>[....]</OWNER>
7 //
8 // ==--==
9 /*=============================================================================
10 **
11 ** Class: Exception
12 **
13 **
14 ** Purpose: The base class for all exceptional conditions.
15 **
16 **
17 =============================================================================*/
18
19 namespace System {
20     using System;
21     using System.Runtime.InteropServices;
22     using System.Runtime.CompilerServices;
23     using System.Runtime.Serialization;
24     using System.Runtime.Versioning;
25     using System.Diagnostics;
26     using System.Security.Permissions;
27     using System.Security;
28     using System.IO;
29     using System.Text;
30     using System.Reflection;
31     using System.Collections;
32     using System.Globalization;
33     using System.Diagnostics.Contracts;
34
35     [ClassInterface(ClassInterfaceType.None)]
36     [ComDefaultInterface(typeof(_Exception))]
37     [Serializable]
38     [ComVisible(true)]
39 #if MONO
40     [StructLayout (LayoutKind.Sequential)]
41 #endif
42     public class Exception : ISerializable
43 #if !(MONO && MOBILE)
44         , _Exception
45 #endif
46 {
47         private void Init()
48         {
49             _message = null;
50             _stackTrace = null;
51             _dynamicMethods = null;
52             HResult = __HResults.COR_E_EXCEPTION;
53 #if !MONO
54             _xcode = _COMPlusExceptionCode;
55             _xptrs = (IntPtr) 0;
56
57             // Initialize the WatsonBuckets to be null
58             _watsonBuckets = null;
59
60             // Initialize the watson bucketing IP
61             _ipForWatsonBuckets = UIntPtr.Zero;
62 #endif
63
64 #if FEATURE_SERIALIZATION
65              _safeSerializationManager = new SafeSerializationManager();
66 #endif // FEATURE_SERIALIZATION
67         }
68
69         public Exception() {
70             Init();
71         }
72     
73         public Exception(String message) {
74             Init();
75             _message = message;
76         }
77     
78         // Creates a new Exception.  All derived classes should 
79         // provide this constructor.
80         // Note: the stack trace is not started until the exception 
81         // is thrown
82         // 
83         public Exception (String message, Exception innerException) {
84             Init();
85             _message = message;
86             _innerException = innerException;
87         }
88
89         [System.Security.SecuritySafeCritical]  // auto-generated
90         protected Exception(SerializationInfo info, StreamingContext context) 
91         {
92             if (info==null)
93                 throw new ArgumentNullException("info");
94             Contract.EndContractBlock();
95     
96             _className = info.GetString("ClassName");
97             _message = info.GetString("Message");
98             _data = (IDictionary)(info.GetValueNoThrow("Data",typeof(IDictionary)));
99             _innerException = (Exception)(info.GetValue("InnerException",typeof(Exception)));
100             _helpURL = info.GetString("HelpURL");
101             _stackTraceString = info.GetString("StackTraceString");
102             _remoteStackTraceString = info.GetString("RemoteStackTraceString");
103             _remoteStackIndex = info.GetInt32("RemoteStackIndex");
104
105 #if !MONO
106             _exceptionMethodString = (String)(info.GetValue("ExceptionMethod",typeof(String)));
107 #endif
108             HResult = info.GetInt32("HResult");
109             _source = info.GetString("Source");
110     
111 #if !MONO
112             // Get the WatsonBuckets that were serialized - this is particularly
113             // done to support exceptions going across AD transitions.
114             // 
115             // We use the no throw version since we could be deserializing a pre-V4
116             // exception object that may not have this entry. In such a case, we would
117             // get null.
118             _watsonBuckets = (Object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[]));
119 #endif
120
121 #if FEATURE_SERIALIZATION
122             _safeSerializationManager = info.GetValueNoThrow("SafeSerializationManager", typeof(SafeSerializationManager)) as SafeSerializationManager;
123 #endif // FEATURE_SERIALIZATION
124
125             if (_className == null || HResult==0)
126                 throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
127             
128             // If we are constructing a new exception after a cross-appdomain call...
129             if (context.State == StreamingContextStates.CrossAppDomain)
130             {
131                 // ...this new exception may get thrown.  It is logically a re-throw, but 
132                 //  physically a brand-new exception.  Since the stack trace is cleared 
133                 //  on a new exception, the "_remoteStackTraceString" is provided to 
134                 //  effectively import a stack trace from a "remote" exception.  So,
135                 //  move the _stackTraceString into the _remoteStackTraceString.  Note
136                 //  that if there is an existing _remoteStackTraceString, it will be 
137                 //  preserved at the head of the new string, so everything works as 
138                 //  expected.
139                 // Even if this exception is NOT thrown, things will still work as expected
140                 //  because the StackTrace property returns the concatenation of the
141                 //  _remoteStackTraceString and the _stackTraceString.
142                 _remoteStackTraceString = _remoteStackTraceString + _stackTraceString;
143                 _stackTraceString = null;
144             }
145         }
146         
147         
148         public virtual String Message {
149                get {  
150                 if (_message == null) {
151                     if (_className==null) {
152                         _className = GetClassName();
153                     }
154                     return Environment.GetResourceString("Exception_WasThrown", _className);
155
156                 } else {
157                     return _message;
158                 }
159             }
160         }
161
162         public virtual IDictionary Data { 
163             [System.Security.SecuritySafeCritical]  // auto-generated
164             get {
165                 if (_data == null)
166                     if (IsImmutableAgileException(this))
167                         _data = new EmptyReadOnlyDictionaryInternal();
168                     else
169                         _data = new ListDictionaryInternal();
170                 
171                 return _data;
172             }
173         }
174
175 #if MONO
176         private static bool IsImmutableAgileException(Exception e) { return false; }
177 #else
178         [System.Security.SecurityCritical]  // auto-generated
179         [ResourceExposure(ResourceScope.None)]
180         [MethodImplAttribute(MethodImplOptions.InternalCall)]
181         private static extern bool IsImmutableAgileException(Exception e);
182 #endif
183
184 #if FEATURE_COMINTEROP
185         //
186         // Exception requires anything to be added into Data dictionary is serializable
187         // This wrapper is made serializable to satisfy this requirement but does NOT serialize 
188         // the object and simply ignores it during serialization, because we only need 
189         // the exception instance in the app to hold the error object alive.
190         // Once the exception is serialized to debugger, debugger only needs the error reference string
191         //
192         [Serializable]
193         internal class __RestrictedErrorObject
194         {
195             // Hold the error object instance but don't serialize/deserialize it
196             [NonSerialized]
197             private object _realErrorObject;
198
199             internal __RestrictedErrorObject(object errorObject)
200             {
201                 _realErrorObject = errorObject;    
202             }
203
204             public object RealErrorObject
205             {
206                get
207                {
208                    return _realErrorObject;
209                }
210             }
211         }
212
213         [FriendAccessAllowed]
214         internal void AddExceptionDataForRestrictedErrorInfo(
215             string restrictedError, 
216             string restrictedErrorReference, 
217             string restrictedCapabilitySid,
218             object restrictedErrorObject,
219             bool hasrestrictedLanguageErrorObject = false)
220         {
221             IDictionary dict = Data;
222             if (dict != null)
223             {
224                 dict.Add("RestrictedDescription", restrictedError);
225                 dict.Add("RestrictedErrorReference", restrictedErrorReference);
226                 dict.Add("RestrictedCapabilitySid", restrictedCapabilitySid);
227
228                 // Keep the error object alive so that user could retrieve error information
229                 // using Data["RestrictedErrorReference"]
230                 dict.Add("__RestrictedErrorObject", (restrictedErrorObject == null ? null : new __RestrictedErrorObject(restrictedErrorObject)));
231                 dict.Add("__HasRestrictedLanguageErrorObject", hasrestrictedLanguageErrorObject);
232             }
233         }
234
235         internal bool TryGetRestrictedLanguageErrorObject(out object restrictedErrorObject)
236         {
237             restrictedErrorObject = null;
238             if (Data != null && Data.Contains("__HasRestrictedLanguageErrorObject"))
239             {
240                 if (Data.Contains("__RestrictedErrorObject"))
241                 {
242                     __RestrictedErrorObject restrictedObject = Data["__RestrictedErrorObject"] as __RestrictedErrorObject;
243                     if (restrictedObject != null)
244                         restrictedErrorObject = restrictedObject.RealErrorObject;
245                 }
246                 return (bool)Data["__HasRestrictedLanguageErrorObject"];
247             }
248
249             return false;
250         }
251 #endif // FEATURE_COMINTEROP
252
253         private string GetClassName()
254         {
255             // Will include namespace but not full instantiation and assembly name.
256             if (_className == null)
257                 _className = GetType().ToString();
258
259             return _className;
260         }
261     
262         // Retrieves the lowest exception (inner most) for the given Exception.
263         // This will traverse exceptions using the innerException property.
264         //
265         public virtual Exception GetBaseException() 
266         {
267             Exception inner = InnerException;
268             Exception back = this;
269             
270             while (inner != null) {
271                 back = inner;
272                 inner = inner.InnerException;
273             }
274             
275             return back;
276         }
277         
278         // Returns the inner exception contained in this exception
279         // 
280         public Exception InnerException {
281             get { return _innerException; }
282         }
283
284
285         [System.Security.SecurityCritical]  // auto-generated
286         [ResourceExposure(ResourceScope.None)]
287         [MethodImplAttribute(MethodImplOptions.InternalCall)]
288         static extern private IRuntimeMethodInfo GetMethodFromStackTrace(Object stackTrace);
289
290 #if !MONO
291         [System.Security.SecuritySafeCritical]  // auto-generated
292         private MethodBase GetExceptionMethodFromStackTrace()
293         {
294             IRuntimeMethodInfo method = GetMethodFromStackTrace(_stackTrace);
295
296             // Under certain race conditions when exceptions are re-used, this can be null
297             if (method == null)
298                 return null;
299
300             return RuntimeType.GetMethodBase(method);
301         }
302 #endif
303     
304         public MethodBase TargetSite {
305             [System.Security.SecuritySafeCritical]  // auto-generated
306             get {
307 #if MONO
308                 StackTrace st = new StackTrace (this, true);
309                 if (st.FrameCount > 0)
310                     return st.GetFrame (0).GetMethod ();
311                 
312                 return null;
313 #else
314                 return GetTargetSiteInternal();
315 #endif
316             }
317         }
318     
319 #if !MONO
320         // This, as well as the entire "exception method" mechanism, appear to be linked to security features which Mono does not support.
321         // this function is provided as a private helper to avoid the security demand
322         [System.Security.SecurityCritical]  // auto-generated
323         private MethodBase GetTargetSiteInternal() {
324             if (_exceptionMethod!=null) {
325                 return _exceptionMethod;
326             }
327             if (_stackTrace==null) {
328                 return null;
329             }
330
331             if (_exceptionMethodString!=null) {
332                 _exceptionMethod = GetExceptionMethodFromString();
333             } else {
334                 _exceptionMethod = GetExceptionMethodFromStackTrace();
335             }
336             return _exceptionMethod;
337         }
338 #endif
339     
340         // Returns the stack trace as a string.  If no stack trace is
341         // available, null is returned.
342         public virtual String StackTrace
343         {
344 #if FEATURE_CORECLR
345             [System.Security.SecuritySafeCritical] 
346 #endif
347             get 
348             {
349                 // By default attempt to include file and line number info
350                 return GetStackTrace(true);
351             }
352         }
353
354         // Computes and returns the stack trace as a string
355         // Attempts to get source file and line number information if needFileInfo
356         // is true.  Note that this requires FileIOPermission(PathDiscovery), and so
357         // will usually fail in CoreCLR.  To avoid the demand and resulting
358         // SecurityException we can explicitly not even try to get fileinfo.
359         #if FEATURE_CORECLR
360         [System.Security.SecurityCritical] // auto-generated
361         #endif
362         private string GetStackTrace(bool needFileInfo)
363         {
364             string stackTraceString = _stackTraceString;
365             string remoteStackTraceString = _remoteStackTraceString;
366
367 #if !FEATURE_CORECLR
368             if (!needFileInfo)
369             {
370                 // Filter out file names/paths and line numbers from _stackTraceString and _remoteStackTraceString.
371                 // This is used only when generating stack trace for Watson where the strings must be PII-free.
372                 stackTraceString = StripFileInfo(stackTraceString, false);
373                 remoteStackTraceString = StripFileInfo(remoteStackTraceString, true);
374             }
375 #endif // !FEATURE_CORECLR
376
377             // if no stack trace, try to get one
378             if (stackTraceString != null)
379             {
380                 return remoteStackTraceString + stackTraceString;
381             }
382             if (_stackTrace == null)
383             {
384                 return remoteStackTraceString;
385             }
386
387             // Obtain the stack trace string. Note that since Environment.GetStackTrace
388             // will add the path to the source file if the PDB is present and a demand
389             // for FileIOPermission(PathDiscovery) succeeds, we need to make sure we 
390             // don't store the stack trace string in the _stackTraceString member variable.
391             String tempStackTraceString = Environment.GetStackTrace(this, needFileInfo);
392             return remoteStackTraceString + tempStackTraceString;
393          }
394     
395         [FriendAccessAllowed]
396         internal void SetErrorCode(int hr)
397         {
398             HResult = hr;
399         }
400         
401         // Sets the help link for this exception.
402         // This should be in a URL/URN form, such as:
403         // "file:///C:/Applications/Bazzal/help.html#ErrorNum42"
404         // Changed to be a read-write String and not return an exception
405         public virtual String HelpLink
406         {
407             get
408             {
409                 return _helpURL;
410             }
411             set
412             {
413                 _helpURL = value;
414             }
415         }
416     
417         public virtual String Source {
418             #if FEATURE_CORECLR
419             [System.Security.SecurityCritical] // auto-generated
420             #endif
421             get { 
422                 if (_source == null)
423                 {
424                     StackTrace st = new StackTrace(this,true);
425                     if (st.FrameCount>0)
426                     {
427                         StackFrame sf = st.GetFrame(0);
428                         MethodBase method = sf.GetMethod();
429
430 #if MONO
431                         if (method != null) { // source can be null
432                             _source = method.DeclaringType.Assembly.UnprotectedGetName ().Name;
433                         }
434 #else
435                         Module module = method.Module;
436
437                         RuntimeModule rtModule = module as RuntimeModule;
438
439                         if (rtModule == null)
440                         {
441                             System.Reflection.Emit.ModuleBuilder moduleBuilder = module as System.Reflection.Emit.ModuleBuilder;
442                             if (moduleBuilder != null)
443                                 rtModule = moduleBuilder.InternalModule;
444                             else
445                                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeReflectionObject"));
446                         }
447
448                         _source = rtModule.GetRuntimeAssembly().GetSimpleName();
449 #endif
450                     }
451                 }
452
453                 return _source;
454             }
455             #if FEATURE_CORECLR
456             [System.Security.SecurityCritical] // auto-generated
457             #endif
458             set { _source = value; }
459         }
460
461 #if FEATURE_CORECLR
462         [System.Security.SecuritySafeCritical] 
463 #endif
464         public override String ToString()
465         {
466             return ToString(true, true);
467         }
468
469         #if FEATURE_CORECLR
470         [System.Security.SecurityCritical] // auto-generated
471         #endif
472         private String ToString(bool needFileLineInfo, bool needMessage) {
473             String message = (needMessage ? Message : null);
474             String s;
475
476             if (message == null || message.Length <= 0) {
477                 s = GetClassName();
478             }
479             else {
480                 s = GetClassName() + ": " + message;
481             }
482
483             if (_innerException!=null) {
484                 s = s + " ---> " + _innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine + 
485                 "   " + Environment.GetResourceString("Exception_EndOfInnerExceptionStack");
486
487             }
488
489             string stackTrace = GetStackTrace(needFileLineInfo);
490             if (stackTrace != null)
491             {
492                 s += Environment.NewLine + stackTrace;
493             }
494
495             return s;
496         }
497
498 #if !MONO
499         [System.Security.SecurityCritical]  // auto-generated
500         private String GetExceptionMethodString() {
501             MethodBase methBase = GetTargetSiteInternal();
502             if (methBase==null) {
503                 return null;
504             }
505             if (methBase is System.Reflection.Emit.DynamicMethod.RTDynamicMethod)
506             {
507                 // DynamicMethods cannot be serialized
508                 return null;
509             }
510
511             // Note that the newline separator is only a separator, chosen such that
512             //  it won't (generally) occur in a method name.  This string is used 
513             //  only for serialization of the Exception Method.
514             char separator = '\n';
515             StringBuilder result = new StringBuilder();
516             if (methBase is ConstructorInfo) {
517                 RuntimeConstructorInfo rci = (RuntimeConstructorInfo)methBase;
518                 Type t = rci.ReflectedType;
519                 result.Append((int)MemberTypes.Constructor);
520                 result.Append(separator);
521                 result.Append(rci.Name);
522                 if (t!=null)
523                 {
524                     result.Append(separator);
525                     result.Append(t.Assembly.FullName);
526                     result.Append(separator);
527                     result.Append(t.FullName);
528                 }
529                 result.Append(separator);
530                 result.Append(rci.ToString());
531             } else {
532                 Contract.Assert(methBase is MethodInfo, "[Exception.GetExceptionMethodString]methBase is MethodInfo");
533                 RuntimeMethodInfo rmi = (RuntimeMethodInfo)methBase;
534                 Type t = rmi.DeclaringType;
535                 result.Append((int)MemberTypes.Method);
536                 result.Append(separator);
537                 result.Append(rmi.Name);
538                 result.Append(separator);
539                 result.Append(rmi.Module.Assembly.FullName);
540                 result.Append(separator);
541                 if (t != null)
542                 {
543                     result.Append(t.FullName);
544                     result.Append(separator);
545                 }
546                 result.Append(rmi.ToString());
547             }
548             
549             return result.ToString();
550         }
551
552         [System.Security.SecurityCritical]  // auto-generated
553         private MethodBase GetExceptionMethodFromString() {
554             Contract.Assert(_exceptionMethodString != null, "Method string cannot be NULL!");
555             String[] args = _exceptionMethodString.Split(new char[]{'\0', '\n'});
556             if (args.Length!=5) {
557                 throw new SerializationException();
558             }
559             SerializationInfo si = new SerializationInfo(typeof(MemberInfoSerializationHolder), new FormatterConverter());
560             si.AddValue("MemberType", (int)Int32.Parse(args[0], CultureInfo.InvariantCulture), typeof(Int32));
561             si.AddValue("Name", args[1], typeof(String));
562             si.AddValue("AssemblyName", args[2], typeof(String));
563             si.AddValue("ClassName", args[3]);
564             si.AddValue("Signature", args[4]);
565             MethodBase result;
566             StreamingContext sc = new StreamingContext(StreamingContextStates.All);
567             try {
568                 result = (MethodBase)new MemberInfoSerializationHolder(si, sc).GetRealObject(sc);
569             } catch (SerializationException) {
570                 result = null;
571             }
572             return result;
573         }
574 #endif
575
576 #if FEATURE_SERIALIZATION
577         protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState
578         {
579             add { _safeSerializationManager.SerializeObjectState += value; }
580             remove { _safeSerializationManager.SerializeObjectState -= value; }
581         }
582 #endif // FEATURE_SERIALIZATION
583
584         [System.Security.SecurityCritical]  // auto-generated_required
585         public virtual void GetObjectData(SerializationInfo info, StreamingContext context) 
586         {
587             if (info == null)
588             {
589                 throw new ArgumentNullException("info");
590             }
591             Contract.EndContractBlock();
592
593             String tempStackTraceString = _stackTraceString;        
594     
595             if (_stackTrace!=null) 
596             {
597                 if (tempStackTraceString==null) 
598                 {
599                     tempStackTraceString = Environment.GetStackTrace(this, true);
600                 }
601 #if !MONO
602                 if (_exceptionMethod==null) 
603                 {
604                     _exceptionMethod = GetExceptionMethodFromStackTrace();
605                 }
606 #endif
607             }
608
609             if (_source == null) 
610             {
611                 _source = Source; // Set the Source information correctly before serialization
612             }
613     
614             info.AddValue("ClassName", GetClassName(), typeof(String));
615             info.AddValue("Message", _message, typeof(String));
616             info.AddValue("Data", _data, typeof(IDictionary));
617             info.AddValue("InnerException", _innerException, typeof(Exception));
618             info.AddValue("HelpURL", _helpURL, typeof(String));
619             info.AddValue("StackTraceString", tempStackTraceString, typeof(String));
620             info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(String));
621             info.AddValue("RemoteStackIndex", _remoteStackIndex, typeof(Int32));
622 #if MONO
623             info.AddValue("ExceptionMethod", null);
624 #else
625             info.AddValue("ExceptionMethod", GetExceptionMethodString(), typeof(String));
626 #endif
627             info.AddValue("HResult", HResult);
628             info.AddValue("Source", _source, typeof(String));
629             
630 #if !MONO
631             // Serialize the Watson bucket details as well
632             info.AddValue("WatsonBuckets", _watsonBuckets, typeof(byte[]));
633 #endif
634
635 #if FEATURE_SERIALIZATION
636             if (_safeSerializationManager != null && _safeSerializationManager.IsActive)
637             {
638                 info.AddValue("SafeSerializationManager", _safeSerializationManager, typeof(SafeSerializationManager));
639
640                 // User classes derived from Exception must have a valid _safeSerializationManager.
641                 // Exceptions defined in mscorlib don't use this field might not have it initalized (since they are 
642                 // often created in the VM with AllocateObject instead if the managed construtor)
643                 // If you are adding code to use a SafeSerializationManager from an mscorlib exception, update
644                 // this assert to ensure that it fails when that exception's _safeSerializationManager is NULL 
645                 Contract.Assert(((_safeSerializationManager != null) || (this.GetType().Assembly == typeof(object).Assembly)), 
646                                 "User defined exceptions must have a valid _safeSerializationManager");
647             
648                 // Handle serializing any transparent or partial trust subclass data
649                 _safeSerializationManager.CompleteSerialization(this, info, context);
650             }
651 #endif // FEATURE_SERIALIZATION
652         }
653
654         // This is used by remoting to preserve the server side stack trace
655         // by appending it to the message ... before the exception is rethrown
656         // at the client call site.
657         internal Exception PrepForRemoting()
658         {
659             String tmp = null;
660
661             if (_remoteStackIndex == 0)
662             {
663                 tmp = Environment.NewLine+ "Server stack trace: " + Environment.NewLine
664                     + StackTrace 
665                     + Environment.NewLine + Environment.NewLine 
666                     + "Exception rethrown at ["+_remoteStackIndex+"]: " + Environment.NewLine;
667             }
668             else
669             {
670                 tmp = StackTrace 
671                     + Environment.NewLine + Environment.NewLine 
672                     + "Exception rethrown at ["+_remoteStackIndex+"]: " + Environment.NewLine;
673             }
674
675             _remoteStackTraceString = tmp;
676             _remoteStackIndex++;
677
678             return this;
679         }
680
681         // This method will clear the _stackTrace of the exception object upon deserialization
682         // to ensure that references from another AD/Process dont get accidently used.
683         [OnDeserialized]
684         private void OnDeserialized(StreamingContext context)
685         {
686             _stackTrace = null;
687
688 #if !MONO
689             // We wont serialize or deserialize the IP for Watson bucketing since
690             // we dont know where the deserialized object will be used in.
691             // Using it across process or an AppDomain could be invalid and result
692             // in AV in the runtime.
693             //
694             // Hence, we set it to zero when deserialization takes place. 
695             _ipForWatsonBuckets = UIntPtr.Zero;
696 #endif
697
698 #if FEATURE_SERIALIZATION
699             if (_safeSerializationManager == null)
700             {
701                 _safeSerializationManager = new SafeSerializationManager();
702             }
703             else
704             {
705                 _safeSerializationManager.CompleteDeserialization(this);
706             }
707 #endif // FEATURE_SERIALIZATION
708         }
709
710         // This is used by the runtime when re-throwing a managed exception.  It will
711         //  copy the stack trace to _remoteStackTraceString.
712 #if FEATURE_CORECLR
713         [System.Security.SecuritySafeCritical] 
714 #endif
715         internal void InternalPreserveStackTrace()
716         {
717             string tmpStackTraceString;
718
719 #if FEATURE_APPX
720             if (AppDomain.IsAppXModel())
721             {
722                 // Call our internal GetStackTrace in AppX so we can parse the result should
723                 // we need to strip file/line info from it to make it PII-free. Calling the
724                 // public and overridable StackTrace getter here was probably not intended.
725                 tmpStackTraceString = GetStackTrace(true);
726
727                 // Make sure that the _source field is initialized if Source is not overriden.
728                 // We want it to contain the original faulting point.
729                 string source = Source;
730             }
731             else
732 #else // FEATURE_APPX
733 #if FEATURE_CORESYSTEM
734             // Preinitialize _source on CoreSystem as well. The legacy behavior is not ideal and
735             // we keep it for back compat but we can afford to make the change on the Phone.
736             string source = Source;
737 #endif // FEATURE_CORESYSTEM
738 #endif // FEATURE_APPX
739             {
740                 // Call the StackTrace getter in classic for compat.
741                 tmpStackTraceString = StackTrace;
742             }
743
744             if (tmpStackTraceString != null && tmpStackTraceString.Length > 0)
745             {
746                 _remoteStackTraceString = tmpStackTraceString + Environment.NewLine;
747             }
748             
749             _stackTrace = null;
750             _stackTraceString = null;
751         }
752         
753 #if FEATURE_EXCEPTIONDISPATCHINFO
754
755         // This is the object against which a lock will be taken
756         // when attempt to restore the EDI. Since its static, its possible
757         // that unrelated exception object restorations could get blocked
758         // for a small duration but that sounds reasonable considering
759         // such scenarios are going to be extremely rare, where timing
760         // matches precisely.
761         [OptionalField]
762         private static object s_EDILock = new object();
763
764 #if !MONO
765         internal UIntPtr IPForWatsonBuckets
766         {
767             get {
768                 return _ipForWatsonBuckets;
769             }        
770         }
771     
772         internal object WatsonBuckets
773         {
774             get 
775             {
776                 return _watsonBuckets;
777             }
778         }
779 #endif
780
781         internal string RemoteStackTrace
782         {
783             get
784             {
785                 return _remoteStackTraceString;
786             }
787         }
788
789 #if MONO
790         // This is only needed for Watson support
791         private string StripFileInfo(string stackTrace, bool isRemoteStackTrace) {
792             return stackTrace;
793         }
794 #else
795         [System.Security.SecurityCritical]  // auto-generated
796         [ResourceExposure(ResourceScope.None)]
797         [MethodImplAttribute(MethodImplOptions.InternalCall)]
798         private static extern void PrepareForForeignExceptionRaise();
799
800         [System.Security.SecurityCritical]  // auto-generated
801         [ResourceExposure(ResourceScope.None)]
802         [MethodImplAttribute(MethodImplOptions.InternalCall)]
803         private static extern void GetStackTracesDeepCopy(Exception exception, out object currentStackTrace, out object dynamicMethodArray);
804
805         [System.Security.SecurityCritical]  // auto-generated
806         [ResourceExposure(ResourceScope.None)]
807         [MethodImplAttribute(MethodImplOptions.InternalCall)]
808         internal static extern void SaveStackTracesFromDeepCopy(Exception exception, object currentStackTrace, object dynamicMethodArray);
809
810         [System.Security.SecurityCritical]  // auto-generated
811         [ResourceExposure(ResourceScope.None)]
812         [MethodImplAttribute(MethodImplOptions.InternalCall)]
813         private static extern object CopyStackTrace(object currentStackTrace);
814
815         [System.Security.SecurityCritical]  // auto-generated
816         [ResourceExposure(ResourceScope.None)]
817         [MethodImplAttribute(MethodImplOptions.InternalCall)]
818         private static extern object CopyDynamicMethods(object currentDynamicMethods);
819
820 #if !FEATURE_CORECLR
821         [System.Security.SecuritySafeCritical]
822         [ResourceExposure(ResourceScope.None)]
823         [MethodImplAttribute(MethodImplOptions.InternalCall)]
824         private extern string StripFileInfo(string stackTrace, bool isRemoteStackTrace);
825 #endif // !FEATURE_CORECLR
826
827         [SecuritySafeCritical]
828         internal object DeepCopyStackTrace(object currentStackTrace)
829         {
830             if (currentStackTrace != null)
831             {
832                 return CopyStackTrace(currentStackTrace);
833             }
834             else
835             {
836                 return null;
837             }
838         }
839
840         [SecuritySafeCritical]
841         internal object DeepCopyDynamicMethods(object currentDynamicMethods)
842         {
843             if (currentDynamicMethods != null)
844             {
845                 return CopyDynamicMethods(currentDynamicMethods);
846             }
847             else
848             {
849                 return null;
850             }
851         }
852         
853         [SecuritySafeCritical]
854         internal void GetStackTracesDeepCopy(out object currentStackTrace, out object dynamicMethodArray)
855         {
856             GetStackTracesDeepCopy(this, out currentStackTrace, out dynamicMethodArray);
857         }
858 #endif
859
860         // This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the
861         // exception, just before the exception is "rethrown".
862         [SecuritySafeCritical]
863         internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
864         {
865 #if MONO
866             captured_traces = (StackTrace[]) exceptionDispatchInfo.BinaryStackTraceArray;
867             _stackTrace = null;
868             _stackTraceString = null;
869 #else
870             bool fCanProcessException = !(IsImmutableAgileException(this));
871             // Restore only for non-preallocated exceptions
872             if (fCanProcessException)
873             {
874                 // Take a lock to ensure only one thread can restore the details
875                 // at a time against this exception object that could have
876                 // multiple ExceptionDispatchInfo instances associated with it.
877                 //
878                 // We do this inside a finally clause to ensure ThreadAbort cannot
879                 // be injected while we have taken the lock. This is to prevent
880                 // unrelated exception restorations from getting blocked due to TAE.
881                 try{}
882                 finally
883                 {
884                     // When restoring back the fields, we again create a copy and set reference to them
885                     // in the exception object. This will ensure that when this exception is thrown and these
886                     // fields are modified, then EDI's references remain intact.
887                     //
888                     // Since deep copying can throw on OOM, try to get the copies
889                     // outside the lock.
890                     object _stackTraceCopy = (exceptionDispatchInfo.BinaryStackTraceArray == null)?null:DeepCopyStackTrace(exceptionDispatchInfo.BinaryStackTraceArray);
891                     object _dynamicMethodsCopy = (exceptionDispatchInfo.DynamicMethodArray == null)?null:DeepCopyDynamicMethods(exceptionDispatchInfo.DynamicMethodArray);
892                     
893                     // Finally, restore the information. 
894                     //
895                     // Since EDI can be created at various points during exception dispatch (e.g. at various frames on the stack) for the same exception instance,
896                     // they can have different data to be restored. Thus, to ensure atomicity of restoration from each EDI, perform the restore under a lock.
897                     lock(Exception.s_EDILock)
898                     {
899 #if !MONO
900                         _watsonBuckets = exceptionDispatchInfo.WatsonBuckets;
901                         _ipForWatsonBuckets = exceptionDispatchInfo.IPForWatsonBuckets;
902 #endif
903                         _remoteStackTraceString = exceptionDispatchInfo.RemoteStackTrace;
904                         SaveStackTracesFromDeepCopy(this, _stackTraceCopy, _dynamicMethodsCopy);
905                     }
906                     _stackTraceString = null;
907
908                     // Marks the TES state to indicate we have restored foreign exception
909                     // dispatch information.
910                     Exception.PrepareForForeignExceptionRaise();
911                 }
912             }
913 #endif
914         }
915 #endif // FEATURE_EXCEPTIONDISPATCHINFO
916
917         private String _className;  //Needed for serialization.  
918 #if !MONO
919         // See TargetSite comments
920         private MethodBase _exceptionMethod;  //Needed for serialization.  
921         private String _exceptionMethodString; //Needed for serialization. 
922 #endif
923         internal String _message;
924         private IDictionary _data;
925         private Exception _innerException;
926         private String _helpURL;
927         private Object _stackTrace;
928 #if !MONO
929         // Watson is Microsoft's online crash reporting system
930         [OptionalField] // This isnt present in pre-V4 exception objects that would be serialized.
931         private Object _watsonBuckets;
932 #endif
933         private String _stackTraceString; //Needed for serialization.  
934         private String _remoteStackTraceString;
935         private int _remoteStackIndex;
936 #pragma warning disable 414  // Field is not used from managed.        
937         // _dynamicMethods is an array of System.Resolver objects, used to keep
938         // DynamicMethodDescs alive for the lifetime of the exception. We do this because
939         // the _stackTrace field holds MethodDescs, and a DynamicMethodDesc can be destroyed
940         // unless a System.Resolver object roots it.
941         private Object _dynamicMethods; 
942 #pragma warning restore 414
943
944         // @MANAGED: HResult is used from within the EE!  Rename with care - check VM directory
945         internal int _HResult;     // HResult
946
947         public int HResult
948         {
949             get
950             {
951                 return _HResult;
952             }
953             protected set
954             {
955                 _HResult = value;
956             }
957         }
958         
959         private String _source;         // Mainly used by VB. 
960 #if !MONO
961         // WARNING: Don't delete/rename _xptrs and _xcode - used by functions
962         // on Marshal class.  Native functions are in COMUtilNative.cpp & AppDomain
963         private IntPtr _xptrs;             // Internal EE stuff 
964 #pragma warning disable 414  // Field is not used from managed.
965         private int _xcode;             // Internal EE stuff 
966 #pragma warning restore 414
967         [OptionalField]
968         private UIntPtr _ipForWatsonBuckets; // Used to persist the IP for Watson Bucketing
969 #endif
970
971 #if FEATURE_SERIALIZATION
972         [OptionalField(VersionAdded = 4)]
973         private SafeSerializationManager _safeSerializationManager;
974 #endif // FEATURE_SERIALIZATION
975
976 #if MONO
977         // Mono: Used when rethrowing exception
978         internal StackTrace[] captured_traces;
979
980         // Mono addition: Used on iPhone
981         IntPtr[] native_trace_ips;
982 #endif
983
984     // See clr\src\vm\excep.h's EXCEPTION_COMPLUS definition:
985         private const int _COMPlusExceptionCode = unchecked((int)0xe0434352);   // Win32 exception code for COM+ exceptions
986
987         // InternalToString is called by the runtime to get the exception text 
988         // and create a corresponding CrossAppDomainMarshaledException
989         [System.Security.SecurityCritical]  // auto-generated
990         internal virtual String InternalToString()
991         {
992 #if !DISABLE_CAS_USE
993             try 
994             {
995 #pragma warning disable 618
996                 SecurityPermission sp= new SecurityPermission(SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy);
997 #pragma warning restore 618
998                 sp.Assert();
999             }
1000             catch  
1001             {
1002                 //under normal conditions there should be no exceptions
1003                 //however if something wrong happens we still can call the usual ToString
1004             }
1005 #endif
1006
1007             // Get the current stack trace string.  On CoreCLR we don't bother
1008             // to try and include file/line-number information because all AppDomains
1009             // are sandboxed, and so this won't succeed in most (or all) cases.  Therefore the
1010             // Demand and exception overhead is a waste.
1011             // We currently have some bugs in watson bucket generation where the SecurityException
1012             // here causes us to lose saved bucket parameters.  By not even doing the demand
1013             // we avoid those problems (although there are deep underlying problems that need to
1014             // be fixed there - relying on this to avoid problems is incomplete and brittle).
1015             bool fGetFileLineInfo = true;
1016 #if FEATURE_CORECLR
1017             fGetFileLineInfo = false;
1018 #endif
1019             return ToString(fGetFileLineInfo, true);
1020         }
1021
1022 #if !FEATURE_CORECLR
1023         // this method is required so Object.GetType is not made virtual by the compiler
1024         // _Exception.GetType()
1025         public new Type GetType()
1026         {
1027             return base.GetType();
1028         }
1029 #endif
1030
1031         internal bool IsTransient
1032         {
1033             [System.Security.SecuritySafeCritical]  // auto-generated
1034             get {
1035                 return nIsTransient(_HResult);
1036             }
1037         }
1038
1039         [System.Security.SecurityCritical]  // auto-generated
1040         [ResourceExposure(ResourceScope.None)]
1041         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1042         private extern static bool nIsTransient(int hr);
1043
1044
1045         // This piece of infrastructure exists to help avoid deadlocks 
1046         // between parts of mscorlib that might throw an exception while 
1047         // holding a lock that are also used by mscorlib's ResourceManager
1048         // instance.  As a special case of code that may throw while holding
1049         // a lock, we also need to fix our asynchronous exceptions to use
1050         // Win32 resources as well (assuming we ever call a managed 
1051         // constructor on instances of them).  We should grow this set of
1052         // exception messages as we discover problems, then move the resources
1053         // involved to native code.
1054         internal enum ExceptionMessageKind
1055         {
1056             ThreadAbort = 1,
1057             ThreadInterrupted = 2,
1058             OutOfMemory = 3
1059         }
1060
1061         // See comment on ExceptionMessageKind
1062         [System.Security.SecuritySafeCritical]  // auto-generated
1063         internal static String GetMessageFromNativeResources(ExceptionMessageKind kind)
1064         {
1065 #if MONO
1066             switch (kind) {
1067             case ExceptionMessageKind.ThreadAbort:
1068                 return "";
1069             case ExceptionMessageKind.ThreadInterrupted:
1070                 return "";
1071             case ExceptionMessageKind.OutOfMemory:
1072                 return "Out of memory";
1073             }
1074             return "";
1075 #else
1076             string retMesg = null;
1077             GetMessageFromNativeResources(kind, JitHelpers.GetStringHandleOnStack(ref retMesg));
1078             return retMesg;
1079 #endif
1080         }
1081
1082 #if !MONO
1083         [System.Security.SecurityCritical]  // auto-generated
1084         [ResourceExposure(ResourceScope.None)]
1085         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1086         [SuppressUnmanagedCodeSecurity]
1087         private static extern void GetMessageFromNativeResources(ExceptionMessageKind kind, StringHandleOnStack retMesg);
1088 #endif
1089
1090 #if MONO
1091         // Exposed to support Mono BCL classes
1092         internal void SetMessage (string s)
1093         {
1094             _message = s;
1095         }
1096
1097         internal void SetStackTrace (string s)
1098         {
1099             _stackTraceString = s;
1100         }
1101
1102         // Support for a System.Runtime.Remoting.Proxies.RealProxy edge case
1103         internal Exception FixRemotingException ()
1104         {
1105             string message = (0 == _remoteStackIndex) ?
1106                 Locale.GetText ("{0}{0}Server stack trace: {0}{1}{0}{0}Exception rethrown at [{2}]: {0}") :
1107                 Locale.GetText ("{1}{0}{0}Exception rethrown at [{2}]: {0}");
1108             string tmp = String.Format (message, Environment.NewLine, StackTrace, _remoteStackIndex);
1109
1110             _remoteStackTraceString = tmp;
1111             _remoteStackIndex++;
1112
1113             _stackTraceString = null;
1114
1115             return this;
1116         }
1117 #endif
1118     }
1119
1120
1121
1122 #if FEATURE_CORECLR
1123
1124     //--------------------------------------------------------------------------
1125     // Telesto: Telesto doesn't support appdomain marshaling of objects so
1126     // managed exceptions that leak across appdomain boundaries are flatted to
1127     // its ToString() output and rethrown as an CrossAppDomainMarshaledException.
1128     // The Message field is set to the ToString() output of the original exception.
1129     //--------------------------------------------------------------------------
1130
1131     [Serializable]
1132     internal sealed class CrossAppDomainMarshaledException : SystemException 
1133     {
1134         public CrossAppDomainMarshaledException(String message, int errorCode) 
1135             : base(message) 
1136         {
1137             SetErrorCode(errorCode);
1138         }
1139
1140         // Normally, only Telesto's UEF will see these exceptions.
1141         // This override prints out the original Exception's ToString()
1142         // output and hides the fact that it is wrapped inside another excepton.
1143         #if FEATURE_CORECLR
1144         [System.Security.SecurityCritical] // auto-generated
1145         #endif
1146         internal override String InternalToString()
1147         {
1148             return Message;
1149         }
1150     
1151     }
1152 #endif
1153
1154
1155 }
1156