bb1980b032e0cad75dffcc17d87fb43227df1551
[reactos.git] / irc / TechBot / TechBot.Commands.Common / ErrorCommand.cs
1 using System;
2 using System.Xml;
3 using System.Collections;
4
5 using TechBot.Library;
6
7 namespace TechBot.Commands.Common
8 {
9 [Command("error", Help = "!error <value>")]
10 public class ErrorCommand : Command
11 {
12 private NtStatusCommand ntStatus;
13 private WinErrorCommand winerror;
14 private HResultCommand hresult;
15
16 public ErrorCommand()
17 {
18 this.ntStatus = new NtStatusCommand();
19 this.winerror = new WinErrorCommand();
20 this.hresult = new HResultCommand();
21 }
22
23 private static int GetSeverity(long error)
24 {
25 return (int)((error >> 30) & 0x3);
26 }
27
28 private static bool IsCustomer(long error)
29 {
30 return (error & 0x20000000) != 0;
31 }
32
33 private static bool IsReserved(long error)
34 {
35 return (error & 0x10000000) != 0;
36 }
37
38 private static int GetFacility(long error)
39 {
40 return (int)((error >> 16) & 0xFFF);
41 }
42
43 private static short GetCode(long error)
44 {
45 return (short)((error >> 0) & 0xFFFF);
46 }
47
48 private static string FormatSeverity(long error)
49 {
50 int severity = GetSeverity(error);
51 switch (severity)
52 {
53 case 0: return "SUCCESS";
54 case 1: return "INFORMATIONAL";
55 case 2: return "WARNING";
56 case 3: return "ERROR";
57 }
58 return null;
59 }
60
61 private static string FormatFacility(long error)
62 {
63 int facility = GetFacility(error);
64 return facility.ToString();
65 }
66
67 private static string FormatCode(long error)
68 {
69 int code = GetCode(error);
70 return code.ToString();
71 }
72
73 public override void ExecuteCommand()
74 {
75 if (Parameters.Equals(String.Empty))
76 {
77 Say("Please provide an Error Code.");
78 return;
79 }
80
81 string errorText = Parameters;
82
83 retry:
84 NumberParser np = new NumberParser();
85 long error = np.Parse(errorText);
86 if (np.Error)
87 {
88 Say("{0} is not a valid Error Code.", Parameters);
89 return;
90 }
91
92 ArrayList descriptions = new ArrayList();
93
94 // Error is out of bounds
95 if ((ulong)error > uint.MaxValue)
96 {
97 // Do nothing
98 }
99 // Error is outside of the range [0, 65535]: it cannot be a plain Win32 error code
100 else if ((ulong)error > ushort.MaxValue)
101 {
102 // Customer bit is set: custom error code
103 if (IsCustomer(error))
104 {
105 string description = String.Format("[custom, severity {0}, facility {1}, code {2}]",
106 FormatSeverity(error),
107 FormatFacility(error),
108 FormatCode(error));
109 descriptions.Add(description);
110 }
111 // Reserved bit is set: HRESULT_FROM_NT(ntstatus)
112 else if (IsReserved(error))
113 {
114 int status = (int)(error & 0xCFFFFFFF);
115 string description = ntStatus.GetNtstatusDescription(status);
116
117 if (description == null)
118 description = status.ToString("X");
119
120 description = String.Format("HRESULT_FROM_NT({0})", description);
121 descriptions.Add(description);
122 }
123 // Win32 facility: HRESULT_FROM_WIN32(winerror)
124 else if (GetFacility(error) == 7)
125 {
126 // Must be an error code
127 if (GetSeverity(error) == 2)
128 {
129 short err = GetCode(error);
130 string description = winerror.GetWinerrorDescription(err);
131
132 if (description == null)
133 description = err.ToString("D");
134
135 description = String.Format("HRESULT_FROM_WIN32({0})", description);
136 descriptions.Add(description);
137 }
138 }
139 }
140
141 string winerrorDescription = winerror.GetWinerrorDescription(error);
142 string ntstatusDescription = ntStatus.GetNtstatusDescription(error);
143 string hresultDescription = hresult.GetHresultDescription(error);
144
145 if (winerrorDescription != null)
146 descriptions.Add(winerrorDescription);
147 if (ntstatusDescription != null)
148 descriptions.Add(ntstatusDescription);
149 if (hresultDescription != null)
150 descriptions.Add(hresultDescription);
151
152 if (descriptions.Count == 0)
153 {
154 // Last chance heuristics: attempt to parse a 8-digit decimal as hexadecimal
155 if (errorText.Length == 8)
156 {
157 errorText = "0x" + errorText;
158 goto retry;
159 }
160
161 Say("I don't know about Error Code {0}.",
162 Parameters);
163 }
164 else if (descriptions.Count == 1)
165 {
166 string description = (string)descriptions[0];
167 Say("{0} is {1}.",
168 Parameters,
169 description);
170 }
171 else
172 {
173 Say("{0} could be:", Parameters);
174
175 foreach (string description in descriptions)
176 Say("\t{0}", description);
177 }
178 }
179 }
180 }