3 using System.Collections;
7 namespace TechBot.Commands.Common
9 [Command("error", Help = "!error <value>")]
10 public class ErrorCommand : Command
12 private NtStatusCommand ntStatus;
13 private WinErrorCommand winerror;
14 private HResultCommand hresult;
18 this.ntStatus = new NtStatusCommand();
19 this.winerror = new WinErrorCommand();
20 this.hresult = new HResultCommand();
23 private static int GetSeverity(long error)
25 return (int)((error >> 30) & 0x3);
28 private static bool IsCustomer(long error)
30 return (error & 0x20000000) != 0;
33 private static bool IsReserved(long error)
35 return (error & 0x10000000) != 0;
38 private static int GetFacility(long error)
40 return (int)((error >> 16) & 0xFFF);
43 private static short GetCode(long error)
45 return (short)((error >> 0) & 0xFFFF);
48 private static string FormatSeverity(long error)
50 int severity = GetSeverity(error);
53 case 0: return "SUCCESS";
54 case 1: return "INFORMATIONAL";
55 case 2: return "WARNING";
56 case 3: return "ERROR";
61 private static string FormatFacility(long error)
63 int facility = GetFacility(error);
64 return facility.ToString();
67 private static string FormatCode(long error)
69 int code = GetCode(error);
70 return code.ToString();
73 public override void ExecuteCommand()
75 if (Parameters.Equals(String.Empty))
77 Say("Please provide an Error Code.");
81 string errorText = Parameters;
84 NumberParser np = new NumberParser();
85 long error = np.Parse(errorText);
88 Say("{0} is not a valid Error Code.", Parameters);
92 ArrayList descriptions = new ArrayList();
94 // Error is out of bounds
95 if ((ulong)error > uint.MaxValue)
99 // Error is outside of the range [0, 65535]: it cannot be a plain Win32 error code
100 else if ((ulong)error > ushort.MaxValue)
102 // Customer bit is set: custom error code
103 if (IsCustomer(error))
105 string description = String.Format("[custom, severity {0}, facility {1}, code {2}]",
106 FormatSeverity(error),
107 FormatFacility(error),
109 descriptions.Add(description);
111 // Reserved bit is set: HRESULT_FROM_NT(ntstatus)
112 else if (IsReserved(error))
114 int status = (int)(error & 0xCFFFFFFF);
115 string description = ntStatus.GetNtstatusDescription(status);
117 if (description == null)
118 description = status.ToString("X");
120 description = String.Format("HRESULT_FROM_NT({0})", description);
121 descriptions.Add(description);
123 // Win32 facility: HRESULT_FROM_WIN32(winerror)
124 else if (GetFacility(error) == 7)
126 // Must be an error code
127 if (GetSeverity(error) == 2)
129 short err = GetCode(error);
130 string description = winerror.GetWinerrorDescription(err);
132 if (description == null)
133 description = err.ToString("D");
135 description = String.Format("HRESULT_FROM_WIN32({0})", description);
136 descriptions.Add(description);
141 string winerrorDescription = winerror.GetWinerrorDescription(error);
142 string ntstatusDescription = ntStatus.GetNtstatusDescription(error);
143 string hresultDescription = hresult.GetHresultDescription(error);
145 if (winerrorDescription != null)
146 descriptions.Add(winerrorDescription);
147 if (ntstatusDescription != null)
148 descriptions.Add(ntstatusDescription);
149 if (hresultDescription != null)
150 descriptions.Add(hresultDescription);
152 if (descriptions.Count == 0)
154 // Last chance heuristics: attempt to parse a 8-digit decimal as hexadecimal
155 if (errorText.Length == 8)
157 errorText = "0x" + errorText;
161 Say("I don't know about Error Code {0}.",
164 else if (descriptions.Count == 1)
166 string description = (string)descriptions[0];
173 Say("{0} could be:", Parameters);
175 foreach (string description in descriptions)
176 Say("\t{0}", description);