The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ Win32Exception

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Win32Exception.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. /*
  16. */
  17. namespace System.ComponentModel
  18. {
  19.     using Microsoft.Win32;
  20.     using System;
  21.     using System.Diagnostics;
  22.     using System.Runtime.InteropServices;
  23.     using System.Runtime.Remoting;
  24.     using System.Runtime.Serialization;
  25.     using System.Security;
  26.     using System.Security.Permissions;
  27.     using System.Text;
  28.    
  29.     /// <devdoc>
  30.     /// <para>The exception that is thrown for a Win32 error code.</para>
  31.     /// </devdoc>
  32.     // Code already shipped - safe to place link demand on derived class constructor when base doesn't have it - Suppress message.
  33.     [HostProtection(SharedState = true)]
  34.     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
  35.     [Serializable()]
  36.     [SuppressUnmanagedCodeSecurity()]
  37.     public class Win32Exception : ExternalException, ISerializable
  38.     {
  39.         /// <devdoc>
  40.         /// <para>Represents the Win32 error code associated with this exception. This
  41.         /// field is read-only.</para>
  42.         /// </devdoc>
  43.         private readonly int nativeErrorCode;
  44.        
  45.         /// <devdoc>
  46.         /// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the last Win32 error
  47.         /// that occured.</para>
  48.         /// </devdoc>
  49.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  50.         public Win32Exception() : this(Marshal.GetLastWin32Error())
  51.         {
  52.         }
  53.         /// <devdoc>
  54.         /// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the specified error.</para>
  55.         /// </devdoc>
  56.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  57.         public Win32Exception(int error) : this(error, GetErrorMessage(error))
  58.         {
  59.         }
  60.         /// <devdoc>
  61.         /// <para>Initializes a new instance of the <see cref='System.ComponentModel.Win32Exception'/> class with the specified error and the
  62.         /// specified detailed description.</para>
  63.         /// </devdoc>
  64.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  65.         public Win32Exception(int error, string message) : base(message)
  66.         {
  67.             nativeErrorCode = error;
  68.         }
  69.        
  70.         /// <devdoc>
  71.         /// Initializes a new instance of the Exception class with a specified error message.
  72.         /// FxCop CA1032: Multiple constructors are required to correctly implement a custom exception.
  73.         /// </devdoc>
  74.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  75.         public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message)
  76.         {
  77.         }
  78.        
  79.         /// <devdoc>
  80.         /// Initializes a new instance of the Exception class with a specified error message and a
  81.         /// reference to the inner exception that is the cause of this exception.
  82.         /// FxCop CA1032: Multiple constructors are required to correctly implement a custom exception.
  83.         /// </devdoc>
  84.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
  85.         public Win32Exception(string message, Exception innerException) : base(message, innerException)
  86.         {
  87.             nativeErrorCode = Marshal.GetLastWin32Error();
  88.         }
  89.        
  90.         protected Win32Exception(SerializationInfo info, StreamingContext context) : base(info, context)
  91.         {
  92.             IntSecurity.UnmanagedCode.Demand();
  93.             nativeErrorCode = info.GetInt32("NativeErrorCode");
  94.         }
  95.        
  96.         /// <devdoc>
  97.         /// <para>Represents the Win32 error code associated with this exception. This
  98.         /// field is read-only.</para>
  99.         /// </devdoc>
  100.         public int NativeErrorCode {
  101.             get { return nativeErrorCode; }
  102.         }
  103.        
  104.         private static string GetErrorMessage(int error)
  105.         {
  106.             //get the system error message...
  107.             string errorMsg = "";
  108.            
  109.             StringBuilder sb = new StringBuilder(256);
  110.             int result = SafeNativeMethods.FormatMessage(SafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS | SafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM | SafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY, NativeMethods.NullHandleRef, error, 0, sb, sb.Capacity + 1, IntPtr.Zero);
  111.             if (result != 0) {
  112.                 int i = sb.Length;
  113.                 while (i > 0) {
  114.                     char ch = sb[i - 1];
  115.                     if (ch > 32 && ch != '.')
  116.                         break;
  117.                     i--;
  118.                 }
  119.                 errorMsg = sb.ToString(0, i);
  120.             }
  121.             else {
  122.                 errorMsg = "Unknown error (0x" + Convert.ToString(error, 16) + ")";
  123.             }
  124.            
  125.             return errorMsg;
  126.         }
  127.        
  128.         // Even though all we're exposing is the nativeErrorCode (which is also available via public property)
  129.         // it's not a bad idea to have this in place. Later, if more fields are added to this exception,
  130.         // we won't need to worry about accidentaly exposing them through this interface.
  131.         [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
  132.         public override void GetObjectData(SerializationInfo info, StreamingContext context)
  133.         {
  134.             if (info == null) {
  135.                 throw new ArgumentNullException("info");
  136.             }
  137.             info.AddValue("NativeErrorCode", nativeErrorCode);
  138.             base.GetObjectData(info, context);
  139.         }
  140.     }
  141. }

Developer Fusion