Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/debugger.c | 62 +++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index a2b5d1f410e..7fe4f872282 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -309,6 +309,56 @@ static void fetch_process_context(struct debugger_context *ctx) #define WAIT_EVENT_TIMEOUT 20000 #define POLL_EVENT_TIMEOUT 200
+#define test_reply_later(a) test_reply_later_(__LINE__,a) +static void test_reply_later_(unsigned int line, struct debugger_context *ctx) +{ + DEBUG_EVENT de0, de1; + HANDLE thread; + NTSTATUS status; + + if (!ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER)) + todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + else + { + ok_(__FILE__,line)(WaitForDebugEvent(&de0, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError()); + ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de0.dwDebugEventCode, + "delayed event differ, code:%x was:%x\n", de0.dwDebugEventCode, ctx->ev.dwDebugEventCode); + ok_(__FILE__,line)(ctx->ev.dwProcessId == de0.dwProcessId, + "delayed event differ, pid:%x was:%x\n", de0.dwProcessId, ctx->ev.dwProcessId); + ok_(__FILE__,line)(ctx->ev.dwThreadId == de0.dwThreadId, + "delayed event differ, tid:%x was:%x\n", de0.dwThreadId, ctx->ev.dwThreadId); + + if (ctx->ev.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != EXIT_THREAD_DEBUG_EVENT && + ctx->ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) + { + thread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ctx->ev.dwThreadId); + ok_(__FILE__,line)(thread != INVALID_HANDLE_VALUE, "OpenThread failed, last error:%u\n", GetLastError()); + + status = NtSuspendThread(thread, NULL); + ok_(__FILE__,line)(!status, "NtSuspendThread failed, last error:%u\n", GetLastError()); + + ok_(__FILE__,line)(ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + + ok_(__FILE__,line)(!WaitForDebugEvent(&de1, 50), "WaitForDebugEvent succeeded.\n"); + status = NtResumeThread(thread, NULL); + + ok_(__FILE__,line)(!status, "NtResumeThread failed, last error:%u\n", GetLastError()); + CloseHandle(thread); + + ok_(__FILE__,line)(WaitForDebugEvent(&de1, 50), "WaitForDebugEvent failed, last error:%u\n", GetLastError()); + ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == de1.dwDebugEventCode, + "delayed event differ, code:%x was:%x\n", de1.dwDebugEventCode, ctx->ev.dwDebugEventCode); + ok_(__FILE__,line)(ctx->ev.dwProcessId == de1.dwProcessId, + "delayed event differ, pid:%x was:%x\n", de1.dwProcessId, ctx->ev.dwProcessId); + ok_(__FILE__,line)(ctx->ev.dwThreadId == de1.dwThreadId, + "delayed event differ, tid:%x was:%x\n", de1.dwThreadId, ctx->ev.dwThreadId); + } + } +} + #define next_event(a,b) next_event_(__LINE__,a,b) static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout) { @@ -1273,7 +1323,11 @@ static void test_debugger(const char *argv0) next_event(&ctx, WAIT_EVENT_TIMEOUT); ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); wait_for_breakpoint(&ctx); - do next_event(&ctx, POLL_EVENT_TIMEOUT); + do + { + test_reply_later(&ctx); + next_event(&ctx, POLL_EVENT_TIMEOUT); + } while(ctx.ev.dwDebugEventCode != -1);
mem = VirtualAllocEx(pi.hProcess, NULL, sizeof(buf), MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -1297,6 +1351,7 @@ static void test_debugger(const char *argv0) debuggee_thread = get_debuggee_thread(&ctx, ctx.ev.dwThreadId);
wait_for_breakpoint(&ctx); + test_reply_later(&ctx); fetch_thread_context(debuggee_thread); ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == thread_proc, "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress); @@ -1304,8 +1359,11 @@ static void test_debugger(const char *argv0) get_ip(&debuggee_thread->ctx));
single_step(&ctx, debuggee_thread, thread_proc + 2); + test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc + 3); + test_reply_later(&ctx); single_step(&ctx, debuggee_thread, thread_proc); + test_reply_later(&ctx);
byte = 0xc3; /* ret */ ret = WriteProcessMemory(pi.hProcess, thread_proc, &byte, 1, NULL); @@ -1328,6 +1386,7 @@ static void test_debugger(const char *argv0) ok(thread != NULL, "CreateRemoteThread failed: %u\n", GetLastError()); expect_event(&ctx, CREATE_THREAD_DEBUG_EVENT); expect_breakpoint_exception(&ctx, NULL); + test_reply_later(&ctx); expect_event(&ctx, EXIT_THREAD_DEBUG_EVENT);
/* BREAKPOINT_PROMPT */ @@ -1422,6 +1481,7 @@ static void test_debugger(const char *argv0)
do { + test_reply_later(&ctx); next_event(&ctx, WAIT_EVENT_TIMEOUT); ok (ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "got exception\n"); }