Skip to content

Commit 4d1b887

Browse files
committed
Added basic "Find out what..." support.
1 parent b14132d commit 4d1b887

18 files changed

+1179
-219
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Diagnostics.Contracts;
3+
4+
namespace ReClassNET.Debugger
5+
{
6+
public class BreakpointAlreadySetException : Exception
7+
{
8+
public IBreakpoint Breakpoint { get; }
9+
10+
public BreakpointAlreadySetException(IBreakpoint breakpoint)
11+
: base("This breakpoint is already set.")
12+
{
13+
Contract.Requires(breakpoint != null);
14+
15+
Breakpoint = breakpoint;
16+
}
17+
}
18+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace ReClassNET.Debugger
4+
{
5+
public class NoHardwareBreakpointAvailableException : Exception
6+
{
7+
public NoHardwareBreakpointAvailableException()
8+
: base("All available hardware breakpoints are already set.")
9+
{
10+
11+
}
12+
}
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Diagnostics.Contracts;
7+
using System.Windows.Forms;
8+
9+
namespace ReClassNET.Debugger
10+
{
11+
public static class RemoteDebuggerExtensions
12+
{
13+
public static bool AskUserAndStartDebugger(this RemoteDebugger debugger)
14+
{
15+
Contract.Requires(debugger != null);
16+
17+
return debugger.StartDebuggerIfNeeded(
18+
() => MessageBox.Show(
19+
"This will attach the debugger of ReClass.NET to the current process. Continue?",
20+
"Confirmation",
21+
MessageBoxButtons.YesNo,
22+
MessageBoxIcon.Question
23+
) == DialogResult.Yes
24+
);
25+
}
26+
}
27+
}

Debugger/RemoteDebugger.Handler.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using ReClassNET.Native;
7+
8+
namespace ReClassNET.Debugger
9+
{
10+
public partial class RemoteDebugger
11+
{
12+
private bool HandleEvent(ref DebugEvent evt)
13+
{
14+
switch (evt.Header.Type)
15+
{
16+
case DebugEventType.CreateProcess:
17+
return HandleCreateProcessEvent(ref evt);
18+
case DebugEventType.ExitProcess:
19+
return HandleExitProcessEvent(ref evt);
20+
case DebugEventType.CreateThread:
21+
return HandleCreateThreadEvent(ref evt);
22+
case DebugEventType.ExitThread:
23+
return HandleExitThreadEvent(ref evt);
24+
case DebugEventType.LoadDll:
25+
return HandleLoadDllEvent(ref evt);
26+
case DebugEventType.UnloadDll:
27+
return HandleUnloadDllEvent(ref evt);
28+
case DebugEventType.Exception:
29+
return HandleExceptionEvent(ref evt);
30+
}
31+
32+
return true;
33+
}
34+
35+
private bool HandleCreateProcessEvent(ref DebugEvent evt)
36+
{
37+
return true;
38+
}
39+
40+
private bool HandleExitProcessEvent(ref DebugEvent evt)
41+
{
42+
return false;
43+
}
44+
45+
private bool HandleCreateThreadEvent(ref DebugEvent evt)
46+
{
47+
return true;
48+
}
49+
50+
private bool HandleExitThreadEvent(ref DebugEvent evt)
51+
{
52+
return true;
53+
}
54+
55+
private bool HandleLoadDllEvent(ref DebugEvent evt)
56+
{
57+
return true;
58+
}
59+
60+
private bool HandleUnloadDllEvent(ref DebugEvent evt)
61+
{
62+
return true;
63+
}
64+
65+
private bool HandleExceptionEvent(ref DebugEvent evt)
66+
{
67+
IBreakpoint current = null;
68+
lock (syncBreakpoint)
69+
{
70+
var causedBy = evt.Data.ExceptionInfo.CausedBy;
71+
72+
foreach (var bp in breakpoints)
73+
{
74+
var hwbp = bp as HardwareBreakpoint;
75+
if (hwbp != null)
76+
{
77+
if (causedBy == hwbp.Register)
78+
{
79+
current = bp;
80+
break;
81+
}
82+
}
83+
}
84+
}
85+
86+
if (current != null)
87+
{
88+
current.Handler(ref evt);
89+
}
90+
91+
return true;
92+
}
93+
}
94+
}

Debugger/RemoteDebugger.Thread.cs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using System;
2+
using System.Diagnostics.Contracts;
3+
using System.Threading;
4+
using ReClassNET.Native;
5+
6+
namespace ReClassNET.Debugger
7+
{
8+
public partial class RemoteDebugger
9+
{
10+
private readonly object syncThread = new object();
11+
12+
private Thread thread;
13+
14+
private volatile bool running = true;
15+
private volatile bool isAttached = false;
16+
17+
public bool IsAttached => isAttached;
18+
19+
public bool StartDebuggerIfNeeded(Func<bool> queryAttach)
20+
{
21+
Contract.Requires(queryAttach != null);
22+
23+
if (!process.IsValid)
24+
{
25+
return false;
26+
}
27+
28+
lock (syncThread)
29+
{
30+
if (thread != null && IsAttached)
31+
{
32+
return true;
33+
}
34+
35+
if (queryAttach())
36+
{
37+
thread = new Thread(Run);
38+
thread.IsBackground = true;
39+
thread.Start();
40+
41+
return true;
42+
}
43+
}
44+
45+
return false;
46+
}
47+
48+
private void Run()
49+
{
50+
try
51+
{
52+
if (!process.NativeHelper.DebuggerAttachToProcess(process.UnderlayingProcess.Id))
53+
{
54+
return;
55+
}
56+
57+
isAttached = true;
58+
59+
var ev = new DebugEvent();
60+
running = true;
61+
while (running)
62+
{
63+
if (process.NativeHelper.DebuggerWaitForDebugEvent(ref ev, 100))
64+
{
65+
ev.Header.ContinueStatus = DebugContinueStatus.Handled;
66+
67+
if (HandleEvent(ref ev))
68+
{
69+
process.NativeHelper.DebuggerContinueEvent(ref ev);
70+
}
71+
else
72+
{
73+
Terminate(false);
74+
}
75+
}
76+
else
77+
{
78+
79+
}
80+
}
81+
82+
process.NativeHelper.DebuggerDetachFromProcess(process.UnderlayingProcess.Id);
83+
}
84+
finally
85+
{
86+
isAttached = false;
87+
}
88+
}
89+
90+
public void Terminate()
91+
{
92+
Terminate(true);
93+
}
94+
95+
private void Terminate(bool join)
96+
{
97+
lock (syncBreakpoint)
98+
{
99+
foreach (var bp in breakpoints)
100+
{
101+
bp.Remove(process);
102+
}
103+
breakpoints.Clear();
104+
}
105+
106+
running = false;
107+
108+
if (join)
109+
{
110+
lock (syncThread)
111+
{
112+
if (thread != null)
113+
{
114+
thread.Join();
115+
}
116+
}
117+
}
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)