The Labs \ Source Viewer \ SSCLI \ System.Configuration \ MBResult

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Debug.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Configuration
  16. {
  17.     using Microsoft.Win32;
  18.     using Microsoft.Win32.SafeHandles;
  19.     using System;
  20.     using System.Collections;
  21.     using System.Collections.Generic;
  22.     using System.Collections.ObjectModel;
  23.     using System.Globalization;
  24.     using System.Reflection;
  25.     using System.Runtime.ConstrainedExecution;
  26.     using System.Runtime.InteropServices;
  27.     using System.Security;
  28.     using System.Security.Permissions;
  29.     using System.Threading;
  30.    
  31.     static internal class Debug
  32.     {
  33.        
  34.         internal const string TAG_INTERNAL = "Internal";
  35.         internal const string TAG_EXTERNAL = "External";
  36.         internal const string TAG_ALL = "*";
  37.        
  38.         internal const string DATE_FORMAT = "yyyy/MM/dd HH:mm:ss.ffff";
  39.         internal const string TIME_FORMAT = "HH:mm:ss:ffff";
  40.        
  41.         #if DBG
  42.         [System.Security.SuppressUnmanagedCodeSecurityAttribute()]
  43.         private static class NativeMethods
  44.         {
  45.             [DllImport("kernel32.dll")]
  46.             static internal extern int GetCurrentProcessId();
  47.            
  48.             [DllImport("kernel32.dll")]
  49.             static internal extern int GetCurrentThreadId();
  50.            
  51.             [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  52.             static internal extern IntPtr GetCurrentProcess();
  53.            
  54.             [DllImport("kernel32.dll", SetLastError = true)]
  55.             static internal extern bool TerminateProcess(HandleRef processHandle, int exitCode);
  56.            
  57.             [DllImport("kernel32.dll", CharSet = CharSet.Auto, BestFitMapping = false)]
  58.             static internal extern void OutputDebugString(string message);
  59.            
  60.             internal const int PM_NOREMOVE = 0;
  61.             internal const int PM_REMOVE = 1;
  62.            
  63.             [StructLayout(LayoutKind.Sequential)]
  64.             internal struct MSG
  65.             {
  66.                 internal IntPtr hwnd;
  67.                 internal int message;
  68.                 internal IntPtr wParam;
  69.                 internal IntPtr lParam;
  70.                 internal int time;
  71.                 internal int pt_x;
  72.                 internal int pt_y;
  73.             }
  74.            
  75.             [DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
  76.             static internal extern bool PeekMessage(            [In(), Out()]
  77. ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove);
  78.            
  79.             internal const int MB_OK = 0, MB_OKCANCEL = 1, MB_ABORTRETRYIGNORE = 2, MB_YESNOCANCEL = 3, MB_YESNO = 4, MB_RETRYCANCEL = 5, MB_ICONHAND = 16, MB_ICONQUESTION = 32, MB_ICONEXCLAMATION = 48, MB_ICONASTERISK = 64,
  80.             MB_USERICON = 128, MB_ICONWARNING = 48, MB_ICONERROR = 16, MB_ICONINFORMATION = 64, MB_DEFBUTTON1 = 0, MB_DEFBUTTON2 = 256, MB_DEFBUTTON3 = 512, MB_DEFBUTTON4 = 768, MB_APPLMODAL = 0, MB_SYSTEMMODAL = 4096,
  81.             MB_TASKMODAL = 8192, MB_HELP = 16384, MB_NOFOCUS = 32768, MB_SETFOREGROUND = 65536, MB_DEFAULT_DESKTOP_ONLY = 131072, MB_TOPMOST = 262144, MB_RIGHT = 524288, MB_RTLREADING = 1048576, MB_SERVICE_NOTIFICATION = 2097152, MB_SERVICE_NOTIFICATION_NT3X = 262144,
  82.             MB_TYPEMASK = 15, MB_ICONMASK = 240, MB_DEFMASK = 3840, MB_MODEMASK = 12288, MB_MISCMASK = 49152;
  83.            
  84.             internal const int IDOK = 1, IDCANCEL = 2, IDABORT = 3, IDRETRY = 4, IDIGNORE = 5, IDYES = 6, IDNO = 7, IDCLOSE = 8, IDHELP = 9;
  85.            
  86.            
  87.             [DllImport("user32.dll", CharSet = CharSet.Auto, BestFitMapping = false)]
  88.             static internal extern int MessageBox(HandleRef hWnd, string text, string caption, int type);
  89.            
  90.             static internal readonly IntPtr HKEY_LOCAL_MACHINE = unchecked((IntPtr)(int)2147483650u);
  91.            
  92.             internal const int READ_CONTROL = 131072;
  93.             internal const int STANDARD_RIGHTS_READ = READ_CONTROL;
  94.            
  95.             internal const int SYNCHRONIZE = 1048576;
  96.            
  97.             internal const int KEY_QUERY_VALUE = 1;
  98.             internal const int KEY_ENUMERATE_SUB_KEYS = 8;
  99.             internal const int KEY_NOTIFY = 16;
  100.            
  101.            
  102.             internal const int KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE));
  103.            
  104.             internal const int REG_NOTIFY_CHANGE_NAME = 1;
  105.             internal const int REG_NOTIFY_CHANGE_LAST_SET = 4;
  106.            
  107.            
  108.             [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false, SetLastError = true)]
  109.             static internal extern int RegOpenKeyEx(IntPtr hKey, string lpSubKey, int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
  110.            
  111.             [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  112.             static internal extern int RegNotifyChangeKeyValue(SafeRegistryHandle hKey, bool watchSubTree, uint notifyFilter, SafeWaitHandle regEvent, bool async);
  113.         }
  114.        
  115.         private class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
  116.         {
  117.            
  118.             // Note: Officially -1 is the recommended invalid handle value for
  119.             // registry keys, but we'll also get back 0 as an invalid handle from
  120.             // RegOpenKeyEx.
  121.            
  122.             [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  123.             internal SafeRegistryHandle() : base(true)
  124.             {
  125.             }
  126.            
  127.             [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
  128.             internal SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle)
  129.             {
  130.                 SetHandle(preexistingHandle);
  131.             }
  132.            
  133.             [DllImport("advapi32.dll"), SuppressUnmanagedCodeSecurity(), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  134.             private static extern int RegCloseKey(IntPtr hKey);
  135.            
  136.             protected override bool ReleaseHandle()
  137.             {
  138.                 // Returns a Win32 error code, 0 for success
  139.                 int r = RegCloseKey(handle);
  140.                 return r == 0;
  141.             }
  142.         }
  143.        
  144.         private enum TagValue
  145.         {
  146.             Disabled = 0,
  147.             Enabled = 1,
  148.             Break = 2,
  149.            
  150.             Min = Disabled,
  151.             Max = Break
  152.         }
  153.        
  154.         private const string TAG_ASSERT = "Assert";
  155.         private const string TAG_ASSERT_BREAK = "AssertBreak";
  156.        
  157.         private const string TAG_DEBUG_VERBOSE = "DebugVerbose";
  158.         private const string TAG_DEBUG_MONITOR = "DebugMonitor";
  159.         private const string TAG_DEBUG_PREFIX = "DebugPrefix";
  160.         private const string TAG_DEBUG_THREAD_PREFIX = "DebugThreadPrefix";
  161.        
  162.         private const string PRODUCT = "Microsoft .NET Framework";
  163.         private const string COMPONENT = "System.Configuration";
  164.        
  165.         private static string s_regKeyName = "Software\\Microsoft\\ASP.NET\\Debug";
  166.         private static string s_listenKeyName = "Software\\Microsoft";
  167.        
  168.         private static bool s_assert;
  169.         private static bool s_assertBreak;
  170.        
  171.         private static bool s_includePrefix;
  172.         private static bool s_includeThreadPrefix;
  173.         private static bool s_monitor;
  174.        
  175.         private static object s_lock;
  176.         private static volatile bool s_inited;
  177.         private static ReadOnlyCollection<Tag> s_tagDefaults;
  178.         private static List<Tag> s_tags;
  179.        
  180.         private static AutoResetEvent s_notifyEvent;
  181.         private static RegisteredWaitHandle s_waitHandle;
  182.         private static SafeRegistryHandle s_regHandle;
  183.         private static bool s_stopMonitoring;
  184.        
  185.         private static Hashtable s_tableAlwaysValidate;
  186.         private static Type[] s_DumpArgs;
  187.         private static Type[] s_ValidateArgs;
  188.        
  189.        
  190.         private class Tag
  191.         {
  192.             string _name;
  193.             TagValue _value;
  194.             int _prefixLength;
  195.            
  196.             internal Tag(string name, TagValue value)
  197.             {
  198.                 _name = name;
  199.                 _value = value;
  200.                
  201.                 if (_name[_name.Length - 1] == '*') {
  202.                     _prefixLength = _name.Length - 1;
  203.                 }
  204.                 else {
  205.                     _prefixLength = -1;
  206.                 }
  207.             }
  208.            
  209.             internal string Name {
  210.                 get { return _name; }
  211.             }
  212.            
  213.             internal TagValue Value {
  214.                 get { return _value; }
  215.             }
  216.            
  217.             internal int PrefixLength {
  218.                 get { return _prefixLength; }
  219.             }
  220.         }
  221.        
  222.         static Debug()
  223.         {
  224.             s_lock = new object();
  225.         }
  226.        
  227.         private static void EnsureInit()
  228.         {
  229.             bool continueInit = false;
  230.            
  231.             if (!s_inited) {
  232.                 lock (s_lock) {
  233.                     if (!s_inited) {
  234.                         s_tableAlwaysValidate = new Hashtable();
  235.                         s_DumpArgs = new Type[1] {typeof(string)};
  236.                         s_ValidateArgs = new Type[0];
  237.                        
  238.                         List<Tag> tagDefaults = new List<Tag>();
  239.                         tagDefaults.Add(new Tag(TAG_ALL, TagValue.Disabled));
  240.                         tagDefaults.Add(new Tag(TAG_INTERNAL, TagValue.Enabled));
  241.                         tagDefaults.Add(new Tag(TAG_EXTERNAL, TagValue.Enabled));
  242.                         tagDefaults.Add(new Tag(TAG_ASSERT, TagValue.Break));
  243.                         tagDefaults.Add(new Tag(TAG_ASSERT_BREAK, TagValue.Disabled));
  244.                         tagDefaults.Add(new Tag(TAG_DEBUG_VERBOSE, TagValue.Enabled));
  245.                         tagDefaults.Add(new Tag(TAG_DEBUG_MONITOR, TagValue.Enabled));
  246.                         tagDefaults.Add(new Tag(TAG_DEBUG_PREFIX, TagValue.Enabled));
  247.                         tagDefaults.Add(new Tag(TAG_DEBUG_THREAD_PREFIX, TagValue.Enabled));
  248.                        
  249.                         s_tagDefaults = tagDefaults.AsReadOnly();
  250.                         s_tags = new List<Tag>(s_tagDefaults);
  251.                         GetBuiltinTagValues();
  252.                        
  253.                         continueInit = true;
  254.                         s_inited = true;
  255.                     }
  256.                 }
  257.             }
  258.            
  259.             // Work to do outside the init lock.
  260.             if (continueInit) {
  261.                 ReadTagsFromRegistry();
  262.                 Trace(TAG_DEBUG_VERBOSE, "Debugging package initialized");
  263.                
  264.                 // Need to read tags before starting to monitor in order to get TAG_DEBUG_MONITOR
  265.                 StartRegistryMonitor();
  266.             }
  267.         }
  268.        
  269.         private static bool StringEqualsIgnoreCase(string s1, string s2)
  270.         {
  271.             return StringComparer.OrdinalIgnoreCase.Equals(s1, s2);
  272.         }
  273.        
  274.        
  275.         private static void GetBuiltinTagValues()
  276.         {
  277.             // Use GetTagValue instead of IsTagEnabled because it does not call EnsureInit
  278.             // and potentially recurse.
  279.             s_assert = (GetTagValue(TAG_ASSERT) != TagValue.Disabled);
  280.             s_assertBreak = (GetTagValue(TAG_ASSERT_BREAK) != TagValue.Disabled);
  281.             s_includePrefix = (GetTagValue(TAG_DEBUG_PREFIX) != TagValue.Disabled);
  282.             s_includeThreadPrefix = (GetTagValue(TAG_DEBUG_THREAD_PREFIX) != TagValue.Disabled);
  283.             s_monitor = (GetTagValue(TAG_DEBUG_MONITOR) != TagValue.Disabled);
  284.         }
  285.        
  286.         private static void ReadTagsFromRegistry()
  287.         {
  288.             lock (s_lock) {
  289.                 try {
  290.                     List<Tag> tags = new List<Tag>(s_tagDefaults);
  291.                    
  292.                 }
  293.                 catch {
  294.                     s_tags = new List<Tag>(s_tagDefaults);
  295.                 }
  296.             }
  297.         }
  298.        
  299.         private static void StartRegistryMonitor()
  300.         {
  301.             if (!s_monitor) {
  302.                 Trace(TAG_DEBUG_VERBOSE, "WARNING: Registry monitoring disabled, changes during process execution will not be recognized.");
  303.                 return;
  304.             }
  305.            
  306.             Trace(TAG_DEBUG_VERBOSE, "Monitoring registry key " + s_listenKeyName + " for changes.");
  307.            
  308.             // Event used to notify of changes.
  309.             s_notifyEvent = new AutoResetEvent(false);
  310.            
  311.             // Register a wait on the event.
  312.             s_waitHandle = ThreadPool.RegisterWaitForSingleObject(s_notifyEvent, OnRegChangeKeyValue, null, -1, false);
  313.            
  314.             // Monitor the registry.
  315.             MonitorRegistryForOneChange();
  316.         }
  317.        
  318.         private static void StopRegistryMonitor()
  319.         {
  320.             // Cleanup allocated handles
  321.             s_stopMonitoring = true;
  322.            
  323.             if (s_regHandle != null) {
  324.                 s_regHandle.Close();
  325.                 s_regHandle = null;
  326.             }
  327.            
  328.             if (s_waitHandle != null) {
  329.                 s_waitHandle.Unregister(s_notifyEvent);
  330.                 s_waitHandle = null;
  331.             }
  332.            
  333.             if (s_notifyEvent != null) {
  334.                 s_notifyEvent.Close();
  335.                 s_notifyEvent = null;
  336.             }
  337.            
  338.             Trace(TAG_DEBUG_VERBOSE, "Registry monitoring stopped.");
  339.         }
  340.        
  341.         public static void OnRegChangeKeyValue(object state, bool timedOut)
  342.         {
  343.             if (!s_stopMonitoring) {
  344.                 if (timedOut) {
  345.                     StopRegistryMonitor();
  346.                 }
  347.                 else {
  348.                     // Monitor again
  349.                     MonitorRegistryForOneChange();
  350.                    
  351.                     // Once we're monitoring, read the changes to the registry.
  352.                     // We have to do this after we start monitoring in order
  353.                     // to catch all changes to the registry.
  354.                     ReadTagsFromRegistry();
  355.                 }
  356.             }
  357.         }
  358.        
  359.         private static void MonitorRegistryForOneChange()
  360.         {
  361.             // Close the open reg handle
  362.             if (s_regHandle != null) {
  363.                 s_regHandle.Close();
  364.                 s_regHandle = null;
  365.             }
  366.            
  367.             // Open the reg key
  368.             int result = NativeMethods.RegOpenKeyEx(NativeMethods.HKEY_LOCAL_MACHINE, s_listenKeyName, 0, NativeMethods.KEY_READ, out s_regHandle);
  369.             if (result != 0) {
  370.                 StopRegistryMonitor();
  371.                 return;
  372.             }
  373.            
  374.             // Listen for changes.
  375.             result = NativeMethods.RegNotifyChangeKeyValue(s_regHandle, true, NativeMethods.REG_NOTIFY_CHANGE_NAME | NativeMethods.REG_NOTIFY_CHANGE_LAST_SET, s_notifyEvent.SafeWaitHandle, true);
  376.            
  377.             if (result != 0) {
  378.                 StopRegistryMonitor();
  379.             }
  380.         }
  381.        
  382.         private static Tag FindMatchingTag(string name, bool exact)
  383.         {
  384.             List<Tag> tags = s_tags;
  385.            
  386.             // Look for exact match first
  387.             foreach (Tag tag in tags) {
  388.                 if (StringEqualsIgnoreCase(name, tag.Name)) {
  389.                     return tag;
  390.                 }
  391.             }
  392.            
  393.             if (exact) {
  394.                 return null;
  395.             }
  396.            
  397.             Tag longestTag = null;
  398.             int longestPrefix = -1;
  399.             foreach (Tag tag in tags) {
  400.                 if (tag.PrefixLength > longestPrefix && 0 == string.Compare(name, 0, tag.Name, 0, tag.PrefixLength, StringComparison.OrdinalIgnoreCase)) {
  401.                    
  402.                     longestTag = tag;
  403.                     longestPrefix = tag.PrefixLength;
  404.                 }
  405.             }
  406.            
  407.             return longestTag;
  408.         }
  409.        
  410.         private static TagValue GetTagValue(string name)
  411.         {
  412.             Tag tag = FindMatchingTag(name, false);
  413.             if (tag != null) {
  414.                 return tag.Value;
  415.             }
  416.             else {
  417.                 return TagValue.Disabled;
  418.             }
  419.         }
  420.        
  421.         private static bool TraceBreak(string tagName, string message, Exception e, bool includePrefix)
  422.         {
  423.             EnsureInit();
  424.            
  425.             TagValue tagValue = GetTagValue(tagName);
  426.             if (tagValue == TagValue.Disabled) {
  427.                 return false;
  428.             }
  429.            
  430.             bool isAssert = object.ReferenceEquals(tagName, TAG_ASSERT);
  431.             if (isAssert) {
  432.                 tagName = "";
  433.             }
  434.            
  435.             string exceptionMessage = null;
  436.             if (e != null) {
  437.                 string errorCode = null;
  438.                 if (e is ExternalException) {
  439.                     errorCode = "_hr=0x" + ((ExternalException)e).ErrorCode.ToString("x", CultureInfo.InvariantCulture);
  440.                 }
  441.                
  442.                 // Use e.ToString() in order to get inner exception
  443.                 if (errorCode != null) {
  444.                     exceptionMessage = "Exception " + e.ToString() + "\n" + errorCode;
  445.                 }
  446.                 else {
  447.                     exceptionMessage = "Exception " + e.ToString();
  448.                 }
  449.             }
  450.            
  451.             if (string.IsNullOrEmpty(message) & exceptionMessage != null) {
  452.                 message = exceptionMessage;
  453.                 exceptionMessage = null;
  454.             }
  455.            
  456.             string traceFormat;
  457.             int idThread = 0;
  458.             int idProcess = 0;
  459.            
  460.             if (!includePrefix || !s_includePrefix) {
  461.                 traceFormat = "{4}\n{5}";
  462.             }
  463.             else {
  464.                 if (s_includeThreadPrefix) {
  465.                     idThread = NativeMethods.GetCurrentThreadId();
  466.                     idProcess = NativeMethods.GetCurrentProcessId();
  467.                     traceFormat = "[0x{0:x}.{1:x} {2} {3}] {4}\n{5}";
  468.                 }
  469.                 else {
  470.                     traceFormat = "[{2} {3}] {4}\n{5}";
  471.                 }
  472.             }
  473.            
  474.             string suffix = "";
  475.             if (exceptionMessage != null) {
  476.                 suffix += exceptionMessage + "\n";
  477.             }
  478.            
  479.             bool doBreak = (tagValue == TagValue.Break);
  480.             if (doBreak && !isAssert) {
  481.                 suffix += "Breaking into debugger...\n";
  482.             }
  483.            
  484.             string traceMessage = string.Format(CultureInfo.InvariantCulture, traceFormat, idProcess, idThread, COMPONENT, tagName, message, suffix);
  485.            
  486.             NativeMethods.OutputDebugString(traceMessage);
  487.            
  488.             return doBreak;
  489.         }
  490.        
  491.         private class MBResult
  492.         {
  493.             internal int Result;
  494.         }
  495.        
  496.         static bool DoAssert(string message)
  497.         {
  498.             if (!s_assert) {
  499.                 return false;
  500.             }
  501.            
  502.             // Skip 2 frames - one for this function, one for
  503.             // the public Assert function that called this function.
  504.             System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(2, true);
  505.             System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(2, true);
  506.            
  507.             string fileName = frame.GetFileName();
  508.             int lineNumber = frame.GetFileLineNumber();
  509.            
  510.             string traceFormat;
  511.             if (!string.IsNullOrEmpty(fileName)) {
  512.                 traceFormat = "ASSERTION FAILED: {0}\nFile: {1}:{2}\nStack trace:\n{3}";
  513.             }
  514.             else {
  515.                 traceFormat = "ASSERTION FAILED: {0}\nStack trace:\n{3}";
  516.             }
  517.            
  518.             string traceMessage = string.Format(CultureInfo.InvariantCulture, traceFormat, message, fileName, lineNumber, trace.ToString());
  519.            
  520.             if (!TraceBreak(TAG_ASSERT, traceMessage, null, true)) {
  521.                 // If the value of "Assert" is not TagValue.Break, then don't even ask user.
  522.                 return false;
  523.             }
  524.            
  525.             if (s_assertBreak) {
  526.                 // If "AssertBreak" is enabled, then always break.
  527.                 return true;
  528.             }
  529.            
  530.             string dialogFormat;
  531.             if (!string.IsNullOrEmpty(fileName)) {
  532.                 dialogFormat = "Failed expression: {0}\r\nFile: {1}:{2}\r\nComponent: {3}\r\nPID={4} TID={5}\r\nStack trace:\r\n{6}\r\n\r\nA=Exit process R=Debug I=Continue";
  533.             }
  534.             else {
  535.                 dialogFormat = "Failed expression: {0}\r\n(no file information available)\r\nComponent: {3}\r\nPID={4} TID={5}\r\nStack trace:\r\n{6}\r\n\r\nA=Exit process R=Debug I=Continue";
  536.             }
  537.            
  538.             string dialogMessage = string.Format(CultureInfo.InvariantCulture, dialogFormat, message, fileName, lineNumber, COMPONENT, NativeMethods.GetCurrentProcessId(), NativeMethods.GetCurrentThreadId(), trace.ToString());
  539.            
  540.             MBResult mbResult = new MBResult();
  541.            
  542.             Thread thread = new Thread(delegate()
  543.             {
  544.                 for (int i = 0; i < 100; i++) {
  545.                     NativeMethods.MSG msg = new NativeMethods.MSG();
  546.                     NativeMethods.PeekMessage(ref msg, new HandleRef(mbResult, IntPtr.Zero), 0, 0, NativeMethods.PM_REMOVE);
  547.                 }
  548.                
  549.                 mbResult.Result = NativeMethods.MessageBox(new HandleRef(mbResult, IntPtr.Zero), dialogMessage, PRODUCT + " Assertion", NativeMethods.MB_SERVICE_NOTIFICATION | NativeMethods.MB_TOPMOST | NativeMethods.MB_ABORTRETRYIGNORE | NativeMethods.MB_ICONEXCLAMATION);
  550.             }
  551. );
  552.            
  553.             thread.Start();
  554.             thread.Join();
  555.            
  556.             if (mbResult.Result == NativeMethods.IDABORT) {
  557.                 IntPtr currentProcess = NativeMethods.GetCurrentProcess();
  558.                 NativeMethods.TerminateProcess(new HandleRef(mbResult, currentProcess), 1);
  559.             }
  560.            
  561.             return mbResult.Result == NativeMethods.IDRETRY;
  562.         }
  563.         #endif
  564.        
  565.         //
  566.         // Sends the message to the debugger if the tag is enabled.
  567.         // Also breaks into the debugger the value of the tag is 2 (TagValue.Break).
  568.         //
  569.         [System.Diagnostics.Conditional("DBG")]
  570.         static internal void Trace(string tagName, string message)
  571.         {
  572.             #if DBG
  573.             if (TraceBreak(tagName, message, null, true)) {
  574.                 Break();
  575.             }
  576.             #endif
  577.         }
  578.        
  579.         //
  580.         // Sends the message to the debugger if the tag is enabled.
  581.         // Also breaks into the debugger the value of the tag is 2 (TagValue.Break).
  582.         //
  583.         [System.Diagnostics.Conditional("DBG")]
  584.         static internal void Trace(string tagName, string message, bool includePrefix)
  585.         {
  586.             #if DBG
  587.             if (TraceBreak(tagName, message, null, includePrefix)) {
  588.                 Break();
  589.             }
  590.             #endif
  591.         }
  592.        
  593.         //
  594.         // Sends the message to the debugger if the tag is enabled.
  595.         // Also breaks into the debugger the value of the tag is 2 (TagValue.Break).
  596.         //
  597.         [System.Diagnostics.Conditional("DBG")]
  598.         static internal void Trace(string tagName, string message, Exception e)
  599.         {
  600.             #if DBG
  601.             if (TraceBreak(tagName, message, e, true)) {
  602.                 Break();
  603.             }
  604.             #endif
  605.         }
  606.        
  607.         //
  608.         // Sends the message to the debugger if the tag is enabled.
  609.         // Also breaks into the debugger the value of the tag is 2 (TagValue.Break).
  610.         //
  611.         [System.Diagnostics.Conditional("DBG")]
  612.         static internal void Trace(string tagName, Exception e)
  613.         {
  614.             #if DBG
  615.             if (TraceBreak(tagName, null, e, true)) {
  616.                 Break();
  617.             }
  618.             #endif
  619.         }
  620.        
  621.         //
  622.         // Sends the message to the debugger if the tag is enabled.
  623.         // Also breaks into the debugger the value of the tag is 2 (TagValue.Break).
  624.         //
  625.         [System.Diagnostics.Conditional("DBG")]
  626.         static internal void Trace(string tagName, string message, Exception e, bool includePrefix)
  627.         {
  628.             #if DBG
  629.             if (TraceBreak(tagName, message, e, includePrefix)) {
  630.                 Break();
  631.             }
  632.             #endif
  633.         }
  634.        
  635.         #if DBG
  636.         #endif
  637.        
  638.        
  639.        
  640.         //
  641.         // If the assertion is false and the 'Assert' tag is enabled:
  642.         // * Send a message to the debugger.
  643.         // * If the 'AssertBreak' tag is enabled, immediately break into the debugger
  644.         // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore
  645.         //
  646.         [System.Diagnostics.Conditional("DBG")]
  647.         static internal void Assert(bool assertion, string message)
  648.         {
  649.             #if DBG
  650.             EnsureInit();
  651.             if (assertion == false) {
  652.                 if (DoAssert(message)) {
  653.                     Break();
  654.                 }
  655.             }
  656.             #endif
  657.         }
  658.        
  659.        
  660.         //
  661.         // If the assertion is false and the 'Assert' tag is enabled:
  662.         // * Send a message to the debugger.
  663.         // * If the 'AssertBreak' tag is enabled, immediately break into the debugger
  664.         // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore
  665.         //
  666.         [System.Diagnostics.Conditional("DBG")]
  667.         static internal void Assert(bool assertion)
  668.         {
  669.             #if DBG
  670.             EnsureInit();
  671.             if (assertion == false) {
  672.                 if (DoAssert(null)) {
  673.                     Break();
  674.                 }
  675.             }
  676.             #endif
  677.         }
  678.        
  679.         //
  680.         // Like Assert, but the assertion is always considered to be false.
  681.         //
  682.         [System.Diagnostics.Conditional("DBG")]
  683.         static internal void Fail(string message)
  684.         {
  685.             #if DBG
  686.             Assert(false, message);
  687.             #endif
  688.         }
  689.        
  690.         //
  691.         // Returns true if the tag is enabled, false otherwise.
  692.         // Note that the tag needn't be an exact match.
  693.         //
  694.         static internal bool IsTagEnabled(string tagName)
  695.         {
  696.             #if DBG
  697.             EnsureInit();
  698.             return GetTagValue(tagName) != TagValue.Disabled;
  699.             #else
  700.             return false;
  701.             #endif
  702.         }
  703.        
  704.         //
  705.         // Returns true if the tag present.
  706.         // This function chekcs for an exact match.
  707.         //
  708.         static internal bool IsTagPresent(string tagName)
  709.         {
  710.             #if DBG
  711.             EnsureInit();
  712.             return FindMatchingTag(tagName, true) != null;
  713.             #else
  714.             return false;
  715.             #endif
  716.         }
  717.        
  718.         //
  719.         // Breaks into the debugger, or launches one if not yet attached.
  720.         //
  721.         [System.Diagnostics.Conditional("DBG")]
  722.         static internal void Break()
  723.         {
  724.             #if DBG
  725.             if (!System.Diagnostics.Debugger.IsAttached) {
  726.                 System.Diagnostics.Debugger.Launch();
  727.             }
  728.             else {
  729.                 System.Diagnostics.Debugger.Break();
  730.             }
  731.             #endif
  732.         }
  733.        
  734.        
  735.         //
  736.         // Tells the debug system to always validate calls for a
  737.         // particular tag. This is useful for temporarily enabling
  738.         // validation in stress tests or other situations where you
  739.         // may not have control over the debug tags that are enabled
  740.         // on a particular machine.
  741.         //
  742.         [System.Diagnostics.Conditional("DBG")]
  743.         static internal void AlwaysValidate(string tagName)
  744.         {
  745.             #if DBG
  746.             EnsureInit();
  747.             s_tableAlwaysValidate[tagName] = tagName;
  748.             #endif
  749.         }
  750.        
  751.        
  752.         //
  753.         // Throws an exception if the assertion is not valid.
  754.         // Use this function from a DebugValidate method where
  755.         // you would otherwise use Assert.
  756.         //
  757.         [System.Diagnostics.Conditional("DBG")]
  758.         static internal void CheckValid(bool assertion, string message)
  759.         {
  760.             #if DBG
  761.             if (!assertion) {
  762.                 throw new Exception(message);
  763.             }
  764.             #endif
  765.         }
  766.        
  767.         //
  768.         // Calls DebugValidate on an object if such a method exists.
  769.         //
  770.         // This method should be used from implementations of DebugValidate
  771.         // where it is unknown whether an object has a DebugValidate method.
  772.         // For example, the DoubleLink class uses it to validate the
  773.         // item of type Object which it points to.
  774.         //
  775.         // This method should NOT be used when code wants to conditionally
  776.         // validate an object and have a failed validation caught in an assert.
  777.         // Use Debug.Validate(tagName, obj) for that purpose.
  778.         //
  779.         [System.Diagnostics.Conditional("DBG")]
  780.         static internal void Validate(object obj)
  781.         {
  782.             #if DBG
  783.             Type type;
  784.             MethodInfo mi;
  785.            
  786.             if (obj != null) {
  787.                 type = obj.GetType();
  788.                
  789.                 mi = type.GetMethod("DebugValidate", BindingFlags.NonPublic | BindingFlags.Instance, null, s_ValidateArgs, null);
  790.                
  791.                 if (mi != null) {
  792.                     object[] tempIndex = null;
  793.                     mi.Invoke(obj, tempIndex);
  794.                 }
  795.             }
  796.             #endif
  797.         }
  798.        
  799.         //
  800.         // Validates an object is the "Validate" tag is enabled, or when
  801.         // the "Validate" tag is not disabled and the given 'tag' is enabled.
  802.         // An Assertion is made if the validation fails.
  803.         //
  804.         [System.Diagnostics.Conditional("DBG")]
  805.         static internal void Validate(string tagName, object obj)
  806.         {
  807.             #if DBG
  808.             EnsureInit();
  809.            
  810.             if (obj != null && (IsTagEnabled("Validate") || (!IsTagPresent("Validate") && (s_tableAlwaysValidate[tagName] != null || IsTagEnabled(tagName))))) {
  811.                 try {
  812.                     Debug.Validate(obj);
  813.                 }
  814.                 catch (Exception e) {
  815.                     Debug.Assert(false, "Validate failed: " + e.InnerException.Message);
  816.                 }
  817.                 catch {
  818.                     Debug.Assert(false, "Validate failed. Non-CLS compliant exception caught.");
  819.                 }
  820.             }
  821.             #endif
  822.         }
  823.        
  824.         #if DBG
  825.        
  826.         //
  827.         // Calls DebugDescription on an object to get its description.
  828.         //
  829.         // This method should only be used in implementations of DebugDescription
  830.         // where it is not known whether a nested objects has an implementation
  831.         // of DebugDescription. For example, the double linked list class uses
  832.         // GetDescription to get the description of the item it points to.
  833.         //
  834.         // This method should NOT be used when you want to conditionally
  835.         // dump an object. Use Debug.Dump instead.
  836.         //
  837.         // @param obj The object to call DebugDescription on. May be null.
  838.         // @param indent A prefix for each line in the description. This is used
  839.         // to allow the nested display of objects within other objects.
  840.         // The indent is usually a multiple of four spaces.
  841.         //
  842.         // @return The description.
  843.         //
  844.         [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
  845.         static internal string GetDescription(object obj, string indent)
  846.         {
  847.             string description;
  848.             Type type;
  849.             MethodInfo mi;
  850.             object[] parameters;
  851.            
  852.             if (obj == null) {
  853.                 description = "\n";
  854.             }
  855.             else {
  856.                 type = obj.GetType();
  857.                 mi = type.GetMethod("DebugDescription", BindingFlags.NonPublic | BindingFlags.Instance, null, s_DumpArgs, null);
  858.                
  859.                 if (mi == null || mi.ReturnType != typeof(string)) {
  860.                     description = indent + obj.ToString();
  861.                 }
  862.                 else {
  863.                     parameters = new object[1] {(object)indent};
  864.                     description = (string)mi.Invoke(obj, parameters);
  865.                 }
  866.             }
  867.            
  868.             return description;
  869.         }
  870.         #endif
  871.        
  872.        
  873.         //
  874.         // Dumps an object to the debugger if the "Dump" tag is enabled,
  875.         // or if the "Dump" tag is not present and the 'tag' is enabled.
  876.         //
  877.         // @param tagName The tag to Dump with.
  878.         // @param obj The object to dump.
  879.         //
  880.         [System.Diagnostics.Conditional("DBG")]
  881.         static internal void Dump(string tagName, object obj)
  882.         {
  883.             #if DBG
  884.             EnsureInit();
  885.            
  886.             string description;
  887.             string traceTag = null;
  888.             bool dumpEnabled;
  889.             bool dumpPresent;
  890.            
  891.             if (obj != null) {
  892.                 dumpEnabled = IsTagEnabled("Dump");
  893.                 dumpPresent = IsTagPresent("Dump");
  894.                 if (dumpEnabled || !dumpPresent) {
  895.                     if (IsTagEnabled(tagName)) {
  896.                         traceTag = tagName;
  897.                     }
  898.                     else if (dumpEnabled) {
  899.                         traceTag = "Dump";
  900.                     }
  901.                    
  902.                     if (traceTag != null) {
  903.                         description = GetDescription(obj, string.Empty);
  904.                         Debug.Trace(traceTag, "Dump\n" + description);
  905.                     }
  906.                 }
  907.             }
  908.             #endif
  909.         }
  910.        
  911.        
  912.     }
  913. }

Developer Fusion