modified Resources/hresult.xml
[reactos.git] / irc / TechBot / TechBot.Library / ErrorCommand.cs
index 6ee2d68..35b7789 100644 (file)
@@ -1,5 +1,6 @@
 using System;\r
 using System.Xml;\r
+using System.Collections;\r
 \r
 namespace TechBot.Library\r
 {\r
@@ -28,58 +29,170 @@ namespace TechBot.Library
                                         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