using System;\r
using System.Xml;\r
+using System.Collections;\r
\r
namespace TechBot.Library\r
{\r
new string[] { "error" });\r
}\r
\r
+ private static int GetSeverity(long error)\r
+ {\r
+ return (int)((error >> 30) & 0x3);\r
+ }\r
+\r
+ private static bool IsCustomer(long error)\r
+ {\r
+ return (error & 0x20000000) != 0;\r
+ }\r
+ \r
+ private static bool IsReserved(long error)\r
+ {\r
+ return (error & 0x10000000) != 0;\r
+ }\r
+\r
+ private static int GetFacility(long error)\r
+ {\r
+ return (int)((error >> 16) & 0xFFF);\r
+ }\r
+ \r
+ private static short GetCode(long error)\r
+ {\r
+ return (short)((error >> 0) & 0xFFFF);\r
+ }\r
+\r
+ private static string FormatSeverity(long error)\r
+ {\r
+ int severity = GetSeverity(error);\r
+ switch (severity)\r
+ {\r
+ case 0: return "SUCCESS";\r
+ case 1: return "INFORMATIONAL";\r
+ case 2: return "WARNING";\r
+ case 3: return "ERROR";\r
+ }\r
+ return null;\r
+ }\r
+\r
+ private static string FormatFacility(long error)\r
+ {\r
+ int facility = GetFacility(error);\r
+ return facility.ToString();\r
+ }\r
+\r
+ private static string FormatCode(long error)\r
+ {\r
+ int code = GetCode(error);\r
+ return code.ToString();\r
+ }\r
+\r
public void Handle(MessageContext context,\r
string commandName,\r
string parameters)\r
{\r
- string errorText = parameters;\r
- if (errorText.Equals(String.Empty))\r
+ string originalErrorText = parameters.Trim();\r
+ if (originalErrorText.Equals(String.Empty))\r
{\r
serviceOutput.WriteLine(context,\r
"Please provide an Error Code.");\r
return;\r
}\r
+ \r
+ string errorText = originalErrorText;\r
\r
+ retry:\r
NumberParser np = new NumberParser();\r
long error = np.Parse(errorText);\r
if (np.Error)\r
{\r
serviceOutput.WriteLine(context,\r
String.Format("{0} is not a valid Error Code.",\r
- errorText));\r
+ originalErrorText));\r
return;\r
}\r
+ \r
+ ArrayList descriptions = new ArrayList();\r
\r
- string description = null;\r
- if (winerror.GetWinerrorDescription(error) != null)\r
+ // Error is out of bounds\r
+ if ((ulong)error > uint.MaxValue)\r
{\r
- description = winerror.GetWinerrorDescription(error);\r
- serviceOutput.WriteLine(context,\r
- String.Format("{0} is {1}.",\r
- error,\r
- description));\r
+ // Do nothing\r
}\r
- if (ntStatus.GetNtstatusDescription(error) != null)\r
+ // Error is outside of the range [0, 65535]: it cannot be a plain Win32 error code\r
+ else if ((ulong)error > ushort.MaxValue)\r
{\r
- description = ntStatus.GetNtstatusDescription(error);\r
+ // Customer bit is set: custom error code\r
+ if (IsCustomer(error))\r
+ {\r
+ string description = String.Format("[custom, severity {0}, facility {1}, code {2}]",\r
+ FormatSeverity(error),\r
+ FormatFacility(error),\r
+ FormatCode(error));\r
+ descriptions.Add(description);\r
+ }\r
+ // Reserved bit is set: HRESULT_FROM_NT(ntstatus)\r
+ else if (IsReserved(error))\r
+ {\r
+ int status = (int)(error & 0xCFFFFFFF);\r
+ string description = ntStatus.GetNtstatusDescription(status);\r
+ \r
+ if (description == null)\r
+ description = status.ToString("X");\r
+ \r
+ description = String.Format("HRESULT_FROM_NT({0})", description);\r
+ descriptions.Add(description);\r
+ }\r
+ // Win32 facility: HRESULT_FROM_WIN32(winerror)\r
+ else if (GetFacility(error) == 7)\r
+ {\r
+ // Must be an error code\r
+ if (GetSeverity(error) == 2)\r
+ {\r
+ short err = GetCode(error);\r
+ string description = winerror.GetWinerrorDescription(err);\r
+ \r
+ if (description == null)\r
+ description = err.ToString("D");\r
+ \r
+ description = String.Format("HRESULT_FROM_WIN32({0})", description);\r
+ descriptions.Add(description);\r
+ }\r
+ }\r
+ }\r
+\r
+ string winerrorDescription = winerror.GetWinerrorDescription(error);\r
+ string ntstatusDescription = ntStatus.GetNtstatusDescription(error);\r
+ string hresultDescription = hresult.GetHresultDescription(error);\r
+ \r
+ if (winerrorDescription != null)\r
+ descriptions.Add(winerrorDescription);\r
+ if (ntstatusDescription != null)\r
+ descriptions.Add(ntstatusDescription);\r
+ if (hresultDescription != null)\r
+ descriptions.Add(hresultDescription);\r
+\r
+ if (descriptions.Count == 0)\r
+ {\r
+ // Last chance heuristics: attempt to parse a 8-digit decimal as hexadecimal\r
+ if (errorText.Length == 8)\r
+ {\r
+ errorText = "0x" + errorText;\r
+ goto retry;\r
+ }\r
+\r
serviceOutput.WriteLine(context,\r
- String.Format("{0} is {1}.",\r
- errorText,\r
- description));\r
+ String.Format("I don't know about Error Code {0}.",\r
+ originalErrorText));\r
}\r
- if (hresult.GetHresultDescription(error) != null)\r
+ else if (descriptions.Count == 1)\r
{\r
- description = hresult.GetHresultDescription(error);\r
+ string description = (string)descriptions[0];\r
serviceOutput.WriteLine(context,\r
String.Format("{0} is {1}.",\r
- errorText,\r
+ originalErrorText,\r
description));\r
}\r
- if(description == null)\r
+ else\r
{\r
serviceOutput.WriteLine(context,\r
- String.Format("I don't know about Error Code {0}.",\r
- errorText));\r
+ String.Format("{0} could be:",\r
+ originalErrorText));\r
+ \r
+ foreach(string description in descriptions)\r
+ serviceOutput.WriteLine(context, String.Format("\t{0}", description));\r
}\r
}\r
\r