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