ReactOS 0.4.15-dev-8109-gd7be748
dbgui.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS NT Layer/System API
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/ntdll/dbg/dbgui.c
5 * PURPOSE: Native Wrappers for the NT Debug Implementation
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <ntdll.h>
12
13#include <ndk/dbgkfuncs.h>
14
15#define NDEBUG
16#include <debug.h>
17
18/* FUNCTIONS *****************************************************************/
19
20/*
21 * @implemented
22 */
26{
28
29 /* Don't connect twice */
30 if (NtCurrentTeb()->DbgSsReserved[1]) return STATUS_SUCCESS;
31
32 /* Setup the Attributes */
34
35 /* Create the object */
36 return ZwCreateDebugObject(&NtCurrentTeb()->DbgSsReserved[1],
40}
41
42/*
43 * @implemented
44 */
48 IN NTSTATUS ContinueStatus)
49{
50 /* Tell the kernel object to continue */
51 return ZwDebugContinue(NtCurrentTeb()->DbgSsReserved[1],
53 ContinueStatus);
54}
55
56/*
57 * @implemented
58 */
62 OUT PVOID Win32DebugEvent)
63{
65 THREAD_BASIC_INFORMATION ThreadBasicInfo;
66 LPDEBUG_EVENT DebugEvent = Win32DebugEvent;
67
68 /* Write common data */
69 DebugEvent->dwProcessId = PtrToUlong(WaitStateChange->AppClientId.UniqueProcess);
70 DebugEvent->dwThreadId = PtrToUlong(WaitStateChange->AppClientId.UniqueThread);
71
72 /* Check what kind of even this is */
73 switch (WaitStateChange->NewState)
74 {
75 /* New thread */
77 {
78 /* Setup Win32 code */
79 DebugEvent->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
80
81 /* Copy data over */
82 DebugEvent->u.CreateThread.hThread =
83 WaitStateChange->StateInfo.CreateThread.HandleToThread;
84 DebugEvent->u.CreateThread.lpStartAddress =
85 WaitStateChange->StateInfo.CreateThread.NewThread.StartAddress;
86
87 /* Query the TEB */
88 Status = NtQueryInformationThread(WaitStateChange->StateInfo.
89 CreateThread.HandleToThread,
91 &ThreadBasicInfo,
92 sizeof(ThreadBasicInfo),
93 NULL);
94 if (!NT_SUCCESS(Status))
95 {
96 /* Failed to get PEB address */
97 DebugEvent->u.CreateThread.lpThreadLocalBase = NULL;
98 }
99 else
100 {
101 /* Write PEB Address */
102 DebugEvent->u.CreateThread.lpThreadLocalBase =
103 ThreadBasicInfo.TebBaseAddress;
104 }
105 break;
106 }
107
108 /* New process */
110 {
111 /* Write Win32 debug code */
112 DebugEvent->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
113
114 /* Copy data over */
115 DebugEvent->u.CreateProcessInfo.hProcess =
116 WaitStateChange->StateInfo.CreateProcessInfo.HandleToProcess;
117 DebugEvent->u.CreateProcessInfo.hThread =
118 WaitStateChange->StateInfo.CreateProcessInfo.HandleToThread;
119 DebugEvent->u.CreateProcessInfo.hFile =
120 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
122 DebugEvent->u.CreateProcessInfo.lpBaseOfImage =
123 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
124 BaseOfImage;
125 DebugEvent->u.CreateProcessInfo.dwDebugInfoFileOffset =
126 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
127 DebugInfoFileOffset;
128 DebugEvent->u.CreateProcessInfo.nDebugInfoSize =
129 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
130 DebugInfoSize;
131 DebugEvent->u.CreateProcessInfo.lpStartAddress =
132 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
133 InitialThread.StartAddress;
134
135 /* Query TEB address */
136 Status = NtQueryInformationThread(WaitStateChange->StateInfo.
137 CreateProcessInfo.HandleToThread,
139 &ThreadBasicInfo,
140 sizeof(ThreadBasicInfo),
141 NULL);
142 if (!NT_SUCCESS(Status))
143 {
144 /* Failed to get PEB address */
145 DebugEvent->u.CreateProcessInfo.lpThreadLocalBase = NULL;
146 }
147 else
148 {
149 /* Write PEB Address */
150 DebugEvent->u.CreateProcessInfo.lpThreadLocalBase =
151 ThreadBasicInfo.TebBaseAddress;
152 }
153
154 /* Clear image name */
155 DebugEvent->u.CreateProcessInfo.lpImageName = NULL;
156 DebugEvent->u.CreateProcessInfo.fUnicode = TRUE;
157 break;
158 }
159
160 /* Thread exited */
162 {
163 /* Write the Win32 debug code and the exit status */
164 DebugEvent->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
165 DebugEvent->u.ExitThread.dwExitCode =
166 WaitStateChange->StateInfo.ExitThread.ExitStatus;
167 break;
168 }
169
170 /* Process exited */
172 {
173 /* Write the Win32 debug code and the exit status */
174 DebugEvent->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
175 DebugEvent->u.ExitProcess.dwExitCode =
176 WaitStateChange->StateInfo.ExitProcess.ExitStatus;
177 break;
178 }
179
180 /* Any sort of exception */
184 {
185 /* Check if this was a debug print */
186 if (WaitStateChange->StateInfo.Exception.ExceptionRecord.
188 {
189 /* Set the Win32 code */
190 DebugEvent->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
191
192 /* Copy debug string information */
193 DebugEvent->u.DebugString.lpDebugStringData =
194 (PVOID)WaitStateChange->
195 StateInfo.Exception.ExceptionRecord.
196 ExceptionInformation[1];
197 DebugEvent->u.DebugString.nDebugStringLength =
198 WaitStateChange->StateInfo.Exception.ExceptionRecord.
199 ExceptionInformation[0];
200 DebugEvent->u.DebugString.fUnicode = FALSE;
201 }
202 else if (WaitStateChange->StateInfo.Exception.ExceptionRecord.
204 {
205 /* Set the Win32 code */
206 DebugEvent->dwDebugEventCode = RIP_EVENT;
207
208 /* Set exception information */
209 DebugEvent->u.RipInfo.dwType =
210 WaitStateChange->StateInfo.Exception.ExceptionRecord.
211 ExceptionInformation[1];
212 DebugEvent->u.RipInfo.dwError =
213 WaitStateChange->StateInfo.Exception.ExceptionRecord.
214 ExceptionInformation[0];
215 }
216 else
217 {
218 /* Otherwise, this is a debug event, copy info over */
219 DebugEvent->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
220 DebugEvent->u.Exception.ExceptionRecord =
221 WaitStateChange->StateInfo.Exception.ExceptionRecord;
222 DebugEvent->u.Exception.dwFirstChance =
223 WaitStateChange->StateInfo.Exception.FirstChance;
224 }
225 break;
226 }
227
228 /* DLL Load */
230 {
231 /* Set the Win32 debug code */
232 DebugEvent->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
233
234 /* Copy the rest of the data */
235 DebugEvent->u.LoadDll.hFile =
236 WaitStateChange->StateInfo.LoadDll.FileHandle;
237 DebugEvent->u.LoadDll.lpBaseOfDll =
238 WaitStateChange->StateInfo.LoadDll.BaseOfDll;
239 DebugEvent->u.LoadDll.dwDebugInfoFileOffset =
240 WaitStateChange->StateInfo.LoadDll.DebugInfoFileOffset;
241 DebugEvent->u.LoadDll.nDebugInfoSize =
242 WaitStateChange->StateInfo.LoadDll.DebugInfoSize;
243 DebugEvent->u.LoadDll.lpImageName =
244 WaitStateChange->StateInfo.LoadDll.NamePointer;
245
246 /* It's Unicode */
247 DebugEvent->u.LoadDll.fUnicode = TRUE;
248 break;
249 }
250
251 /* DLL Unload */
253 {
254 /* Set Win32 code and DLL Base */
255 DebugEvent->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
256 DebugEvent->u.UnloadDll.lpBaseOfDll =
257 WaitStateChange->StateInfo.UnloadDll.BaseAddress;
258 break;
259 }
260
261 /* Anything else, fail */
262 default: return STATUS_UNSUCCESSFUL;
263 }
264
265 /* Return success */
266 return STATUS_SUCCESS;
267}
268
269/*
270 * @implemented
271 */
273NTAPI
275 IN PLARGE_INTEGER TimeOut OPTIONAL)
276{
277 /* Tell the kernel to wait */
278 return NtWaitForDebugEvent(NtCurrentTeb()->DbgSsReserved[1],
279 TRUE,
280 TimeOut,
281 WaitStateChange);
282}
283
284/*
285 * @implemented
286 */
287VOID
288NTAPI
290{
291 /* Make sure a debugger is enabled; if so, breakpoint */
292 if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
293
294 /* Exit the thread */
296}
297
298/*
299 * @implemented
300 */
302NTAPI
304{
308
309 /* Create the thread that will do the breakin */
311 NULL,
312 FALSE,
313 0,
314 0,
315 PAGE_SIZE,
317 NULL,
318 &hThread,
319 &ClientId);
320
321 /* Close the handle on success */
323
324 /* Return status */
325 return Status;
326}
327
328/*
329 * @implemented
330 */
331HANDLE
332NTAPI
334{
335 /* Just return the handle from the TEB */
336 return NtCurrentTeb()->DbgSsReserved[1];
337}
338
339/*
340* @implemented
341*/
342VOID
343NTAPI
345{
346 /* Just set the handle in the TEB */
347 NtCurrentTeb()->DbgSsReserved[1] = DebugObject;
348}
349
350/*
351 * @implemented
352 */
354NTAPI
356{
358
359 /* Tell the kernel to start debugging */
360 Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]);
361 if (NT_SUCCESS(Status))
362 {
363 /* Now break-in the process */
365 if (!NT_SUCCESS(Status))
366 {
367 /* We couldn't break-in, cancel debugging */
369 }
370 }
371
372 /* Return status */
373 return Status;
374}
375
376/*
377 * @implemented
378 */
380NTAPI
382{
383 /* Call the kernel to remove the debug object */
384 return NtRemoveProcessDebug(Process, NtCurrentTeb()->DbgSsReserved[1]);
385}
386
387/* EOF */
#define NtCurrentPeb()
Definition: FLS.c:22
LONG NTSTATUS
Definition: precomp.h:26
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
SIZE_T LPDEBUG_EVENT
Definition: cordebug.idl:83
NTSYSAPI NTSTATUS NTAPI ZwDebugContinue(_In_ HANDLE DebugObject, _In_ PCLIENT_ID AppClientId, _In_ NTSTATUS ContinueStatus)
NTSYSAPI NTSTATUS NTAPI ZwCreateDebugObject(_Out_ PHANDLE DebugHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ ULONG Flags)
NTSTATUS NTAPI NtRemoveProcessDebug(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1873
NTSTATUS NTAPI NtDebugActiveProcess(IN HANDLE ProcessHandle, IN HANDLE DebugHandle)
Definition: dbgkobj.c:1797
NTSTATUS NTAPI NtWaitForDebugEvent(IN HANDLE DebugHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
Definition: dbgkobj.c:2001
#define DEBUG_OBJECT_ALL_ACCESS
Definition: dbgktypes.h:34
#define DBGK_KILL_PROCESS_ON_EXIT
Definition: dbgktypes.h:49
@ DbgBreakpointStateChange
Definition: dbgktypes.h:120
@ DbgCreateProcessStateChange
Definition: dbgktypes.h:116
@ DbgCreateThreadStateChange
Definition: dbgktypes.h:115
@ DbgExitProcessStateChange
Definition: dbgktypes.h:118
@ DbgExceptionStateChange
Definition: dbgktypes.h:119
@ DbgUnloadDllStateChange
Definition: dbgktypes.h:123
@ DbgExitThreadStateChange
Definition: dbgktypes.h:117
@ DbgSingleStepStateChange
Definition: dbgktypes.h:121
@ DbgLoadDllStateChange
Definition: dbgktypes.h:122
NTSTATUS NTAPI DbgUiContinue(IN PCLIENT_ID ClientId, IN NTSTATUS ContinueStatus)
Definition: dbgui.c:47
NTSTATUS NTAPI DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, OUT PVOID Win32DebugEvent)
Definition: dbgui.c:61
NTSTATUS NTAPI DbgUiDebugActiveProcess(IN HANDLE Process)
Definition: dbgui.c:355
NTSTATUS NTAPI DbgUiIssueRemoteBreakin(IN HANDLE Process)
Definition: dbgui.c:303
NTSTATUS NTAPI DbgUiStopDebugging(IN HANDLE Process)
Definition: dbgui.c:381
NTSTATUS NTAPI DbgUiConnectToDbg(VOID)
Definition: dbgui.c:25
NTSTATUS NTAPI DbgUiWaitStateChange(OUT PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PLARGE_INTEGER TimeOut OPTIONAL)
Definition: dbgui.c:274
HANDLE NTAPI DbgUiGetThreadDebugObject(VOID)
Definition: dbgui.c:333
VOID NTAPI DbgUiRemoteBreakin(VOID)
Definition: dbgui.c:289
VOID NTAPI DbgUiSetThreadDebugObject(HANDLE DebugObject)
Definition: dbgui.c:344
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
@ ThreadBasicInformation
Definition: compat.h:935
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
#define PtrToUlong(u)
Definition: config.h:107
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define NtCurrentTeb
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI VOID NTAPI RtlExitUserThread(_In_ NTSTATUS Status)
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
HANDLE hThread
Definition: wizard.c:28
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
#define DBG_RIPEXCEPTION
Definition: ntstatus.h:54
#define DBG_PRINTEXCEPTION_C
Definition: ntstatus.h:53
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
#define DebugEvent(tess)
Definition: sweep.c:59
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define RIP_EVENT
Definition: winbase.h:110
#define CREATE_PROCESS_DEBUG_EVENT
Definition: winbase.h:104
#define LOAD_DLL_DEBUG_EVENT
Definition: winbase.h:107
#define EXIT_PROCESS_DEBUG_EVENT
Definition: winbase.h:106
#define OUTPUT_DEBUG_STRING_EVENT
Definition: winbase.h:109
#define EXCEPTION_DEBUG_EVENT
Definition: winbase.h:102
#define CREATE_THREAD_DEBUG_EVENT
Definition: winbase.h:103
#define UNLOAD_DLL_DEBUG_EVENT
Definition: winbase.h:108
#define EXIT_THREAD_DEBUG_EVENT
Definition: winbase.h:105
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151