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