diff --git a/reactos/dll/win32/kernel32/debug/debugger.c b/reactos/dll/win32/kernel32/debug/debugger.c index 9ec67d152b8..6f50448b849 100644 --- a/reactos/dll/win32/kernel32/debug/debugger.c +++ b/reactos/dll/win32/kernel32/debug/debugger.c @@ -465,16 +465,109 @@ IsDebuggerPresent(VOID) } /* - * @unimplemented + * @implemented */ BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds) { - /* FIXME: TODO */ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + LARGE_INTEGER WaitTime; + PLARGE_INTEGER Timeout; + DBGUI_WAIT_STATE_CHANGE WaitStateChange; + NTSTATUS Status; + + /* Check if this is an infinite wait */ + if (dwMilliseconds == INFINITE) + { + /* Under NT, this means no timer argument */ + Timeout = NULL; + } + else + { + /* Otherwise, convert the time to NT Format */ + WaitTime.QuadPart = UInt32x32To64(-10000, dwMilliseconds); + Timeout = &WaitTime; + } + + /* Loop while we keep getting interrupted */ + do + { + /* Call the native API */ + Status = DbgUiWaitStateChange(&WaitStateChange, Timeout); + } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC)); + + /* Check if the wait failed */ + if (!(NT_SUCCESS(Status)) || (Status != DBG_UNABLE_TO_PROVIDE_HANDLE)) + { + /* Set the error code and quit */ + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Check if we timed out */ + if (Status == STATUS_TIMEOUT) + { + /* Fail with a timeout error */ + SetLastError(ERROR_SEM_TIMEOUT); + return FALSE; + } + + /* Convert the structure */ + Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent); + if (!NT_SUCCESS(Status)) + { + /* Set the error code and quit */ + SetLastErrorByStatus(Status); + return FALSE; + } + + /* Check what kind of event this was */ + switch (lpDebugEvent->dwDebugEventCode) + { + /* New thread was created */ + case CREATE_THREAD_DEBUG_EVENT: + + /* Setup the thread data */ + SaveThreadHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->dwThreadId, + lpDebugEvent->u.CreateThread.hThread); + break; + + /* New process was created */ + case CREATE_PROCESS_DEBUG_EVENT: + + /* Setup the process data */ + SaveProcessHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->u.CreateProcessInfo.hProcess); + + /* Setup the thread data */ + SaveThreadHandle(lpDebugEvent->dwProcessId, + lpDebugEvent->dwThreadId, + lpDebugEvent->u.CreateThread.hThread); + break; + + /* Process was exited */ + case EXIT_PROCESS_DEBUG_EVENT: + + /* Mark the thread data as such */ + MarkProcessHandle(lpDebugEvent->dwProcessId); + break; + + /* Thread was exited */ + case EXIT_THREAD_DEBUG_EVENT: + + /* Mark the thread data */ + MarkThreadHandle(lpDebugEvent->dwThreadId); + break; + + /* Nothing to do for anything else */ + default: + break; + } + + /* Return success */ + return TRUE; } /* EOF */ diff --git a/reactos/include/psdk/ntstatus.h b/reactos/include/psdk/ntstatus.h index 97b93a6a010..13c445ceb71 100644 --- a/reactos/include/psdk/ntstatus.h +++ b/reactos/include/psdk/ntstatus.h @@ -58,6 +58,7 @@ #define STATUS_WAIT_63 ((NTSTATUS)0x0000003f) #define STATUS_ABANDONED ((NTSTATUS)0x00000080) #define STATUS_ABANDONED_WAIT_63 ((NTSTATUS)0x000000BF) +#define STATUS_USER_APC ((NTSTATUS)0x000000C0) #define STATUS_KERNEL_APC ((NTSTATUS)0x00000100) #define STATUS_ALERTED ((NTSTATUS)0x00000101) #define STATUS_TIMEOUT ((NTSTATUS)0x00000102)