Update debugger types and thread report handling

This commit is contained in:
x1nixmzeng 2020-10-11 12:14:42 +01:00
parent 3a740d7933
commit 96155736e5
3 changed files with 166 additions and 143 deletions

View File

@ -9,6 +9,7 @@ using WinDebug = VsChromium.Core.Win32.Debugging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using WinLowLevel = LowLevelDesign.Win32.Windows.NativeMethods; using WinLowLevel = LowLevelDesign.Win32.Windows.NativeMethods;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace CxbxDebugger namespace CxbxDebugger
{ {
@ -32,13 +33,18 @@ namespace CxbxDebugger
string[] args = new string[] { }; string[] args = new string[] { };
string Target = ""; string Target = "";
public string ProcessName
{
get { return Target; }
}
RunState State = RunState.NotLaunched; RunState State = RunState.NotLaunched;
DebuggerMessages.DebuggerInit InitParams = new DebuggerMessages.DebuggerInit(); DebuggerMessages.DebuggerInit InitParams = new DebuggerMessages.DebuggerInit();
DebuggerInstance DebugInstance; DebuggerInstance DebugInstance;
List<IDebuggerGeneralEvents> GeneralEvents = new List<IDebuggerGeneralEvents>(); List<IDebuggerSessionEvents> SessionEvents = new List<IDebuggerSessionEvents>();
List<IDebuggerProcessEvents> ProcessEvents = new List<IDebuggerProcessEvents>(); List<IDebuggerProcessEvents> ProcessEvents = new List<IDebuggerProcessEvents>();
List<IDebuggerThreadEvents> ThreadEvents = new List<IDebuggerThreadEvents>(); List<IDebuggerThreadEvents> ThreadEvents = new List<IDebuggerThreadEvents>();
List<IDebuggerModuleEvents> ModuleEvents = new List<IDebuggerModuleEvents>(); List<IDebuggerModuleEvents> ModuleEvents = new List<IDebuggerModuleEvents>();
@ -103,7 +109,7 @@ namespace CxbxDebugger
bpStall.Set(); bpStall.Set();
// Remove all events // Remove all events
GeneralEvents.Clear(); SessionEvents.Clear();
ProcessEvents.Clear(); ProcessEvents.Clear();
ThreadEvents.Clear(); ThreadEvents.Clear();
ModuleEvents.Clear(); ModuleEvents.Clear();
@ -172,6 +178,9 @@ namespace CxbxDebugger
if (CanLaunch() == false) if (CanLaunch() == false)
throw new Exception("Unable to launch in this state"); throw new Exception("Unable to launch in this state");
if (args.Length == 0)
return false;
var DebugCreationFlags = var DebugCreationFlags =
WinProcesses.ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS | WinProcesses.ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS |
WinProcesses.ProcessCreationFlags.CREATE_NEW_CONSOLE; WinProcesses.ProcessCreationFlags.CREATE_NEW_CONSOLE;
@ -197,7 +206,7 @@ namespace CxbxDebugger
// Store so they can be marshalled and closed correctly // Store so they can be marshalled and closed correctly
hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess); hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess);
hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread); hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread);
bContinue = true; bContinue = true;
State = RunState.Running; State = RunState.Running;
@ -313,10 +322,7 @@ namespace CxbxDebugger
Thread.StartAddress = DebugInfo.lpStartAddress; Thread.StartAddress = DebugInfo.lpStartAddress;
Thread.ThreadBase = DebugInfo.lpThreadLocalBase; Thread.ThreadBase = DebugInfo.lpThreadLocalBase;
foreach (IDebuggerThreadEvents Event in ThreadEvents ) Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(Thread));
{
Event.OnThreadCreate(Thread);
}
} }
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent) private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent)
@ -333,10 +339,7 @@ namespace CxbxDebugger
{ {
uint ExitCode = DebugInfo.dwExitCode; uint ExitCode = DebugInfo.dwExitCode;
foreach (IDebuggerThreadEvents Event in ThreadEvents) Parallel.ForEach(ThreadEvents, Event => Event.OnThreadExit(TargetThread, ExitCode));
{
Event.OnThreadExit(TargetThread, ExitCode);
}
} }
} }
@ -369,26 +372,17 @@ namespace CxbxDebugger
DebugInstance = new DebuggerInstance(Process); DebugInstance = new DebuggerInstance(Process);
RegisterEventInterfaces(DebugInstance); RegisterEventInterfaces(DebugInstance);
foreach (IDebuggerProcessEvents Event in ProcessEvents) Parallel.ForEach(ProcessEvents, Event => Event.OnProcessCreate(Process));
{
Event.OnProcessCreate(Process);
}
foreach (IDebuggerThreadEvents Event in ThreadEvents) Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(MainThread));
{
Event.OnThreadCreate(MainThread);
}
var XboxModule = new DebuggerModule(); var XboxModule = new DebuggerModule();
XboxModule.Path = Target; XboxModule.Path = Target;
XboxModule.ImageBase = DebugInfo.lpBaseOfImage; XboxModule.ImageBase = DebugInfo.lpBaseOfImage;
XboxModule.Core = true; XboxModule.Core = true;
foreach (IDebuggerModuleEvents Event in ModuleEvents) Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(XboxModule));
{
Event.OnModuleLoaded(XboxModule);
}
} }
private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent) private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent)
@ -405,10 +399,7 @@ namespace CxbxDebugger
if (TargetProcess != null) if (TargetProcess != null)
{ {
foreach (IDebuggerProcessEvents Event in ProcessEvents) Parallel.ForEach(ProcessEvents, Event => Event.OnProcessExit(TargetProcess, ExitCode));
{
Event.OnProcessExit(TargetProcess, ExitCode);
}
} }
} }
@ -426,10 +417,7 @@ namespace CxbxDebugger
Module.Path = ResolveProcessPath(DebugInfo.hFile); Module.Path = ResolveProcessPath(DebugInfo.hFile);
Module.ImageBase = DebugInfo.lpBaseOfDll; Module.ImageBase = DebugInfo.lpBaseOfDll;
foreach (IDebuggerModuleEvents Event in ModuleEvents) Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(Module));
{
Event.OnModuleLoaded(Module);
}
} }
private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent) private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent)
@ -445,10 +433,7 @@ namespace CxbxDebugger
if (TargetModule != null) if (TargetModule != null)
{ {
foreach (IDebuggerModuleEvents Event in ModuleEvents) Parallel.ForEach(ModuleEvents, Event => Event.OnModuleUnloaded(TargetModule));
{
Event.OnModuleUnloaded(TargetModule);
}
} }
} }
@ -458,10 +443,7 @@ namespace CxbxDebugger
string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1); string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1);
foreach(IDebuggerOutputEvents Event in OutputEvents) Parallel.ForEach(OutputEvents, Event => Event.OnDebugOutput(debugString));
{
Event.OnDebugOutput(debugString);
}
} }
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent) private void HandleException(WinDebug.DEBUG_EVENT DebugEvent)
@ -482,12 +464,28 @@ namespace CxbxDebugger
} }
break; break;
case ExceptionCode.PrivilegedInstruction:
{
// Seeing this frequently called in Win10
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
}
break;
case ExceptionCode.StatusHandleNotClosable:
{
// Seeing this frequently called in Win10
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
}
break;
case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION: case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION:
{ {
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
bool Handled = false; bool Handled = false;
foreach (IDebuggerExceptionEvents Event in ExceptionEvents) foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
@ -506,7 +504,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetHLECacheReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetHLECacheReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
SetupHLECacheProvider(Report.FileName); SetupHLECacheProvider(Report.FileName);
} }
} }
@ -517,7 +515,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetKernelPatchReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetKernelPatchReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
KernelSymbolProvider.AddKernelSymbolFromMessage(Report); KernelSymbolProvider.AddKernelSymbolFromMessage(Report);
} }
@ -529,12 +527,9 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetFileOpenedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetFileOpenedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
foreach (IDebuggerFileEvents Event in FileEvents) Parallel.ForEach(FileEvents, Event => Event.OnFileOpened(Report));
{
Event.OnFileOpened(Report);
}
} }
} }
break; break;
@ -544,12 +539,9 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetFileReadReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetFileReadReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
foreach (IDebuggerFileEvents Event in FileEvents) Parallel.ForEach(FileEvents, Event => Event.OnFileRead(Report));
{
Event.OnFileRead(Report);
}
} }
} }
break; break;
@ -559,12 +551,9 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetFileWriteReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetFileWriteReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
foreach (IDebuggerFileEvents Event in FileEvents) Parallel.ForEach(FileEvents, Event => Event.OnFileWrite(Report));
{
Event.OnFileWrite(Report);
}
} }
} }
break; break;
@ -574,13 +563,10 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetFileClosedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetFileClosedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
if (Report != null) if (Report != null)
{ {
foreach (IDebuggerFileEvents Event in FileEvents) Parallel.ForEach(FileEvents, Event => Event.OnFileClosed(Report));
{
Event.OnFileClosed(Report);
}
} }
} }
} }
@ -591,14 +577,23 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetDebuggerInitReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetDebuggerInitReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
InitParams = Report; InitParams = Report;
foreach (IDebuggerGeneralEvents Event in GeneralEvents) Parallel.ForEach(SessionEvents, Event => Event.OnDebugTitleLoaded(InitParams.Title));
{ }
Event.OnDebugTitleLoaded(InitParams.Title); }
} break;
case (ExceptionCode)DebuggerMessages.ReportType.DEBUGGER_NEW_TARGET:
{
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null)
{
var Report = DebuggerMessages.GetDebuggerNewTargetReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
Parallel.ForEach(SessionEvents, Event => Event.OnDebugTargetChanged(Report.CommandLine));
} }
} }
break; break;
@ -608,7 +603,7 @@ namespace CxbxDebugger
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
if (Thread != null) if (Thread != null)
{ {
var Report = DebuggerMessages.GetMSVCThreadName(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); var Report = DebuggerMessages.GetMSVCThreadName(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
if(Report != null) if(Report != null)
{ {
// Resolve the ThreadId of an invalid ID to the current thread name // Resolve the ThreadId of an invalid ID to the current thread name
@ -623,10 +618,7 @@ namespace CxbxDebugger
// Update the resolved thread name // Update the resolved thread name
ResolvedThread.DebugName = Report.Name; ResolvedThread.DebugName = Report.Name;
foreach (IDebuggerThreadEvents Event in ThreadEvents) Parallel.ForEach(ThreadEvents, Event => Event.OnThreadNamed(Thread));
{
Event.OnThreadNamed(Thread);
}
} }
} }
} }
@ -644,10 +636,7 @@ namespace CxbxDebugger
bpStall.Reset(); bpStall.Reset();
foreach (IDebuggerExceptionEvents Event in ExceptionEvents) Parallel.ForEach(ExceptionEvents, Event => Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance));
{
Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance);
}
bpStall.WaitOne(); bpStall.WaitOne();
} }
@ -674,10 +663,7 @@ namespace CxbxDebugger
WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT(); WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT();
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE;
foreach (IDebuggerGeneralEvents Event in GeneralEvents) Parallel.ForEach(SessionEvents, Event => Event.OnDebugStart());
{
Event.OnDebugStart();
}
// Loop until told to stop // Loop until told to stop
while (bContinue == true) while (bContinue == true)
@ -734,10 +720,7 @@ namespace CxbxDebugger
State = RunState.Ended; State = RunState.Ended;
foreach (IDebuggerGeneralEvents Event in GeneralEvents) Parallel.ForEach(SessionEvents, Event => Event.OnDebugEnd());
{
Event.OnDebugEnd();
}
} }
public DebuggerSymbol ResolveSymbol(uint Address) public DebuggerSymbol ResolveSymbol(uint Address)
@ -757,8 +740,8 @@ namespace CxbxDebugger
public void RegisterEventInterfaces(object EventClass) public void RegisterEventInterfaces(object EventClass)
{ {
IDebuggerGeneralEvents GeneralListener = EventClass as IDebuggerGeneralEvents; IDebuggerSessionEvents SessionListener = EventClass as IDebuggerSessionEvents;
if(GeneralListener != null ) GeneralEvents.Add(GeneralListener); if(SessionListener != null ) SessionEvents.Add(SessionListener);
IDebuggerProcessEvents ProcessListener = EventClass as IDebuggerProcessEvents; IDebuggerProcessEvents ProcessListener = EventClass as IDebuggerProcessEvents;
if (ProcessListener != null) ProcessEvents.Add(ProcessListener); if (ProcessListener != null) ProcessEvents.Add(ProcessListener);

View File

@ -5,11 +5,12 @@ using System;
namespace CxbxDebugger namespace CxbxDebugger
{ {
public interface IDebuggerGeneralEvents public interface IDebuggerSessionEvents
{ {
void OnDebugStart(); void OnDebugStart();
void OnDebugEnd(); void OnDebugEnd();
void OnDebugTitleLoaded(string Title); void OnDebugTitleLoaded(string Title);
void OnDebugTargetChanged(string CommandLine);
} }
public interface IDebuggerProcessEvents public interface IDebuggerProcessEvents

View File

@ -9,15 +9,20 @@ namespace CxbxDebugger
{ {
public enum ReportType : uint public enum ReportType : uint
{ {
HLECACHE_FILE = 0x00deed00, HLECACHE_FILE = 0x1000,
KERNEL_PATCH = 0x00deed01,
FILE_OPENED = 0x00deed02,
FILE_READ = 0x00deed03,
FILE_CLOSED = 0x00deed04,
DEBUGGER_INIT = 0x00deed05,
FILE_WRITE = 0x00deed06,
OVERRIDE_EXCEPTION = 0x00ceed01, KERNEL_PATCH = 0x2000,
FILE_OPENED = 0x3000,
FILE_READ = 0x3001,
FILE_WRITE = 0x3002,
FILE_CLOSED = 0x3003,
DEBUGGER_INIT = 0x400,
DEBUGGER_NEW_TARGET = 0x401,
OVERRIDE_EXCEPTION = 0x500,
// Exception code from https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx // Exception code from https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
MS_VC_EXCEPTION = 0x406D1388, MS_VC_EXCEPTION = 0x406D1388,
@ -29,22 +34,38 @@ namespace CxbxDebugger
WCHAR, WCHAR,
}; };
public class DataProcessor
{
uint[] SourceData;
uint SourceIndex;
public DataProcessor(uint[] Data)
{
SourceData = Data;
SourceIndex = 0;
}
public uint Pop()
{
return SourceData[SourceIndex++];
}
}
public class HLECache public class HLECache
{ {
public string FileName { get; set; } public string FileName { get; set; }
} }
public static HLECache GetHLECacheReport(DebuggerThread Context, uint[] Data) public static HLECache GetHLECacheReport(DebuggerThread Context, DataProcessor Data)
{ {
HLECache Report = new HLECache(); HLECache Report = new HLECache();
StringType Type = (StringType)Data[0]; var Type = (StringType)Data.Pop();
if (Type != StringType.CHAR) if (Type != StringType.CHAR)
throw new Exception("GetHLECacheReport expects a string message"); throw new Exception("GetHLECacheReport expects a string message");
uint Length = Data[1]; var Length = Data.Pop(); ;
IntPtr MessagePtr = new IntPtr(Data[2]); var MessagePtr = new IntPtr(Data.Pop());
Report.FileName = Context.OwningProcess.ReadString(MessagePtr, Length); Report.FileName = Context.OwningProcess.ReadString(MessagePtr, Length);
@ -57,20 +78,19 @@ namespace CxbxDebugger
public IntPtr Address { get; set; } public IntPtr Address { get; set; }
} }
public static KernelPatch GetKernelPatchReport(DebuggerThread Context, uint[] Data) public static KernelPatch GetKernelPatchReport(DebuggerThread Context, DataProcessor Data)
{ {
KernelPatch Report = new KernelPatch(); KernelPatch Report = new KernelPatch();
StringType Type = (StringType)Data[0]; var Type = (StringType)Data.Pop();
if (Type != StringType.CHAR) if (Type != StringType.CHAR)
throw new Exception("GetKernelPatchReport expects a string message"); throw new Exception("GetKernelPatchReport expects a string message");
uint Length = Data[1]; var Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data[2]); var MessagePtr = new IntPtr(Data.Pop());
Report.Name = Context.OwningProcess.ReadString(MessagePtr, Length); Report.Name = Context.OwningProcess.ReadString(MessagePtr, Length);
Report.Address = new IntPtr(Data[3]); Report.Address = new IntPtr(Data.Pop());
return Report; return Report;
} }
@ -82,23 +102,21 @@ namespace CxbxDebugger
public bool Succeeded { get; set; } public bool Succeeded { get; set; }
} }
public static FileOpened GetFileOpenedReport(DebuggerThread Context, uint[] Data) public static FileOpened GetFileOpenedReport(DebuggerThread Context, DataProcessor Data)
{ {
FileOpened Report = new FileOpened(); FileOpened Report = new FileOpened();
Report.Handle = new IntPtr(Data[0]); Report.Handle = new IntPtr(Data.Pop());
StringType Type = (StringType)Data[1];
var Type = (StringType)Data.Pop();
if (Type != StringType.WCHAR) if (Type != StringType.WCHAR)
throw new Exception("GetFileOpenedReport expects a widestring message"); throw new Exception("GetFileOpenedReport expects a widestring message");
uint Length = Data[2]; var Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data[3]); var MessagePtr = new IntPtr(Data.Pop());
Report.FileName = Context.OwningProcess.ReadWString(MessagePtr, Length); Report.FileName = Context.OwningProcess.ReadWString(MessagePtr, Length);
Report.Succeeded = Data.Pop() != 0;
Report.Succeeded = Data[4] != 0;
return Report; return Report;
} }
@ -110,13 +128,13 @@ namespace CxbxDebugger
public uint Offset { get; set; } public uint Offset { get; set; }
} }
public static FileRead GetFileReadReport(DebuggerThread Context, uint[] Data) public static FileRead GetFileReadReport(DebuggerThread Context, DataProcessor Data)
{ {
FileRead Report = new FileRead(); FileRead Report = new FileRead();
Report.Handle = new IntPtr(Data[0]); Report.Handle = new IntPtr(Data.Pop());
Report.Length = Data[1]; Report.Length = Data.Pop();
Report.Offset = Data[2]; Report.Offset = Data.Pop();
return Report; return Report;
} }
@ -128,13 +146,13 @@ namespace CxbxDebugger
public uint Offset { get; set; } public uint Offset { get; set; }
} }
public static FileWrite GetFileWriteReport(DebuggerThread Context, uint[] Data) public static FileWrite GetFileWriteReport(DebuggerThread Context, DataProcessor Data)
{ {
FileWrite Report = new FileWrite(); FileWrite Report = new FileWrite();
Report.Handle = new IntPtr(Data[0]); Report.Handle = new IntPtr(Data.Pop());
Report.Length = Data[1]; Report.Length = Data.Pop();
Report.Offset = Data[2]; Report.Offset = Data.Pop();
return Report; return Report;
} }
@ -144,18 +162,20 @@ namespace CxbxDebugger
public IntPtr Handle { get; set; } public IntPtr Handle { get; set; }
} }
public static FileClosed GetFileClosedReport(DebuggerThread Context, uint[] Data) public static FileClosed GetFileClosedReport(DebuggerThread Context, DataProcessor Data)
{ {
// TODO: Restructure this library // TODO: Restructure this library
uint InvalidHandle = (uint)VsChromium.Core.Win32.Handles.NativeMethods.INVALID_HANDLE_VALUE; uint InvalidHandle = (uint)VsChromium.Core.Win32.Handles.NativeMethods.INVALID_HANDLE_VALUE;
var Handle = Data.Pop();
// Skip invalid file handles // Skip invalid file handles
if (Data[0] == InvalidHandle) if (Handle == InvalidHandle)
return null; return null;
FileClosed Report = new FileClosed(); FileClosed Report = new FileClosed();
Report.Handle = new IntPtr(Data[0]); Report.Handle = new IntPtr(Handle);
return Report; return Report;
} }
@ -169,59 +189,78 @@ namespace CxbxDebugger
public IntPtr ParameterBase { get; set; } public IntPtr ParameterBase { get; set; }
} }
public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, uint[] Data) public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, DataProcessor Data)
{ {
ExceptionHandledQuery Query = new ExceptionHandledQuery(); ExceptionHandledQuery Query = new ExceptionHandledQuery();
Query.ReponseAddr = new IntPtr(Data[0]); Query.ReponseAddr = new IntPtr(Data.Pop());
Query.ExceptionAddress = Data[1]; Query.ExceptionAddress = Data.Pop();
Query.ExceptionCode = Data[2]; Query.ExceptionCode = Data.Pop();
Query.ParameterCount = Data[3]; Query.ParameterCount = Data.Pop();
Query.ParameterBase = new IntPtr(Data[4]); Query.ParameterBase = new IntPtr(Data.Pop());
return Query; return Query;
} }
public class DebuggerInit public class DebuggerInit
{ {
public uint TitleID { get; set; }
public string Title { get; set; } public string Title { get; set; }
} }
public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, uint[] Data) public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, DataProcessor Data)
{ {
DebuggerInit Report = new DebuggerInit(); DebuggerInit Report = new DebuggerInit();
Report.TitleID = Data[0]; StringType Type = (StringType)Data.Pop();
StringType Type = (StringType)Data[1];
if (Type != StringType.CHAR) if (Type != StringType.CHAR)
throw new Exception("GetDebuggerInitReport expects a string message"); throw new Exception("GetDebuggerInitReport expects a string message");
uint Length = Data[2]; uint Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data[3]); IntPtr MessagePtr = new IntPtr(Data.Pop());
Report.Title = Context.OwningProcess.ReadString(MessagePtr, Length); Report.Title = Context.OwningProcess.ReadString(MessagePtr, Length);
return Report; return Report;
} }
public class DebuggerNewTarget
{
public string CommandLine { get; set; }
}
public static DebuggerNewTarget GetDebuggerNewTargetReport(DebuggerThread Context, DataProcessor Data)
{
var Report = new DebuggerNewTarget();
StringType Type = (StringType)Data.Pop();
if (Type != StringType.CHAR)
throw new Exception("GetDebuggerInitReport expects a string message");
uint Length = Data.Pop();
IntPtr MessagePtr = new IntPtr(Data.Pop());
Report.CommandLine = Context.OwningProcess.ReadString(MessagePtr, Length);
return Report;
}
public class MSVCThreadName public class MSVCThreadName
{ {
public string Name { get; set; } public string Name { get; set; }
public uint ThreadId { get; set; } public uint ThreadId { get; set; }
} }
public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, uint[] Data) public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, DataProcessor Data)
{ {
uint Type = Data[0]; var Type = Data.Pop();
if (Type != 0x1000) if (Type != 0x1000)
return null; return null;
string ReportName = ""; string ReportName = "";
IntPtr MessagePtr = new IntPtr(Data[1]); IntPtr MessagePtr = new IntPtr(Data.Pop());
if (MessagePtr != IntPtr.Zero) if (MessagePtr != IntPtr.Zero)
{ {
ReportName = Context.OwningProcess.ReadString(MessagePtr); ReportName = Context.OwningProcess.ReadString(MessagePtr);
@ -230,7 +269,7 @@ namespace CxbxDebugger
MSVCThreadName Report = new MSVCThreadName(); MSVCThreadName Report = new MSVCThreadName();
Report.Name = ReportName; Report.Name = ReportName;
Report.ThreadId = Data[2]; Report.ThreadId = Data.Pop();
return Report; return Report;
} }