Delete FriendAccessAllowedAttribute and associated dead code (#15101)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Exception.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*=============================================================================
6 **
7 **
8 **
9 ** Purpose: The base class for all exceptional conditions.
10 **
11 **
12 =============================================================================*/
13
14 namespace System
15 {
16     using System;
17     using System.Runtime.InteropServices;
18     using System.Runtime.CompilerServices;
19     using System.Runtime.Serialization;
20     using System.Runtime.Versioning;
21     using System.Diagnostics;
22     using System.Security;
23     using System.IO;
24     using System.Text;
25     using System.Reflection;
26     using System.Collections;
27     using System.Globalization;
28
29     [Serializable]
30     [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
31     public class Exception : ISerializable
32     {
33         private void Init()
34         {
35             _message = null;
36             _stackTrace = null;
37             _dynamicMethods = null;
38             HResult = HResults.COR_E_EXCEPTION;
39             _xcode = _COMPlusExceptionCode;
40             _xptrs = (IntPtr)0;
41
42             // Initialize the WatsonBuckets to be null
43             _watsonBuckets = null;
44
45             // Initialize the watson bucketing IP
46             _ipForWatsonBuckets = UIntPtr.Zero;
47         }
48
49         public Exception()
50         {
51             Init();
52         }
53
54         public Exception(String message)
55         {
56             Init();
57             _message = message;
58         }
59
60         // Creates a new Exception.  All derived classes should 
61         // provide this constructor.
62         // Note: the stack trace is not started until the exception 
63         // is thrown
64         // 
65         public Exception(String message, Exception innerException)
66         {
67             Init();
68             _message = message;
69             _innerException = innerException;
70         }
71
72         protected Exception(SerializationInfo info, StreamingContext context)
73         {
74             if (info == null)
75                 throw new ArgumentNullException(nameof(info));
76
77             _className = info.GetString("ClassName"); // Do not rename (binary serialization)
78             _message = info.GetString("Message"); // Do not rename (binary serialization)
79             _data = (IDictionary)(info.GetValueNoThrow("Data", typeof(IDictionary))); // Do not rename (binary serialization)
80             _innerException = (Exception)(info.GetValue("InnerException", typeof(Exception))); // Do not rename (binary serialization)
81             _helpURL = info.GetString("HelpURL"); // Do not rename (binary serialization)
82             _stackTraceString = info.GetString("StackTraceString"); // Do not rename (binary serialization)
83             _remoteStackTraceString = info.GetString("RemoteStackTraceString"); // Do not rename (binary serialization)
84             _remoteStackIndex = info.GetInt32("RemoteStackIndex"); // Do not rename (binary serialization)
85
86             HResult = info.GetInt32("HResult"); // Do not rename (binary serialization)
87             _source = info.GetString("Source"); // Do not rename (binary serialization)
88
89             // Get the WatsonBuckets that were serialized - this is particularly
90             // done to support exceptions going across AD transitions.
91             // 
92             // We use the no throw version since we could be deserializing a pre-V4
93             // exception object that may not have this entry. In such a case, we would
94             // get null.
95             _watsonBuckets = (Object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[])); // Do not rename (binary serialization)
96
97
98             if (_className == null || HResult == 0)
99                 throw new SerializationException(SR.Serialization_InsufficientState);
100
101             // If we are constructing a new exception after a cross-appdomain call...
102             if (context.State == StreamingContextStates.CrossAppDomain)
103             {
104                 // ...this new exception may get thrown.  It is logically a re-throw, but 
105                 //  physically a brand-new exception.  Since the stack trace is cleared 
106                 //  on a new exception, the "_remoteStackTraceString" is provided to 
107                 //  effectively import a stack trace from a "remote" exception.  So,
108                 //  move the _stackTraceString into the _remoteStackTraceString.  Note
109                 //  that if there is an existing _remoteStackTraceString, it will be 
110                 //  preserved at the head of the new string, so everything works as 
111                 //  expected.
112                 // Even if this exception is NOT thrown, things will still work as expected
113                 //  because the StackTrace property returns the concatenation of the
114                 //  _remoteStackTraceString and the _stackTraceString.
115                 _remoteStackTraceString = _remoteStackTraceString + _stackTraceString;
116                 _stackTraceString = null;
117             }
118         }
119
120
121         public virtual String Message
122         {
123             get
124             {
125                 if (_message == null)
126                 {
127                     if (_className == null)
128                     {
129                         _className = GetClassName();
130                     }
131                     return SR.Format(SR.Exception_WasThrown, _className);
132                 }
133                 else
134                 {
135                     return _message;
136                 }
137             }
138         }
139
140         public virtual IDictionary Data
141         {
142             get
143             {
144                 if (_data == null)
145                     if (IsImmutableAgileException(this))
146                         _data = new EmptyReadOnlyDictionaryInternal();
147                     else
148                         _data = new ListDictionaryInternal();
149
150                 return _data;
151             }
152         }
153
154         [MethodImplAttribute(MethodImplOptions.InternalCall)]
155         private static extern bool IsImmutableAgileException(Exception e);
156
157 #if FEATURE_COMINTEROP
158         //
159         // Exception requires anything to be added into Data dictionary is serializable
160         // This wrapper is made serializable to satisfy this requirement but does NOT serialize 
161         // the object and simply ignores it during serialization, because we only need 
162         // the exception instance in the app to hold the error object alive.
163         // Once the exception is serialized to debugger, debugger only needs the error reference string
164         //
165         [Serializable]
166         internal class __RestrictedErrorObject
167         {
168             // Hold the error object instance but don't serialize/deserialize it
169             [NonSerialized]
170             private object _realErrorObject;
171
172             internal __RestrictedErrorObject(object errorObject)
173             {
174                 _realErrorObject = errorObject;
175             }
176
177             public object RealErrorObject
178             {
179                 get
180                 {
181                     return _realErrorObject;
182                 }
183             }
184         }
185
186         // [FriendAccessAllowed]
187         internal void AddExceptionDataForRestrictedErrorInfo(
188             string restrictedError,
189             string restrictedErrorReference,
190             string restrictedCapabilitySid,
191             object restrictedErrorObject,
192             bool hasrestrictedLanguageErrorObject = false)
193         {
194             IDictionary dict = Data;
195             if (dict != null)
196             {
197                 dict.Add("RestrictedDescription", restrictedError);
198                 dict.Add("RestrictedErrorReference", restrictedErrorReference);
199                 dict.Add("RestrictedCapabilitySid", restrictedCapabilitySid);
200
201                 // Keep the error object alive so that user could retrieve error information
202                 // using Data["RestrictedErrorReference"]
203                 dict.Add("__RestrictedErrorObject", (restrictedErrorObject == null ? null : new __RestrictedErrorObject(restrictedErrorObject)));
204                 dict.Add("__HasRestrictedLanguageErrorObject", hasrestrictedLanguageErrorObject);
205             }
206         }
207
208         internal bool TryGetRestrictedLanguageErrorObject(out object restrictedErrorObject)
209         {
210             restrictedErrorObject = null;
211             if (Data != null && Data.Contains("__HasRestrictedLanguageErrorObject"))
212             {
213                 if (Data.Contains("__RestrictedErrorObject"))
214                 {
215                     __RestrictedErrorObject restrictedObject = Data["__RestrictedErrorObject"] as __RestrictedErrorObject;
216                     if (restrictedObject != null)
217                         restrictedErrorObject = restrictedObject.RealErrorObject;
218                 }
219                 return (bool)Data["__HasRestrictedLanguageErrorObject"];
220             }
221
222             return false;
223         }
224 #endif // FEATURE_COMINTEROP
225
226         private string GetClassName()
227         {
228             // Will include namespace but not full instantiation and assembly name.
229             if (_className == null)
230                 _className = GetType().ToString();
231
232             return _className;
233         }
234
235         // Retrieves the lowest exception (inner most) for the given Exception.
236         // This will traverse exceptions using the innerException property.
237         //
238         public virtual Exception GetBaseException()
239         {
240             Exception inner = InnerException;
241             Exception back = this;
242
243             while (inner != null)
244             {
245                 back = inner;
246                 inner = inner.InnerException;
247             }
248
249             return back;
250         }
251
252         // Returns the inner exception contained in this exception
253         // 
254         public Exception InnerException
255         {
256             get { return _innerException; }
257         }
258
259
260         [MethodImplAttribute(MethodImplOptions.InternalCall)]
261         static extern private IRuntimeMethodInfo GetMethodFromStackTrace(Object stackTrace);
262
263         private MethodBase GetExceptionMethodFromStackTrace()
264         {
265             IRuntimeMethodInfo method = GetMethodFromStackTrace(_stackTrace);
266
267             // Under certain race conditions when exceptions are re-used, this can be null
268             if (method == null)
269                 return null;
270
271             return RuntimeType.GetMethodBase(method);
272         }
273
274         public MethodBase TargetSite
275         {
276             get
277             {
278                 return GetTargetSiteInternal();
279             }
280         }
281
282
283         // this function is provided as a private helper to avoid the security demand
284         private MethodBase GetTargetSiteInternal()
285         {
286             if (_exceptionMethod != null)
287             {
288                 return _exceptionMethod;
289             }
290             if (_stackTrace == null)
291             {
292                 return null;
293             }
294             
295             _exceptionMethod = GetExceptionMethodFromStackTrace();
296             return _exceptionMethod;
297         }
298
299         // Returns the stack trace as a string.  If no stack trace is
300         // available, null is returned.
301         public virtual String StackTrace
302         {
303             get
304             {
305                 // By default attempt to include file and line number info
306                 return GetStackTrace(true);
307             }
308         }
309
310         // Computes and returns the stack trace as a string
311         // Attempts to get source file and line number information if needFileInfo
312         // is true.  Note that this requires FileIOPermission(PathDiscovery), and so
313         // will usually fail in CoreCLR.  To avoid the demand and resulting
314         // SecurityException we can explicitly not even try to get fileinfo.
315         private string GetStackTrace(bool needFileInfo)
316         {
317             string stackTraceString = _stackTraceString;
318             string remoteStackTraceString = _remoteStackTraceString;
319
320             // if no stack trace, try to get one
321             if (stackTraceString != null)
322             {
323                 return remoteStackTraceString + stackTraceString;
324             }
325             if (_stackTrace == null)
326             {
327                 return remoteStackTraceString;
328             }
329
330             // Obtain the stack trace string. Note that since Environment.GetStackTrace
331             // will add the path to the source file if the PDB is present and a demand
332             // for FileIOPermission(PathDiscovery) succeeds, we need to make sure we 
333             // don't store the stack trace string in the _stackTraceString member variable.
334             String tempStackTraceString = Environment.GetStackTrace(this, needFileInfo);
335             return remoteStackTraceString + tempStackTraceString;
336         }
337
338         // [FriendAccessAllowed]
339         internal void SetErrorCode(int hr)
340         {
341             HResult = hr;
342         }
343
344         // Sets the help link for this exception.
345         // This should be in a URL/URN form, such as:
346         // "file:///C:/Applications/Bazzal/help.html#ErrorNum42"
347         // Changed to be a read-write String and not return an exception
348         public virtual String HelpLink
349         {
350             get
351             {
352                 return _helpURL;
353             }
354             set
355             {
356                 _helpURL = value;
357             }
358         }
359
360         public virtual String Source
361         {
362             get
363             {
364                 if (_source == null)
365                 {
366                     StackTrace st = new StackTrace(this, true);
367                     if (st.FrameCount > 0)
368                     {
369                         StackFrame sf = st.GetFrame(0);
370                         MethodBase method = sf.GetMethod();
371
372                         Module module = method.Module;
373
374                         RuntimeModule rtModule = module as RuntimeModule;
375
376                         if (rtModule == null)
377                         {
378                             System.Reflection.Emit.ModuleBuilder moduleBuilder = module as System.Reflection.Emit.ModuleBuilder;
379                             if (moduleBuilder != null)
380                                 rtModule = moduleBuilder.InternalModule;
381                             else
382                                 throw new ArgumentException(SR.Argument_MustBeRuntimeReflectionObject);
383                         }
384
385                         _source = rtModule.GetRuntimeAssembly().GetSimpleName();
386                     }
387                 }
388
389                 return _source;
390             }
391             set { _source = value; }
392         }
393
394         public override String ToString()
395         {
396             return ToString(true, true);
397         }
398
399         private String ToString(bool needFileLineInfo, bool needMessage)
400         {
401             String message = (needMessage ? Message : null);
402             String s;
403
404             if (message == null || message.Length <= 0)
405             {
406                 s = GetClassName();
407             }
408             else
409             {
410                 s = GetClassName() + ": " + message;
411             }
412
413             if (_innerException != null)
414             {
415                 s = s + " ---> " + _innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine +
416                 "   " + SR.Exception_EndOfInnerExceptionStack;
417             }
418
419             string stackTrace = GetStackTrace(needFileLineInfo);
420             if (stackTrace != null)
421             {
422                 s += Environment.NewLine + stackTrace;
423             }
424
425             return s;
426         }
427
428         protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState
429         {
430             add { throw new PlatformNotSupportedException(SR.PlatformNotSupported_SecureBinarySerialization); }
431             remove { throw new PlatformNotSupportedException(SR.PlatformNotSupported_SecureBinarySerialization); }
432         }
433
434         public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
435         {
436             if (info == null)
437             {
438                 throw new ArgumentNullException(nameof(info));
439             }
440
441             String tempStackTraceString = _stackTraceString;
442
443             if (_stackTrace != null)
444             {
445                 if (tempStackTraceString == null)
446                 {
447                     tempStackTraceString = Environment.GetStackTrace(this, true);
448                 }
449                 if (_exceptionMethod == null)
450                 {
451                     _exceptionMethod = GetExceptionMethodFromStackTrace();
452                 }
453             }
454
455             if (_source == null)
456             {
457                 _source = Source; // Set the Source information correctly before serialization
458             }
459
460             info.AddValue("ClassName", GetClassName(), typeof(String)); // Do not rename (binary serialization)
461             info.AddValue("Message", _message, typeof(String)); // Do not rename (binary serialization)
462             info.AddValue("Data", _data, typeof(IDictionary)); // Do not rename (binary serialization)
463             info.AddValue("InnerException", _innerException, typeof(Exception)); // Do not rename (binary serialization)
464             info.AddValue("HelpURL", _helpURL, typeof(String)); // Do not rename (binary serialization)
465             info.AddValue("StackTraceString", tempStackTraceString, typeof(String)); // Do not rename (binary serialization)
466             info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(String)); // Do not rename (binary serialization)
467             info.AddValue("RemoteStackIndex", _remoteStackIndex, typeof(Int32)); // Do not rename (binary serialization)
468             info.AddValue("ExceptionMethod", null, typeof(String)); // Do not rename (binary serialization)
469             info.AddValue("HResult", HResult); // Do not rename (binary serialization)
470             info.AddValue("Source", _source, typeof(String)); // Do not rename (binary serialization)
471
472             // Serialize the Watson bucket details as well
473             info.AddValue("WatsonBuckets", _watsonBuckets, typeof(byte[])); // Do not rename (binary serialization)
474         }
475
476         // This method will clear the _stackTrace of the exception object upon deserialization
477         // to ensure that references from another AD/Process dont get accidentally used.
478         [OnDeserialized]
479         private void OnDeserialized(StreamingContext context)
480         {
481             _stackTrace = null;
482
483             // We wont serialize or deserialize the IP for Watson bucketing since
484             // we dont know where the deserialized object will be used in.
485             // Using it across process or an AppDomain could be invalid and result
486             // in AV in the runtime.
487             //
488             // Hence, we set it to zero when deserialization takes place. 
489             _ipForWatsonBuckets = UIntPtr.Zero;
490         }
491
492         // This is used by the runtime when re-throwing a managed exception.  It will
493         //  copy the stack trace to _remoteStackTraceString.
494         internal void InternalPreserveStackTrace()
495         {
496             string tmpStackTraceString;
497
498 #if FEATURE_APPX
499             if (AppDomain.IsAppXModel())
500             {
501                 // Call our internal GetStackTrace in AppX so we can parse the result should
502                 // we need to strip file/line info from it to make it PII-free. Calling the
503                 // public and overridable StackTrace getter here was probably not intended.
504                 tmpStackTraceString = GetStackTrace(true);
505
506                 // Make sure that the _source field is initialized if Source is not overriden.
507                 // We want it to contain the original faulting point.
508                 string source = Source;
509             }
510             else
511 #else // FEATURE_APPX
512             // Preinitialize _source on CoreSystem as well. The legacy behavior is not ideal and
513             // we keep it for back compat but we can afford to make the change on the Phone.
514             string source = Source;
515 #endif // FEATURE_APPX
516             {
517                 // Call the StackTrace getter in classic for compat.
518                 tmpStackTraceString = StackTrace;
519             }
520
521             if (tmpStackTraceString != null && tmpStackTraceString.Length > 0)
522             {
523                 _remoteStackTraceString = tmpStackTraceString + Environment.NewLine;
524             }
525
526             _stackTrace = null;
527             _stackTraceString = null;
528         }
529
530
531         // This is the object against which a lock will be taken
532         // when attempt to restore the EDI. Since its static, its possible
533         // that unrelated exception object restorations could get blocked
534         // for a small duration but that sounds reasonable considering
535         // such scenarios are going to be extremely rare, where timing
536         // matches precisely.
537         [OptionalField]
538         private static object s_EDILock = new object();
539
540         internal UIntPtr IPForWatsonBuckets
541         {
542             get
543             {
544                 return _ipForWatsonBuckets;
545             }
546         }
547
548         internal object WatsonBuckets
549         {
550             get
551             {
552                 return _watsonBuckets;
553             }
554         }
555
556         internal string RemoteStackTrace
557         {
558             get
559             {
560                 return _remoteStackTraceString;
561             }
562         }
563
564         [MethodImplAttribute(MethodImplOptions.InternalCall)]
565         private static extern void PrepareForForeignExceptionRaise();
566
567         [MethodImplAttribute(MethodImplOptions.InternalCall)]
568         private static extern void GetStackTracesDeepCopy(Exception exception, out object currentStackTrace, out object dynamicMethodArray);
569
570         [MethodImplAttribute(MethodImplOptions.InternalCall)]
571         internal static extern void SaveStackTracesFromDeepCopy(Exception exception, object currentStackTrace, object dynamicMethodArray);
572
573         [MethodImplAttribute(MethodImplOptions.InternalCall)]
574         private static extern object CopyStackTrace(object currentStackTrace);
575
576         [MethodImplAttribute(MethodImplOptions.InternalCall)]
577         private static extern object CopyDynamicMethods(object currentDynamicMethods);
578
579         internal object DeepCopyStackTrace(object currentStackTrace)
580         {
581             if (currentStackTrace != null)
582             {
583                 return CopyStackTrace(currentStackTrace);
584             }
585             else
586             {
587                 return null;
588             }
589         }
590
591         internal object DeepCopyDynamicMethods(object currentDynamicMethods)
592         {
593             if (currentDynamicMethods != null)
594             {
595                 return CopyDynamicMethods(currentDynamicMethods);
596             }
597             else
598             {
599                 return null;
600             }
601         }
602
603         internal void GetStackTracesDeepCopy(out object currentStackTrace, out object dynamicMethodArray)
604         {
605             GetStackTracesDeepCopy(this, out currentStackTrace, out dynamicMethodArray);
606         }
607
608         // This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the
609         // exception, just before the exception is "rethrown".
610         internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
611         {
612             bool fCanProcessException = !(IsImmutableAgileException(this));
613             // Restore only for non-preallocated exceptions
614             if (fCanProcessException)
615             {
616                 // Take a lock to ensure only one thread can restore the details
617                 // at a time against this exception object that could have
618                 // multiple ExceptionDispatchInfo instances associated with it.
619                 //
620                 // We do this inside a finally clause to ensure ThreadAbort cannot
621                 // be injected while we have taken the lock. This is to prevent
622                 // unrelated exception restorations from getting blocked due to TAE.
623                 try { }
624                 finally
625                 {
626                     // When restoring back the fields, we again create a copy and set reference to them
627                     // in the exception object. This will ensure that when this exception is thrown and these
628                     // fields are modified, then EDI's references remain intact.
629                     //
630                     // Since deep copying can throw on OOM, try to get the copies
631                     // outside the lock.
632                     object _stackTraceCopy = (exceptionDispatchInfo.BinaryStackTraceArray == null) ? null : DeepCopyStackTrace(exceptionDispatchInfo.BinaryStackTraceArray);
633                     object _dynamicMethodsCopy = (exceptionDispatchInfo.DynamicMethodArray == null) ? null : DeepCopyDynamicMethods(exceptionDispatchInfo.DynamicMethodArray);
634
635                     // Finally, restore the information. 
636                     //
637                     // Since EDI can be created at various points during exception dispatch (e.g. at various frames on the stack) for the same exception instance,
638                     // they can have different data to be restored. Thus, to ensure atomicity of restoration from each EDI, perform the restore under a lock.
639                     lock (Exception.s_EDILock)
640                     {
641                         _watsonBuckets = exceptionDispatchInfo.WatsonBuckets;
642                         _ipForWatsonBuckets = exceptionDispatchInfo.IPForWatsonBuckets;
643                         _remoteStackTraceString = exceptionDispatchInfo.RemoteStackTrace;
644                         SaveStackTracesFromDeepCopy(this, _stackTraceCopy, _dynamicMethodsCopy);
645                     }
646                     _stackTraceString = null;
647
648                     // Marks the TES state to indicate we have restored foreign exception
649                     // dispatch information.
650                     Exception.PrepareForForeignExceptionRaise();
651                 }
652             }
653         }
654
655         private String _className;  //Needed for serialization.  
656         private MethodBase _exceptionMethod;  //Needed for serialization.  
657         internal String _message;
658         private IDictionary _data;
659         private Exception _innerException;
660         private String _helpURL;
661         private Object _stackTrace;
662         [OptionalField] // This isnt present in pre-V4 exception objects that would be serialized.
663         private Object _watsonBuckets;
664         private String _stackTraceString; //Needed for serialization.  
665         private String _remoteStackTraceString;
666         private int _remoteStackIndex;
667 #pragma warning disable 414  // Field is not used from managed.        
668         // _dynamicMethods is an array of System.Resolver objects, used to keep
669         // DynamicMethodDescs alive for the lifetime of the exception. We do this because
670         // the _stackTrace field holds MethodDescs, and a DynamicMethodDesc can be destroyed
671         // unless a System.Resolver object roots it.
672         private Object _dynamicMethods;
673 #pragma warning restore 414
674
675         // @MANAGED: HResult is used from within the EE!  Rename with care - check VM directory
676         internal int _HResult;     // HResult
677
678         public int HResult
679         {
680             get
681             {
682                 return _HResult;
683             }
684             protected set
685             {
686                 _HResult = value;
687             }
688         }
689
690         private String _source;         // Mainly used by VB. 
691         // WARNING: Don't delete/rename _xptrs and _xcode - used by functions
692         // on Marshal class.  Native functions are in COMUtilNative.cpp & AppDomain
693         private IntPtr _xptrs;             // Internal EE stuff 
694 #pragma warning disable 414  // Field is not used from managed.
695         private int _xcode;             // Internal EE stuff 
696 #pragma warning restore 414
697         [OptionalField]
698         private UIntPtr _ipForWatsonBuckets; // Used to persist the IP for Watson Bucketing
699
700
701         // See src\inc\corexcep.h's EXCEPTION_COMPLUS definition:
702         private const int _COMPlusExceptionCode = unchecked((int)0xe0434352);   // Win32 exception code for COM+ exceptions
703
704         // InternalToString is called by the runtime to get the exception text 
705         // and create a corresponding CrossAppDomainMarshaledException
706         internal virtual String InternalToString()
707         {
708             // Get the current stack trace string. 
709             return ToString(true, true);
710         }
711
712         // this method is required so Object.GetType is not made virtual by the compiler
713         // _Exception.GetType()
714         public new Type GetType()
715         {
716             return base.GetType();
717         }
718
719         internal bool IsTransient
720         {
721             get
722             {
723                 return nIsTransient(_HResult);
724             }
725         }
726
727         [MethodImplAttribute(MethodImplOptions.InternalCall)]
728         private extern static bool nIsTransient(int hr);
729
730
731         // This piece of infrastructure exists to help avoid deadlocks 
732         // between parts of mscorlib that might throw an exception while 
733         // holding a lock that are also used by mscorlib's ResourceManager
734         // instance.  As a special case of code that may throw while holding
735         // a lock, we also need to fix our asynchronous exceptions to use
736         // Win32 resources as well (assuming we ever call a managed 
737         // constructor on instances of them).  We should grow this set of
738         // exception messages as we discover problems, then move the resources
739         // involved to native code.
740         internal enum ExceptionMessageKind
741         {
742             ThreadAbort = 1,
743             ThreadInterrupted = 2,
744             OutOfMemory = 3
745         }
746
747         // See comment on ExceptionMessageKind
748         internal static String GetMessageFromNativeResources(ExceptionMessageKind kind)
749         {
750             string retMesg = null;
751             GetMessageFromNativeResources(kind, JitHelpers.GetStringHandleOnStack(ref retMesg));
752             return retMesg;
753         }
754
755         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
756         private static extern void GetMessageFromNativeResources(ExceptionMessageKind kind, StringHandleOnStack retMesg);
757     }
758
759     //--------------------------------------------------------------------------
760     // Telesto: Telesto doesn't support appdomain marshaling of objects so
761     // managed exceptions that leak across appdomain boundaries are flatted to
762     // its ToString() output and rethrown as an CrossAppDomainMarshaledException.
763     // The Message field is set to the ToString() output of the original exception.
764     //--------------------------------------------------------------------------
765
766     internal sealed class CrossAppDomainMarshaledException : SystemException
767     {
768         public CrossAppDomainMarshaledException(String message, int errorCode)
769             : base(message)
770         {
771             HResult = errorCode;
772         }
773
774         // Normally, only Telesto's UEF will see these exceptions.
775         // This override prints out the original Exception's ToString()
776         // output and hides the fact that it is wrapped inside another excepton.
777         internal override String InternalToString()
778         {
779             return Message;
780         }
781     }
782 }
783