From 561c27e0d308b51d2339a62a02656f217b567a08 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 28 Jun 2006 17:02:37 +0000 Subject: [PATCH] - Implement, export and NDKize: DbgUiGetThreadDebugObject, DbgUiDebugActiveProcess, DbgUiStopDebugging, NtSetInformationDebugObject. - Make CheckRemoteDebuggerPresent fail if no process was specified. - Implement DebugActiveProcess, DebugActiveProcessStop, DebugBreakProcess, DebugSetProcessKillOnExit. - Add *.vcproj to ignore lists. svn path=/trunk/; revision=22675 --- reactos/dll/ntdll/dbg/dbgui.c | 58 +++- reactos/dll/ntdll/def/ntdll.def | 4 + reactos/dll/win32/kernel32/debug/break.c | 32 -- reactos/dll/win32/kernel32/debug/debugger.c | 278 ++++++++++++------ reactos/dll/win32/kernel32/include/kernel32.h | 3 + reactos/dll/win32/kernel32/kernel32.rbuild | 1 - reactos/dll/win32/kernel32/misc/console.c | 4 +- reactos/include/ndk/dbgkfuncs.h | 55 ++++ reactos/include/ndk/umfuncs.h | 24 ++ reactos/tools/nci/sysfuncs.lst | 3 + 10 files changed, 340 insertions(+), 122 deletions(-) delete mode 100644 reactos/dll/win32/kernel32/debug/break.c diff --git a/reactos/dll/ntdll/dbg/dbgui.c b/reactos/dll/ntdll/dbg/dbgui.c index 33c37b26eb8..b1d3423b20e 100644 --- a/reactos/dll/ntdll/dbg/dbgui.c +++ b/reactos/dll/ntdll/dbg/dbgui.c @@ -1,9 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: lib/ntdll/dbg/dbgui.c - * PURPOSE: User-Mode DbgUI Support - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * PROJECT: ReactOS NT Layer/System API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/ntdll/dbg/dbgui.c + * PURPOSE: Native Wrappers for the NT Debug Implementation + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES *****************************************************************/ @@ -135,4 +135,52 @@ DbgUiIssueRemoteBreakin(HANDLE Process) return Status; } +/* + * @implemented + */ +HANDLE +NTAPI +DbgUiGetThreadDebugObject(VOID) +{ + /* Just return the handle from the TEB */ + return NtCurrentTeb()->DbgSsReserved[0]; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +DbgUiDebugActiveProcess(IN HANDLE Process) +{ + NTSTATUS Status; + + /* Tell the kernel to start debugging */ + Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[0]); + if (NT_SUCCESS(Status)) + { + /* Now break-in the process */ + Status = DbgUiIssueRemoteBreakin(Process); + if (!NT_SUCCESS(Status)) + { + /* We couldn't break-in, cancel debugging */ + DbgUiStopDebugging(Process); + } + } + + /* Return status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +DbgUiStopDebugging(IN HANDLE Process) +{ + /* Call the kernel to remove the debug object */ + return NtRemoveProcessDebug(Process, NtCurrentTeb()->DbgSsReserved[0]); +} + /* EOF */ diff --git a/reactos/dll/ntdll/def/ntdll.def b/reactos/dll/ntdll/def/ntdll.def index 8c9f10ee254..c0d5eaf6810 100644 --- a/reactos/dll/ntdll/def/ntdll.def +++ b/reactos/dll/ntdll/def/ntdll.def @@ -24,10 +24,13 @@ DbgBreakPoint@0 DbgPrint DbgPrintEx DbgPrompt@12 +DbgUiDebugActiveProcess@4 DbgUiConnectToDbg@0 DbgUiContinue@8 +DbgUiGetThreadDebugObject@0 DbgUiIssueRemoteBreakin@4 DbgUiRemoteBreakin@0 +DbgUiStopDebugging@4 DbgUiWaitStateChange@8 DbgUserBreakPoint@0 KiRaiseUserExceptionDispatcher@0 @@ -230,6 +233,7 @@ NtSetEaFile@16 NtSetEvent@8 NtSetHighEventPair@4 NtSetHighWaitLowEventPair@4 +NtSetInformationDebugObject@20 NtSetInformationFile@20 NtSetInformationJobObject@16 NtSetInformationKey@16 diff --git a/reactos/dll/win32/kernel32/debug/break.c b/reactos/dll/win32/kernel32/debug/break.c deleted file mode 100644 index c91b62f82f0..00000000000 --- a/reactos/dll/win32/kernel32/debug/break.c +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/debug/debugger.c - * PURPOSE: DebugBreakProcess() - * PROGRAMMER: KJK::Hyperion - */ - -/* INCLUDES ******************************************************************/ - -#include - -/* FUNCTIONS *****************************************************************/ - -/* - * @implemented - */ -WINBASEAPI BOOL WINAPI DebugBreakProcess(HANDLE Process) -{ - NTSTATUS nErrCode = DbgUiIssueRemoteBreakin(Process); - - if(!NT_SUCCESS(nErrCode)) - { - SetLastErrorByStatus(nErrCode); - return FALSE; - } - - return TRUE; -} - -/* EOF */ diff --git a/reactos/dll/win32/kernel32/debug/debugger.c b/reactos/dll/win32/kernel32/debug/debugger.c index b827b7b3e97..4a9688b8d2f 100644 --- a/reactos/dll/win32/kernel32/debug/debugger.c +++ b/reactos/dll/win32/kernel32/debug/debugger.c @@ -1,123 +1,239 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/kernel32/debug/debugger.c - * PURPOSE: Win32 Debugger API - * PROGRAMMER: Thomas Weidenmueller - * KJK::Hyperion +/* + * PROJECT: ReactOS Win32 Base API + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/kernel32/debug/debugger.c + * PURPOSE: Wrappers for the NT Debug Implementation + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *****************************************************************/ #include +#define NDEBUG +#include "debug.h" + /* FUNCTIONS *****************************************************************/ /* * @implemented */ -BOOL WINAPI -CheckRemoteDebuggerPresent ( - HANDLE hProcess, - PBOOL pbDebuggerPresent - ) +BOOL +WINAPI +CheckRemoteDebuggerPresent(IN HANDLE hProcess, + OUT PBOOL pbDebuggerPresent) { - HANDLE DebugPort; - NTSTATUS Status; + HANDLE DebugPort; + NTSTATUS Status; - if (pbDebuggerPresent == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); + /* Make sure we have an output and process*/ + if (!(pbDebuggerPresent) || !(hProcess)) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Check if the process has a debug object/port */ + Status = NtQueryInformationProcess(hProcess, + ProcessDebugPort, + (PVOID)&DebugPort, + sizeof(HANDLE), + NULL); + if (NT_SUCCESS(Status)) + { + /* Return the current state */ + *pbDebuggerPresent = (DebugPort) ? TRUE : FALSE; + return TRUE; + } + + /* Otherwise, fail */ + SetLastErrorByStatus(Status); return FALSE; - } - - Status = NtQueryInformationProcess(hProcess, - ProcessDebugPort, - (PVOID)&DebugPort, - sizeof(HANDLE), - NULL); - if (NT_SUCCESS(Status)) - { - *pbDebuggerPresent = ((DebugPort != NULL) ? TRUE : FALSE); - return TRUE; - } - - SetLastErrorByStatus(Status); - return FALSE; } - /* * @implemented */ -BOOL WINAPI -ContinueDebugEvent ( - DWORD dwProcessId, - DWORD dwThreadId, - DWORD dwContinueStatus - ) +BOOL +WINAPI +ContinueDebugEvent(IN DWORD dwProcessId, + IN DWORD dwThreadId, + IN DWORD dwContinueStatus) { - CLIENT_ID ClientId; - NTSTATUS Status; + CLIENT_ID ClientId; + NTSTATUS Status; - ClientId.UniqueProcess = (HANDLE)dwProcessId; - ClientId.UniqueThread = (HANDLE)dwThreadId; + /* Set the Client ID */ + ClientId.UniqueProcess = (HANDLE)dwProcessId; + ClientId.UniqueThread = (HANDLE)dwThreadId; - Status = DbgUiContinue(&ClientId, dwContinueStatus); - if (!NT_SUCCESS(Status)) - { - SetLastErrorByStatus(Status); - return FALSE; - } + /* Continue debugging */ + Status = DbgUiContinue(&ClientId, dwContinueStatus); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastErrorByStatus(Status); + return FALSE; + } - return TRUE; + /* Succes */ + return TRUE; } +HANDLE +ProcessIdToHandle(IN DWORD dwProcessId) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + CLIENT_ID ClientId; + + /* If we don't have a PID, look it up */ + if (dwProcessId == 0xFFFFFFFF) dwProcessId = (DWORD)CsrGetProcessId(); + + /* Open a handle to the process */ + ClientId.UniqueProcess = (HANDLE)dwProcessId; + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + Status = NtOpenProcess(&Handle, + PROCESS_ALL_ACCESS, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastErrorByStatus(Status); + return 0; + } + + /* Return the handle */ + return Handle; +} /* - * NOTE: I'm not sure if the function is complete. - * - * @unimplemented + * @implemented */ BOOL WINAPI -DebugActiveProcess( - DWORD dwProcessId - ) +DebugActiveProcess(IN DWORD dwProcessId) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS Status; + HANDLE Handle; + + /* Connect to the debugger */ + Status = DbgUiConnectToDbg(); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Get the process handle */ + Handle = ProcessIdToHandle(dwProcessId); + if (!Handle) return FALSE; + + /* Now debug the process */ + Status = DbgUiDebugActiveProcess(Handle); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Success */ + return TRUE; } - /* - * @unimplemented + * @implemented */ BOOL WINAPI -DebugActiveProcessStop ( - DWORD dwProcessId - ) +DebugActiveProcessStop(IN DWORD dwProcessId) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS Status; + HANDLE Handle; + + /* Get the process handle */ + Handle = ProcessIdToHandle(dwProcessId); + if (!Handle) return FALSE; + + /* Now stop debgging the process */ + Status = DbgUiStopDebugging(Handle); + NtClose(Handle); + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + + /* Success */ + return TRUE; } - /* - * @unimplemented + * @implemented */ BOOL WINAPI -DebugSetProcessKillOnExit ( - BOOL KillOnExit - ) +DebugBreakProcess(IN HANDLE Process) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS Status; + + /* Send the breakin request */ + Status = DbgUiIssueRemoteBreakin(Process); + if(!NT_SUCCESS(Status)) + { + /* Failure */ + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Success */ + return TRUE; } +/* + * @implemented + */ +BOOL +WINAPI +DebugSetProcessKillOnExit(IN BOOL KillOnExit) +{ + HANDLE Handle; + NTSTATUS Status; + ULONG State; + + /* Get the debug object */ + Handle = DbgUiGetThreadDebugObject(); + if (!Handle) + { + /* Fail */ + SetLastErrorByStatus(STATUS_INVALID_HANDLE); + return FALSE; + } + + /* Now set the kill-on-exit state */ + State = KillOnExit; + Status = NtSetInformationDebugObject(Handle, + DebugObjectKillProcessOnExitInformation, + &State, + sizeof(State), + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + SetLastError(Status); + return FALSE; + } + + /* Success */ + return TRUE; +} /* * @implemented @@ -126,22 +242,20 @@ BOOL WINAPI IsDebuggerPresent (VOID) { - return (BOOL)NtCurrentPeb()->BeingDebugged; + return (BOOL)NtCurrentPeb()->BeingDebugged; } - /* * @unimplemented */ BOOL WINAPI -WaitForDebugEvent ( - LPDEBUG_EVENT lpDebugEvent, - DWORD dwMilliseconds - ) +WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, + DWORD dwMilliseconds) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + /* FIXME: TODO */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; } /* EOF */ diff --git a/reactos/dll/win32/kernel32/include/kernel32.h b/reactos/dll/win32/kernel32/include/kernel32.h index 5decc1c1b61..9966f31729e 100755 --- a/reactos/dll/win32/kernel32/include/kernel32.h +++ b/reactos/dll/win32/kernel32/include/kernel32.h @@ -63,6 +63,9 @@ BOOL STDCALL VerifyConsoleIoHandle(HANDLE Handle); BOOL STDCALL CloseConsoleHandle(HANDLE Handle); +HANDLE STDCALL +GetConsoleInputWaitHandle (VOID); + HANDLE STDCALL OpenConsoleW (LPWSTR wsName, DWORD dwDesiredAccess, BOOL bInheritHandle, diff --git a/reactos/dll/win32/kernel32/kernel32.rbuild b/reactos/dll/win32/kernel32/kernel32.rbuild index f1d419577f8..603704fc5ed 100644 --- a/reactos/dll/win32/kernel32/kernel32.rbuild +++ b/reactos/dll/win32/kernel32/kernel32.rbuild @@ -10,7 +10,6 @@ 0x502 k32.h - break.c debugger.c output.c diff --git a/reactos/dll/win32/kernel32/misc/console.c b/reactos/dll/win32/kernel32/misc/console.c index ed52f71e3e9..2f91486efad 100644 --- a/reactos/dll/win32/kernel32/misc/console.c +++ b/reactos/dll/win32/kernel32/misc/console.c @@ -567,7 +567,7 @@ GetConsoleHardwareState (HANDLE hConsole, /* * @implemented */ -DWORD STDCALL +HANDLE STDCALL GetConsoleInputWaitHandle (VOID) /* * Undocumented @@ -585,7 +585,7 @@ GetConsoleInputWaitHandle (VOID) SetLastErrorByStatus(Status); return 0; } - return (DWORD) Request.Data.GetConsoleInputWaitHandle.InputWaitHandle; + return Request.Data.GetConsoleInputWaitHandle.InputWaitHandle; } diff --git a/reactos/include/ndk/dbgkfuncs.h b/reactos/include/ndk/dbgkfuncs.h index b53cdf7f5d4..a00efca82cd 100644 --- a/reactos/include/ndk/dbgkfuncs.h +++ b/reactos/include/ndk/dbgkfuncs.h @@ -23,10 +23,19 @@ Author: // Dependencies // #include +#include // // Native calls // +NTSYSCALLAPI +NTSTATUS +NTAPI +NtDebugActiveProcess( + IN HANDLE Process, + IN HANDLE DebugObject +); + NTSYSCALLAPI NTSTATUS NTAPI @@ -56,6 +65,33 @@ NtWaitForDebugEvent( OUT PDBGUI_WAIT_STATE_CHANGE StateChange ); +NTSYSCALLAPI +NTSTATUS +NTAPI +NtRemoveProcessDebug( + IN HANDLE Process, + IN HANDLE DebugObject +); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtSetInformationDebugObject( + IN HANDLE DebugObject, + IN DEBUGOBJECTINFOCLASS InformationClass, + IN PVOID Information, + IN ULONG InformationLength, + OUT PULONG ReturnLength OPTIONAL +); + +NTSYSAPI +NTSTATUS +NTAPI +ZwDebugActiveProcess( + IN HANDLE Process, + IN HANDLE DebugObject +); + NTSYSAPI NTSTATUS NTAPI @@ -75,6 +111,14 @@ ZwDebugContinue( IN NTSTATUS ContinueStatus ); +NTSYSAPI +NTSTATUS +NTAPI +ZwRemoveProcessDebug( + IN HANDLE Process, + IN HANDLE DebugObject +); + NTSYSAPI NTSTATUS NTAPI @@ -84,4 +128,15 @@ ZwWaitForDebugEvent( IN PLARGE_INTEGER Timeout OPTIONAL, OUT PDBGUI_WAIT_STATE_CHANGE StateChange ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwSetInformationDebugObject( + IN HANDLE DebugObject, + IN DEBUGOBJECTINFOCLASS InformationClass, + IN PVOID Information, + IN ULONG InformationLength, + OUT PULONG ReturnLength OPTIONAL +); #endif diff --git a/reactos/include/ndk/umfuncs.h b/reactos/include/ndk/umfuncs.h index 3747f391ae3..1850090a25b 100644 --- a/reactos/include/ndk/umfuncs.h +++ b/reactos/include/ndk/umfuncs.h @@ -89,6 +89,12 @@ CsrFreeCaptureBuffer( struct _CSR_CAPTURE_BUFFER *CaptureBuffer ); +HANDLE +NTAPI +CsrGetProcessId( + VOID +); + NTSTATUS NTAPI CsrNewThread(VOID); @@ -139,6 +145,18 @@ DbgUiContinue( IN ULONG ContinueStatus ); +NTSTATUS +NTAPI +DbgUiDebugActiveProcess( + IN HANDLE Process +); + +NTSTATUS +NTAPI +DbgUiStopDebugging( + IN HANDLE Process +); + NTSTATUS NTAPI DbgUiWaitStateChange( @@ -158,6 +176,12 @@ DbgUiIssueRemoteBreakin( IN HANDLE Process ); +HANDLE +NTAPI +DbgUiGetThreadDebugObject( + VOID +); + // // Loader Functions // diff --git a/reactos/tools/nci/sysfuncs.lst b/reactos/tools/nci/sysfuncs.lst index 57afeb9cab3..b8c2e5e8bc8 100644 --- a/reactos/tools/nci/sysfuncs.lst +++ b/reactos/tools/nci/sysfuncs.lst @@ -42,6 +42,7 @@ NtCreateThread 8 NtCreateTimer 4 NtCreateToken 13 NtCreateWaitablePort 5 +NtDebugActiveProcess 2 NtDebugContinue 3 NtDelayExecution 2 NtDeleteAtom 1 @@ -162,6 +163,7 @@ NtRegisterThreadTerminatePort 1 NtReleaseMutant 2 NtReleaseSemaphore 3 NtRemoveIoCompletion 5 +NtRemoveProcessDebug 2 NtReplaceKey 3 NtReplyPort 2 NtReplyWaitReceivePort 4 @@ -188,6 +190,7 @@ NtSetEaFile 4 NtSetEvent 2 NtSetHighEventPair 1 NtSetHighWaitLowEventPair 1 +NtSetInformationDebugObject 5 NtSetInformationFile 5 NtSetInformationKey 4 NtSetInformationJobObject 4