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