ReactOS 0.4.16-dev-2207-geb15453
debugger.c File Reference
#include <stdio.h>
#include <assert.h>
#include <ntstatus.h>
#include <windows.h>
#include <winternl.h>
#include <winreg.h>
#include "wine/test.h"
#include "wine/heap.h"
#include "wine/rbtree.h"
Include dependency graph for debugger.c:

Go to the source code of this file.

Classes

struct  tag_reg_save_value
 
struct  debugger_blackbox_t
 
struct  debugger_context
 
struct  debuggee_thread
 
struct  child_blackbox
 
struct  find_main_window
 

Macros

#define WIN32_NO_STATUS
 
#define STATUS_DEBUGGER_INACTIVE   ((NTSTATUS) 0xC0000354)
 
#define child_ok   (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_child_ok
 
#define load_blackbox(a, b, c)   _load_blackbox(__LINE__, (a), (b), (c))
 
#define fetch_thread_context(a)   fetch_thread_context_(__LINE__,a)
 
#define set_thread_context(a, b)   set_thread_context_(__LINE__,a,b)
 
#define WAIT_EVENT_TIMEOUT   20000
 
#define POLL_EVENT_TIMEOUT   200
 
#define next_event(a, b)   next_event_(__LINE__,a,b)
 
#define next_event_filter(a, b, c)   next_event_filter_(__LINE__, (a), (b), (c))
 
#define wait_for_breakpoint(a)   wait_for_breakpoint_(__LINE__,a)
 
#define check_thread_running(h)   ok(_check_thread_suspend_count(h) == 0, "Expecting running thread\n")
 
#define check_thread_suspended(h)   ok(_check_thread_suspend_count(h) > 0, "Expecting suspended thread\n")
 
#define expect_event(a, b)   expect_event_(__LINE__,a,b)
 
#define expect_exception(a, b)   expect_exception_(__LINE__,a,b)
 
#define check_breakpoint_exception(a, b)   expect_breakpoint_exception_(__LINE__,a,b)
 
#define expect_breakpoint_exception(a, b)   expect_breakpoint_exception_(__LINE__,a,b)
 
#define single_step(a, b, c)   single_step_(__LINE__,a,b,c)
 
#define OP_BP   0
 

Typedefs

typedef struct tag_reg_save_value reg_save_value
 

Functions

static BOOL (WINAPI *pCheckRemoteDebuggerPresent)(HANDLE
 
static void (WINAPI *pDbgBreakPoint)(void)
 
static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE process)
 
static HANDLE (WINAPI *pDbgUiGetThreadDebugObject)(void)
 
static DWORD (WINAPI *pGetMappedFileNameW)(HANDLE
 
static void WINAPIV __WINE_PRINTF_ATTR (2, 3)
 
static void get_file_name (char *buf)
 
static DWORD save_value (HKEY hkey, const char *value, reg_save_value *saved)
 
static void restore_value (HKEY hkey, reg_save_value *saved)
 
static void get_events (const char *name, HANDLE *start_event, HANDLE *done_event)
 
static void save_blackbox (const char *logfile, void *blackbox, int size, const char *dbgtrace)
 
static int _load_blackbox (unsigned int line, const char *logfile, void *blackbox, int size)
 
static DWORD WINAPI thread_proc (void *arg)
 
static void run_background_thread (void)
 
static void doCrash (void)
 
int debuggee_thread_compare (const void *key, const struct wine_rb_entry *entry)
 
static void add_thread (struct debugger_context *ctx, DWORD tid)
 
static struct debuggee_threadget_debuggee_thread (struct debugger_context *ctx, DWORD tid)
 
static void remove_thread (struct debugger_context *ctx, DWORD tid)
 
static voidget_ip (const CONTEXT *ctx)
 
static void set_ip (CONTEXT *ctx, void *ip)
 
static void fetch_thread_context_ (unsigned line, struct debuggee_thread *thread)
 
static void set_thread_context_ (unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread)
 
static void next_event_ (unsigned line, struct debugger_context *ctx, unsigned timeout)
 
static DWORD event_mask (DWORD ev)
 
static void next_event_filter_ (unsigned line, struct debugger_context *ctx, DWORD timeout, DWORD mask)
 
static void wait_for_breakpoint_ (unsigned line, struct debugger_context *ctx)
 
static LONG _check_thread_suspend_count (HANDLE h)
 
static void process_attach_events (struct debugger_context *ctx, BOOL pass_exception)
 
static void doDebugger (int argc, char **argv)
 
static void crash_and_debug (HKEY hkey, const char *argv0, const char *dbgtasks)
 
static void crash_and_winedbg (HKEY hkey, const char *argv0)
 
static void test_ExitCode (void)
 
static void test_RemoteDebugger (void)
 
static void doChild (int argc, char **argv)
 
static void check_dll_event (HANDLE process, DEBUG_EVENT *ev)
 
static void test_debug_loop (int argc, char **argv)
 
static BOOL CALLBACK enum_windows_callback (HWND handle, LPARAM lParam)
 
static void close_main_windows (DWORD pid)
 
static void test_debug_loop_wow64 (void)
 
static void doChildren (int argc, char **argv)
 
static void test_debug_children (const char *name, DWORD flag, BOOL debug_child, BOOL pass_exception)
 
static void wait_debugger (HANDLE event, unsigned int cnt)
 
static void expect_event_ (unsigned line, struct debugger_context *ctx, DWORD event_code)
 
static void expect_exception_ (unsigned line, struct debugger_context *ctx, DWORD exception_code)
 
static void check_breakpoint_exception_ (unsigned line, struct debugger_context *ctx, const void *expect_addr)
 
static void expect_breakpoint_exception_ (unsigned line, struct debugger_context *ctx, const void *expect_addr)
 
static void single_step_ (unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread, void *expect_addr)
 
static void test_debugger (const char *argv0)
 
static DWORD run_child_wait (char *cmd, HANDLE event)
 
static DWORD WINAPI debug_and_exit (void *arg)
 
static DWORD WINAPI debug_and_wait (void *arg)
 
static DWORD WINAPI create_debug_port (void *arg)
 
static void test_kill_on_exit (const char *argv0)
 
 START_TEST (debugger)
 

Variables

static int myARGC
 
static char ** myARGV
 
static BOOL is_wow64
 
static PBOOL
 
static ACCESS_MASK
 
static OBJECT_ATTRIBUTES ULONG
 
static DEBUGOBJECTINFOCLASS
 
static void WCHAR DWORD
 
static LONG child_failures
 
static HMODULE ntdll
 
static HMODULE ole32_mod
 
static HMODULE oleaut32_mod
 
static HMODULE oleacc_mod
 
static const BYTE loop_code []
 
static const BYTE call_debug_service_code []
 
static PROCESS_INFORMATION pi
 
static charcmd
 

Macro Definition Documentation

◆ check_breakpoint_exception

#define check_breakpoint_exception (   a,
  b 
)    expect_breakpoint_exception_(__LINE__,a,b)

Definition at line 1548 of file debugger.c.

◆ check_thread_running

#define check_thread_running (   h)    ok(_check_thread_suspend_count(h) == 0, "Expecting running thread\n")

Definition at line 423 of file debugger.c.

◆ check_thread_suspended

#define check_thread_suspended (   h)    ok(_check_thread_suspend_count(h) > 0, "Expecting suspended thread\n")

Definition at line 424 of file debugger.c.

◆ child_ok

#define child_ok   (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_child_ok

Definition at line 37 of file debugger.c.

◆ expect_breakpoint_exception

#define expect_breakpoint_exception (   a,
  b 
)    expect_breakpoint_exception_(__LINE__,a,b)

Definition at line 1561 of file debugger.c.

◆ expect_event

#define expect_event (   a,
  b 
)    expect_event_(__LINE__,a,b)

Definition at line 1532 of file debugger.c.

◆ expect_exception

#define expect_exception (   a,
  b 
)    expect_exception_(__LINE__,a,b)

Definition at line 1540 of file debugger.c.

◆ fetch_thread_context

#define fetch_thread_context (   a)    fetch_thread_context_(__LINE__,a)

Definition at line 306 of file debugger.c.

◆ load_blackbox

#define load_blackbox (   a,
  b,
  c 
)    _load_blackbox(__LINE__, (a), (b), (c))

Definition at line 151 of file debugger.c.

◆ next_event

#define next_event (   a,
  b 
)    next_event_(__LINE__,a,b)

Definition at line 335 of file debugger.c.

◆ next_event_filter

#define next_event_filter (   a,
  b,
  c 
)    next_event_filter_(__LINE__, (a), (b), (c))

Definition at line 403 of file debugger.c.

◆ OP_BP

#define OP_BP   0

Definition at line 1642 of file debugger.c.

◆ POLL_EVENT_TIMEOUT

#define POLL_EVENT_TIMEOUT   200

Definition at line 333 of file debugger.c.

◆ set_thread_context

#define set_thread_context (   a,
  b 
)    set_thread_context_(__LINE__,a,b)

Definition at line 324 of file debugger.c.

◆ single_step

#define single_step (   a,
  b,
  c 
)    single_step_(__LINE__,a,b,c)

Definition at line 1568 of file debugger.c.

◆ STATUS_DEBUGGER_INACTIVE

#define STATUS_DEBUGGER_INACTIVE   ((NTSTATUS) 0xC0000354)

Definition at line 34 of file debugger.c.

◆ WAIT_EVENT_TIMEOUT

#define WAIT_EVENT_TIMEOUT   20000

Definition at line 332 of file debugger.c.

◆ wait_for_breakpoint

#define wait_for_breakpoint (   a)    wait_for_breakpoint_(__LINE__,a)

Definition at line 412 of file debugger.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 25 of file debugger.c.

Typedef Documentation

◆ reg_save_value

Function Documentation

◆ __WINE_PRINTF_ATTR()

static void WINAPIV __WINE_PRINTF_ATTR ( ,
 
)
static

Definition at line 61 of file debugger.c.

62{
64
69}
#define msg(x)
Definition: auth_time.c:54
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
GLenum condition
Definition: glext.h:9255
int winetest_vok(int condition, const char *msg, va_list ap)
static LONG child_failures
Definition: debugger.c:57
static va_list valist
Definition: printf.c:46

◆ _check_thread_suspend_count()

static LONG _check_thread_suspend_count ( HANDLE  h)
static

Definition at line 426 of file debugger.c.

427{
428 DWORD suspend_count;
429
430 suspend_count = SuspendThread(h);
431 if (suspend_count != (DWORD)-1 && ResumeThread(h) == (DWORD)-1)
432 return (DWORD)-2;
433 return suspend_count;
434}
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723

◆ _load_blackbox()

static int _load_blackbox ( unsigned int  line,
const char logfile,
void blackbox,
int  size 
)
static

Definition at line 152 of file debugger.c.

153{
155 DWORD read;
156 BOOL ret;
157 char buf[4096];
158
161 {
162 ok_(__FILE__, line)(0, "unable to open '%s': %#lx\n", logfile, GetLastError());
163 return 0;
164 }
165 SetLastError(0xdeadbeef);
166 ret = ReadFile(hFile, blackbox, size, &read, NULL);
167 ok(ret, "ReadFile failed: %ld\n", GetLastError());
168#ifdef __REACTOS__
169 ok(read == size || broken(read == 0) /* WS03 */, "wrong size for '%s': read=%ld\n", logfile, read);
170#else
171 ok(read == size, "wrong size for '%s': read=%ld\n", logfile, read);
172#endif
173 ret = ReadFile(hFile, buf, sizeof(buf) - 1, &read, NULL);
174 if (ret && read)
175 {
176 buf[read] = 0;
177 trace("debugger traces:>>>\n%s\n<<< Done.\n", buf);
178 }
180 return 1;
181}
#define read
Definition: acwin.h:96
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define ok_(x1, x2)
Definition: atltest.h:61
#define NULL
Definition: types.h:112
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
return ret
Definition: mutex.c:146
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
_In_ HANDLE hFile
Definition: mswsock.h:90
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
Definition: parser.c:49
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

◆ add_thread()

static void add_thread ( struct debugger_context ctx,
DWORD  tid 
)
static

Definition at line 258 of file debugger.c.

259{
260 struct debuggee_thread *thread;
261 if (!ctx->thread_cnt++) wine_rb_init(&ctx->threads, debuggee_thread_compare);
262 thread = heap_alloc(sizeof(*thread));
263 thread->tid = tid;
264 thread->tag = ctx->thread_tag;
265 thread->handle = NULL;
266 wine_rb_put(&ctx->threads, &tid, &thread->entry);
267 if (!ctx->main_thread) ctx->main_thread = thread;
268}
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static HANDLE thread
Definition: service.c:33
static TfClientId tid
int debuggee_thread_compare(const void *key, const struct wine_rb_entry *entry)
Definition: debugger.c:252
#define wine_rb_put
Definition: rbtree.h:410
#define wine_rb_init
Definition: rbtree.h:406

Referenced by next_event_(), and test_debugger().

◆ BOOL()

static BOOL ( WINAPI pCheckRemoteDebuggerPresent)
static

◆ check_breakpoint_exception_()

static void check_breakpoint_exception_ ( unsigned  line,
struct debugger_context ctx,
const void expect_addr 
)
static

Definition at line 1549 of file debugger.c.

1550{
1551 struct debuggee_thread *thread;
1552 if (!expect_addr) return;
1553 ok_(__FILE__,line)(ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress == expect_addr,
1554 "ExceptionAddress = %p expected %p\n", ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress, expect_addr);
1555 thread = get_debuggee_thread(ctx, ctx->ev.dwThreadId);
1557 ok_(__FILE__,line)(get_ip(&thread->ctx) == (char*)expect_addr + 1, "unexpected instruction pointer %p expected %p\n",
1558 get_ip(&thread->ctx), expect_addr);
1559}
static void * get_ip(const CONTEXT *ctx)
Definition: debugger.c:286
static struct debuggee_thread * get_debuggee_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:270
#define fetch_thread_context(a)
Definition: debugger.c:306

Referenced by expect_breakpoint_exception_().

◆ check_dll_event()

static void check_dll_event ( HANDLE  process,
DEBUG_EVENT ev 
)
static

Definition at line 1001 of file debugger.c.

1002{
1004
1005 switch (ev->dwDebugEventCode)
1006 {
1008 break;
1010 if (!pGetMappedFileNameW( process, ev->u.LoadDll.lpBaseOfDll, module, MAX_PATH )) module[0] = 0;
1011 if ((p = wcsrchr( module, '\\' ))) p++;
1012 else p = module;
1013 if (!wcsicmp( p, L"ole32.dll" )) ole32_mod = ev->u.LoadDll.lpBaseOfDll;
1014 else if (!wcsicmp( p, L"oleaut32.dll" )) oleaut32_mod = ev->u.LoadDll.lpBaseOfDll;
1015 else if (!wcsicmp( p, L"oleacc.dll" )) oleacc_mod = ev->u.LoadDll.lpBaseOfDll;
1016 break;
1021 break;
1022 }
1023}
#define wcsrchr
Definition: compat.h:16
#define MAX_PATH
Definition: compat.h:34
#define wcsicmp
Definition: compat.h:15
#define L(x)
Definition: resources.c:13
GLfloat GLfloat p
Definition: glext.h:8902
#define CREATE_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:35
#define LOAD_DLL_DEBUG_EVENT
Definition: minwinbase.h:38
#define UNLOAD_DLL_DEBUG_EVENT
Definition: minwinbase.h:39
static HMODULE ole32_mod
Definition: debugger.c:999
static HMODULE oleaut32_mod
Definition: debugger.c:999
static HMODULE oleacc_mod
Definition: debugger.c:999
UNLOAD_DLL_DEBUG_INFO UnloadDll
Definition: minwinbase.h:207
union _DEBUG_EVENT::@3249 u
DWORD dwDebugEventCode
Definition: minwinbase.h:196
LOAD_DLL_DEBUG_INFO LoadDll
Definition: minwinbase.h:206
HANDLE HMODULE
Definition: typedefs.h:77
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by test_debug_loop().

◆ close_main_windows()

static void close_main_windows ( DWORD  pid)
static

Definition at line 1148 of file debugger.c.

1149{
1150 struct find_main_window fmw = {pid, 0};
1151 unsigned i;
1152
1154 ok(fmw.count, "no window found\n");
1155 for (i = 0; i < fmw.count; i++)
1156 PostMessageA(fmw.windows[i], WM_CLOSE, 0, 0);
1157}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LONG_PTR LPARAM
Definition: minwindef.h:175
static BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
Definition: debugger.c:1133
HWND windows[5]
Definition: debugger.c:1130
unsigned count
Definition: debugger.c:1129
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WM_CLOSE
Definition: winuser.h:1649
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
BOOL WINAPI PostMessageA(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)

Referenced by test_debug_loop_wow64().

◆ crash_and_debug()

static void crash_and_debug ( HKEY  hkey,
const char argv0,
const char dbgtasks 
)
static

Definition at line 621 of file debugger.c.

622{
623 static BOOL skip_crash_and_debug = FALSE;
624 BOOL bRet;
625 DWORD ret;
626 HANDLE start_event, done_event;
627 char* cmd;
628 char dbglog[MAX_PATH];
632 debugger_blackbox_t dbg_blackbox;
633 DWORD wait_code;
634
635 if (skip_crash_and_debug)
636 {
637 win_skip("Skipping crash_and_debug\n");
638 return;
639 }
640
641 ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
643 {
644 skip_crash_and_debug = TRUE;
645 skip("No write access to change the debugger\n");
646 return;
647 }
648
649 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%ld\n", ret);
650
651 get_file_name(dbglog);
652 get_events(dbglog, &start_event, &done_event);
653 cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+10+strlen(dbgtasks)+1+strlen(dbglog)+2+34+1);
654 sprintf(cmd, "%s debugger %s \"%s\" %%ld %%ld", argv0, dbgtasks, dbglog);
655 ret=RegSetValueExA(hkey, "debugger", 0, REG_SZ, (BYTE*)cmd, strlen(cmd)+1);
656 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/debugger: ret=%ld\n", ret);
658
659 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv0) + 16);
660 sprintf(cmd, "%s debugger crash", argv0);
661
662 trace("running %s...\n", dbgtasks);
663 memset(&startup, 0, sizeof(startup));
664 startup.cb = sizeof(startup);
666 startup.wShowWindow = SW_SHOWNORMAL;
668 ok(ret, "CreateProcess: err=%ld\n", GetLastError());
670 CloseHandle(info.hThread);
671
672 /* The process exits... */
673 trace("waiting for child exit...\n");
674 wait_code = WaitForSingleObject(info.hProcess, 30000);
675#if defined(_WIN64) && defined(__MINGW32__)
676 /* Mingw x64 doesn't output proper unwind info */
677 skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
678 if (skip_crash_and_debug)
679 {
681 WaitForSingleObject(info.hProcess, 5000);
682 CloseHandle(info.hProcess);
683 DeleteFileA(dbglog);
684 win_skip("Giving up on child process\n");
685 return;
686 }
687#endif
688 ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
689 bRet = GetExitCodeProcess(info.hProcess, &exit_code);
690 ok(bRet, "GetExitCodeProcess failed: err=%ld\n", GetLastError());
691 if (strstr(dbgtasks, "code2"))
692 {
693 /* If, after attaching to the debuggee, the debugger exits without
694 * detaching, then the debuggee gets a special exit code.
695 */
697 broken(exit_code == STATUS_ACCESS_VIOLATION) || /* Intermittent Vista+ */
698 broken(exit_code == WAIT_ABANDONED), /* NT4, W2K */
699 "wrong exit code : %08lx\n", exit_code);
700 }
701 else
703 broken(exit_code == WAIT_ABANDONED), /* NT4, W2K, W2K3 */
704 "wrong exit code : %08lx\n", exit_code);
705 CloseHandle(info.hProcess);
706
707 /* ...before the debugger */
708 if (strstr(dbgtasks, "order"))
709 ok(SetEvent(start_event), "SetEvent(start_event) failed\n");
710
711 trace("waiting for the debugger...\n");
712 wait_code = WaitForSingleObject(done_event, 5000);
713#if defined(_WIN64) && defined(__MINGW32__)
714 /* Mingw x64 doesn't output proper unwind info */
715 skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
716 if (skip_crash_and_debug)
717 {
718 DeleteFileA(dbglog);
719 win_skip("Giving up on debugger\n");
720 return;
721 }
722#endif
723 ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the debugger\n");
724
725 ok(load_blackbox(dbglog, &dbg_blackbox, sizeof(dbg_blackbox)), "failed to open: %s\n", dbglog);
726
727 ok(dbg_blackbox.argc == 6, "wrong debugger argument count: %d\n", dbg_blackbox.argc);
728 ok(dbg_blackbox.pid == info.dwProcessId, "the child and debugged pids don't match: %ld != %ld\n", info.dwProcessId, dbg_blackbox.pid);
729 ok(dbg_blackbox.debug_rc, "debugger: SetEvent(debug_event) failed err=%ld\n", dbg_blackbox.debug_err);
730 ok(dbg_blackbox.attach_rc, "DebugActiveProcess(%ld) failed err=%ld\n", dbg_blackbox.pid, dbg_blackbox.attach_err);
731 ok(dbg_blackbox.nokill_rc, "DebugSetProcessKillOnExit(FALSE) failed err=%ld\n", dbg_blackbox.nokill_err);
732 ok(dbg_blackbox.detach_rc, "DebugActiveProcessStop(%ld) failed err=%ld\n", dbg_blackbox.pid, dbg_blackbox.detach_err);
733 ok(!dbg_blackbox.failures, "debugger reported %lu failures\n", dbg_blackbox.failures);
734
735 DeleteFileA(dbglog);
736}
static void startup(void)
#define skip(...)
Definition: atltest.h:64
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_SUCCESS
Definition: deptool.c:10
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4749
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1534
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3415
#define STATUS_ACCESS_VIOLATION
#define REG_SZ
Definition: layer.c:22
#define win_skip
Definition: minitest.h:67
#define sprintf
Definition: sprintf.c:45
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:34
static void get_events(const char *name, HANDLE *start_event, HANDLE *done_event)
Definition: debugger.c:115
static char * cmd
Definition: debugger.c:2304
#define load_blackbox(a, b, c)
Definition: debugger.c:151
static UINT exit_code
Definition: process.c:80
static HANDLE start_event
Definition: thread.c:136
#define get_file_name
Definition: regproc.h:51
#define memset(x, y, z)
Definition: compat.h:39
static char argv0[MAX_PATH]
Definition: shlexec.c:49
Definition: ftp_var.h:139
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
#define WAIT_ABANDONED
Definition: winbase.h:389
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define SW_SHOWNORMAL
Definition: winuser.h:781
unsigned char BYTE
Definition: xxhash.c:193

Referenced by test_ExitCode().

◆ crash_and_winedbg()

static void crash_and_winedbg ( HKEY  hkey,
const char argv0 
)
static

Definition at line 738 of file debugger.c.

739{
740 BOOL bRet;
741 DWORD ret;
742 char* cmd;
746
747 ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
748 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%ld\n", ret);
749
751 sprintf(cmd, "%s debugger crash", argv0);
752
753 memset(&startup, 0, sizeof(startup));
754 startup.cb = sizeof(startup);
756 startup.wShowWindow = SW_SHOWNORMAL;
758 ok(ret, "CreateProcess: err=%ld\n", GetLastError());
760 CloseHandle(info.hThread);
761
762 trace("waiting for child exit...\n");
763 ok(WaitForSingleObject(info.hProcess, 60000) == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
764 bRet = GetExitCodeProcess(info.hProcess, &exit_code);
765 ok(bRet, "GetExitCodeProcess failed: err=%ld\n", GetLastError());
766 ok(exit_code == STATUS_ACCESS_VIOLATION, "exit code = %08lx\n", exit_code);
767 CloseHandle(info.hProcess);
768}

Referenced by test_ExitCode().

◆ create_debug_port()

static DWORD WINAPI create_debug_port ( void arg)
static

Definition at line 2344 of file debugger.c.

2345{
2346 STARTUPINFOA si = { sizeof(si) };
2347 NTSTATUS status = pDbgUiConnectToDbg();
2348
2349 ok( !status, "DbgUiConnectToDbg failed %lx\n", status );
2350 *(HANDLE *)arg = pDbgUiGetThreadDebugObject();
2351 Sleep( INFINITE );
2352 ExitThread(0);
2353}
LONG NTSTATUS
Definition: precomp.h:26
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
#define INFINITE
Definition: serial.h:102
static SYSTEM_INFO si
Definition: virtual.c:39
Definition: ps.c:97
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790

Referenced by test_kill_on_exit().

◆ debug_and_exit()

static DWORD WINAPI debug_and_exit ( void arg)
static

Definition at line 2306 of file debugger.c.

2307{
2308 STARTUPINFOA si = { sizeof(si) };
2309 HANDLE debug;
2310 ULONG val = 0;
2312 BOOL ret;
2313
2315 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2316 debug = pDbgUiGetThreadDebugObject();
2317 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2318 &val, sizeof(val), NULL );
2319 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
2320 *(HANDLE *)arg = debug;
2321 Sleep(200);
2322 ExitThread(0);
2323}
@ DebugObjectKillProcessOnExitInformation
Definition: dbgktypes.h:58
GLuint GLfloat * val
Definition: glext.h:7180
#define debug(msg)
Definition: key_call.c:71
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
uint32_t ULONG
Definition: typedefs.h:59
#define DEBUG_PROCESS
Definition: winbase.h:180

Referenced by test_kill_on_exit().

◆ debug_and_wait()

static DWORD WINAPI debug_and_wait ( void arg)
static

Definition at line 2325 of file debugger.c.

2326{
2327 STARTUPINFOA si = { sizeof(si) };
2328 HANDLE debug = *(HANDLE *)arg;
2329 ULONG val = 0;
2331 BOOL ret;
2332
2333 pDbgUiSetThreadDebugObject( debug );
2335 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2336 debug = pDbgUiGetThreadDebugObject();
2337 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2338 &val, sizeof(val), NULL );
2339 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
2340 Sleep(INFINITE);
2341 ExitThread(0);
2342}

Referenced by test_kill_on_exit().

◆ debuggee_thread_compare()

int debuggee_thread_compare ( const void key,
const struct wine_rb_entry entry 
)

Definition at line 252 of file debugger.c.

253{
255 return memcmp(key, &thread->tid, sizeof(thread->tid));
256}
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
uint32_t entry
Definition: isohybrid.c:63
#define WINE_RB_ENTRY_VALUE
Definition: rbtree.h:414
Definition: copy.c:22

Referenced by add_thread().

◆ doChild()

static void doChild ( int  argc,
char **  argv 
)
static

Definition at line 897 of file debugger.c.

898{
899 struct child_blackbox blackbox;
900 const char *blackbox_file;
902 HMODULE mod;
904 DWORD ppid;
905 BOOL debug;
906 BOOL ret;
907
908 blackbox_file = argv[4];
909 sscanf(argv[3], "%08lx", &ppid);
910
912 child_ok(!!parent, "OpenProcess failed, last error %#lx.\n", GetLastError());
913
914 ret = pCheckRemoteDebuggerPresent(parent, &debug);
915 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
916 child_ok(!debug, "Expected debug == 0, got %#x.\n", debug);
917
918 ret = DebugActiveProcess(ppid);
919 child_ok(ret, "DebugActiveProcess failed, last error %#lx.\n", GetLastError());
920
921 ret = pCheckRemoteDebuggerPresent(parent, &debug);
922 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
923 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
924
926 child_ok(ret, "DebugActiveProcessStop failed, last error %#lx.\n", GetLastError());
927
928 ret = pCheckRemoteDebuggerPresent(parent, &debug);
929 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
930 child_ok(!debug, "Expected debug == 0, got %#x.\n", debug);
931
933 child_ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
934
936 child_ok(ret, "Expected ret != 0, got %#x.\n", ret);
937 ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug);
938 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
939 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
940
941 NtCurrentTeb()->Peb->BeingDebugged = FALSE;
942
944 child_ok(!ret, "Expected ret != 0, got %#x.\n", ret);
945 ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug);
946 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
947 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
948
949 NtCurrentTeb()->Peb->BeingDebugged = TRUE;
950
951 mod = LoadLibraryW( L"ole32.dll" );
952 FreeLibrary( mod );
953
955 wcscat( path, L"\\oleaut32.dll" );
957 child_ok( file != INVALID_HANDLE_VALUE, "failed to open %s: %lu\n", debugstr_w(path), GetLastError());
959 child_ok( map != NULL, "failed to create mapping %s: %lu\n", debugstr_w(path), GetLastError() );
960 mod = MapViewOfFile( map, FILE_MAP_READ, 0, 0, 0 );
961 child_ok( mod != NULL, "failed to map %s: %lu\n", debugstr_w(path), GetLastError() );
962 CloseHandle( file );
963 CloseHandle( map );
965
966 if (sizeof(void *) > sizeof(int))
967 {
969 wcscat( path, L"\\oleacc.dll" );
970 }
971 else if (is_wow64)
972 {
973#ifdef __REACTOS__
974 static wchar_t expected_path[MAX_PATH];
975 GetWindowsDirectoryW(expected_path, MAX_PATH);
976 wcscat(expected_path, L"\\sysnative\\oleacc.dll");
977 wcscpy( path, expected_path );
978#else
979 wcscpy( path, L"c:\\windows\\sysnative\\oleacc.dll" );
980#endif
981 }
982 else goto done;
983
985 child_ok( file != INVALID_HANDLE_VALUE, "failed to open %s: %lu\n", debugstr_w(path), GetLastError());
987 child_ok( map != NULL, "failed to create mapping %s: %lu\n", debugstr_w(path), GetLastError() );
988 mod = MapViewOfFile( map, FILE_MAP_READ, 0, 0, 0 );
989 child_ok( mod != NULL, "failed to map %s: %lu\n", debugstr_w(path), GetLastError() );
990 CloseHandle( file );
991 CloseHandle( map );
993
994done:
995 blackbox.failures = child_failures;
996 save_blackbox(blackbox_file, &blackbox, sizeof(blackbox), NULL);
997}
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:66
Definition: _map.h:48
#define PAGE_READONLY
Definition: compat.h:138
#define UnmapViewOfFile
Definition: compat.h:746
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define FreeLibrary(x)
Definition: compat.h:748
#define GetCurrentProcess()
Definition: compat.h:759
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define MapViewOfFile
Definition: compat.h:745
#define LoadLibraryW(x)
Definition: compat.h:747
BOOL WINAPI DebugActiveProcessStop(IN DWORD dwProcessId)
Definition: debugger.c:486
BOOL WINAPI DebugActiveProcess(IN DWORD dwProcessId)
Definition: debugger.c:445
UINT WINAPI GetSystemWow64DirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2421
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
BOOL WINAPI IsDebuggerPresent(void)
Definition: debug.c:167
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
r parent
Definition: btrfs.c:3010
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define NtCurrentTeb
#define debugstr_w
Definition: kernel32.h:32
#define child_ok
Definition: debugger.c:37
static BOOL is_wow64
Definition: debugger.c:41
static void save_blackbox(const char *logfile, void *blackbox, int size, const char *dbgtrace)
Definition: debugger.c:131
#define argv
Definition: mplay32.c:18
#define SEC_IMAGE
Definition: mmtypes.h:97
wcscat
wcscpy
Definition: fci.c:127

Referenced by START_TEST().

◆ doChildren()

static void doChildren ( int  argc,
char **  argv 
)
static

Definition at line 1299 of file debugger.c.

1300{
1301 const char *arguments = "debugger children last";
1302 struct child_blackbox blackbox;
1303 const char *blackbox_file, *p;
1304 char event_name[MAX_PATH];
1307 HANDLE event;
1308 char *cmd;
1309 BOOL ret;
1310
1311 if (!strcmp(argv[3], "last")) return;
1312
1313 blackbox_file = argv[3];
1314
1316
1317 p = strrchr(blackbox_file, '\\');
1318 p = p ? p+1 : blackbox_file;
1319 strcpy(event_name, p);
1320 strcat(event_name, "_init");
1321 event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
1322 child_ok(event != NULL, "OpenEvent failed, last error %ld.\n", GetLastError());
1323 SetEvent(event);
1325
1326 p = strrchr(blackbox_file, '\\');
1327 p = p ? p+1 : blackbox_file;
1328 strcpy(event_name, p);
1329 strcat(event_name, "_attach");
1330 event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
1331 child_ok(event != NULL, "OpenEvent failed, last error %ld.\n", GetLastError());
1334
1335 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + 2);
1336 sprintf(cmd, "%s %s", argv[0], arguments);
1337
1338 memset(&si, 0, sizeof(si));
1339 si.cb = sizeof(si);
1340 ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
1341 child_ok(ret, "CreateProcess failed, last error %ld.\n", GetLastError());
1342
1344 "Timed out waiting for the child to exit\n");
1345
1347 child_ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1349 child_ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1350
1351 blackbox.failures = child_failures;
1352 save_blackbox(blackbox_file, &blackbox, sizeof(blackbox), NULL);
1353
1355}
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
struct _cl_event * event
Definition: glext.h:7739
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
static void run_background_thread(void)
Definition: debugger.c:190
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
Definition: synch.c:669

Referenced by START_TEST().

◆ doCrash()

static void doCrash ( void  )
static

Definition at line 198 of file debugger.c.

199{
200 volatile char* p;
201
202 /* make sure the exception gets to the debugger */
203 SetErrorMode( 0 );
205
207
208 /* Just crash */
209 trace("child: crashing...\n");
210 p=NULL;
211 *p=0;
212}
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:751
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
Definition: except.c:790

Referenced by START_TEST().

◆ doDebugger()

static void doDebugger ( int  argc,
char **  argv 
)
static

Definition at line 521 of file debugger.c.

522{
523 const char* logfile;
524 debugger_blackbox_t blackbox;
525 HANDLE start_event = 0, done_event = 0, debug_event;
526 char buf[4096] = "";
527 struct debugger_context ctx = { 0 };
528
529 blackbox.argc=argc;
530 logfile=(argc >= 4 ? argv[3] : NULL);
531 blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0);
532
533 blackbox.attach_err=0;
534 if (strstr(myARGV[2], "attach"))
535 {
536 blackbox.attach_rc=DebugActiveProcess(blackbox.pid);
537 if (!blackbox.attach_rc)
538 blackbox.attach_err=GetLastError();
539 }
540 else
541 blackbox.attach_rc=TRUE;
542
543 if (strstr(myARGV[2], "process"))
544 {
545 strcat(buf, "processing debug messages\n");
547 }
548
549 debug_event=(argc >= 6 ? (HANDLE)(INT_PTR)atol(argv[5]) : NULL);
550 blackbox.debug_err=0;
551 if (debug_event && strstr(myARGV[2], "event"))
552 {
553 strcat(buf, "setting event\n");
554 blackbox.debug_rc=SetEvent(debug_event);
555 if (!blackbox.debug_rc)
556 blackbox.debug_err=GetLastError();
557 }
558 else
559 blackbox.debug_rc=TRUE;
560
561 if (strstr(myARGV[2], "process"))
562 {
564 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
565 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == STATUS_ACCESS_VIOLATION, "ExceptionCode = %lx\n",
566 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
567 }
568
569 if (logfile)
570 {
571 get_events(logfile, &start_event, &done_event);
572 }
573
574 if (strstr(myARGV[2], "order"))
575 {
576 strcat(buf, "waiting for the start signal...\n");
578 }
579
580 blackbox.nokill_err=0;
581 if (strstr(myARGV[2], "nokill"))
582 {
584 if (!blackbox.nokill_rc)
585 blackbox.nokill_err=GetLastError();
586 }
587 else
588 blackbox.nokill_rc=TRUE;
589
590 blackbox.detach_err=0;
591 if (strstr(myARGV[2], "detach"))
592 {
593 blackbox.detach_rc = DebugActiveProcessStop(blackbox.pid);
594 if (!blackbox.detach_rc)
595 blackbox.detach_err=GetLastError();
596 }
597 else
598 blackbox.detach_rc=TRUE;
599
600 if (debug_event && strstr(myARGV[2], "late"))
601 {
602 strcat(buf, "setting event\n");
603 blackbox.debug_rc=SetEvent(debug_event);
604 if (!blackbox.debug_rc)
605 blackbox.debug_err=GetLastError();
606 }
607
608 strcat(buf, "done debugging...\n");
609 if (logfile)
610 {
611 blackbox.failures = winetest_get_failures();
612 save_blackbox(logfile, &blackbox, sizeof(blackbox), buf);
613 }
614
615 SetEvent(done_event);
616
617 /* Just exit with a known value */
618 ExitProcess(0xdeadbeef);
619}
static int argc
Definition: ServiceArgs.c:12
BOOL WINAPI DebugSetProcessKillOnExit(IN BOOL KillOnExit)
Definition: debugger.c:542
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
_ACRTIMP __msvcrt_long __cdecl atol(const char *)
Definition: string.c:1782
LONG winetest_get_failures(void)
#define EXCEPTION_DEBUG_EVENT
Definition: minwinbase.h:33
#define WAIT_EVENT_TIMEOUT
Definition: debugger.c:332
static void process_attach_events(struct debugger_context *ctx, BOOL pass_exception)
Definition: debugger.c:436
#define next_event(a, b)
Definition: debugger.c:335
static char ** myARGV
Definition: debugger.c:40
int32_t INT_PTR
Definition: typedefs.h:64
PVOID HANDLE
Definition: typedefs.h:73

Referenced by START_TEST().

◆ DWORD()

static DWORD ( WINAPI pGetMappedFileNameW)
static

◆ enum_windows_callback()

static BOOL CALLBACK enum_windows_callback ( HWND  handle,
LPARAM  lParam 
)
static

Definition at line 1133 of file debugger.c.

1134{
1135 struct find_main_window* fmw = (struct find_main_window*)lParam;
1136 DWORD pid = 0;
1137
1138 if (GetWindowThreadProcessId(handle, &pid) && fmw->pid == pid &&
1140 {
1141 ok(fmw->count < ARRAY_SIZE(fmw->windows), "Too many windows\n");
1142 if (fmw->count < ARRAY_SIZE(fmw->windows))
1143 fmw->windows[fmw->count++] = handle;
1144 }
1145 return TRUE;
1146}
#define ARRAY_SIZE(A)
Definition: main.h:20
LPARAM lParam
Definition: combotst.c:139
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
#define GW_OWNER
Definition: winuser.h:777
HWND WINAPI GetWindow(_In_ HWND, _In_ UINT)

Referenced by close_main_windows().

◆ event_mask()

static DWORD event_mask ( DWORD  ev)
static

Definition at line 398 of file debugger.c.

399{
400 return (ev >= 1 && ev <= 7) ? (1LU << ev) : 0;
401}
#define U(x)
Definition: wordpad.c:45

Referenced by next_event_filter_(), test_debugger(), and wait_for_breakpoint_().

◆ expect_breakpoint_exception_()

static void expect_breakpoint_exception_ ( unsigned  line,
struct debugger_context ctx,
const void expect_addr 
)
static

Definition at line 1562 of file debugger.c.

1563{
1565 check_breakpoint_exception_(line, ctx, expect_addr);
1566}
#define EXCEPTION_BREAKPOINT
Definition: minwinbase.h:46
static void expect_exception_(unsigned line, struct debugger_context *ctx, DWORD exception_code)
Definition: debugger.c:1541
static void check_breakpoint_exception_(unsigned line, struct debugger_context *ctx, const void *expect_addr)
Definition: debugger.c:1549

◆ expect_event_()

static void expect_event_ ( unsigned  line,
struct debugger_context ctx,
DWORD  event_code 
)
static

Definition at line 1533 of file debugger.c.

1534{
1536 ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == event_code, "dwDebugEventCode = %ld expected %ld\n",
1537 ctx->ev.dwDebugEventCode, event_code);
1538}

Referenced by expect_exception_().

◆ expect_exception_()

static void expect_exception_ ( unsigned  line,
struct debugger_context ctx,
DWORD  exception_code 
)
static

Definition at line 1541 of file debugger.c.

1542{
1544 ok_(__FILE__,line)(ctx->ev.u.Exception.ExceptionRecord.ExceptionCode == exception_code, "ExceptionCode = %lx expected %lx\n",
1545 ctx->ev.u.Exception.ExceptionRecord.ExceptionCode, exception_code);
1546}
#define exception_code
Definition: excpt.h:84
static void expect_event_(unsigned line, struct debugger_context *ctx, DWORD event_code)
Definition: debugger.c:1533

Referenced by expect_breakpoint_exception_(), and single_step_().

◆ fetch_thread_context_()

static void fetch_thread_context_ ( unsigned  line,
struct debuggee_thread thread 
)
static

Definition at line 307 of file debugger.c.

308{
309 BOOL ret;
310
311 if (!thread->handle)
312 {
314 FALSE, thread->tid);
315 ok_(__FILE__,line)(thread->handle != NULL, "OpenThread failed: %lu\n", GetLastError());
316 }
317
318 memset(&thread->ctx, 0xaa, sizeof(thread->ctx));
319 thread->ctx.ContextFlags = CONTEXT_FULL;
320 ret = GetThreadContext(thread->handle, &thread->ctx);
321 ok_(__FILE__,line)(ret, "GetThreadContext failed: %lu\n", GetLastError());
322}
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:150
#define THREAD_SET_CONTEXT
#define THREAD_GET_CONTEXT
#define CONTEXT_FULL
Definition: nt_native.h:1378

◆ get_debuggee_thread()

static struct debuggee_thread * get_debuggee_thread ( struct debugger_context ctx,
DWORD  tid 
)
static

Definition at line 270 of file debugger.c.

271{
272 struct wine_rb_entry *entry = wine_rb_get(&ctx->threads, &tid);
273 ok(entry != NULL, "unknown thread %lx\n", tid);
275}
#define wine_rb_entry
Definition: rbtree.h:404
#define wine_rb_get
Definition: rbtree.h:409

Referenced by check_breakpoint_exception_(), next_event_(), remove_thread(), and test_debugger().

◆ get_events()

static void get_events ( const char name,
HANDLE start_event,
HANDLE done_event 
)
static

Definition at line 115 of file debugger.c.

116{
117 const char* basename;
118 char* event_name;
119
120 basename=strrchr(name, '\\');
122 event_name=HeapAlloc(GetProcessHeap(), 0, 6+strlen(basename)+1);
123
124 sprintf(event_name, "start_%s", basename);
125 *start_event=CreateEventA(NULL, 0,0, event_name);
126 sprintf(event_name, "done_%s", basename);
127 *done_event=CreateEventA(NULL, 0,0, event_name);
128 HeapFree(GetProcessHeap(), 0, event_name);
129}
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
Definition: name.c:39
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637

Referenced by crash_and_debug(), and doDebugger().

◆ get_file_name()

static void get_file_name ( char buf)
static

Definition at line 72 of file debugger.c.

73{
74 char path[MAX_PATH];
75
76 buf[0] = '\0';
77 GetTempPathA(sizeof(path), path);
78 GetTempFileNameA(path, "wt", 0, buf);
79}
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26

◆ get_ip()

static void * get_ip ( const CONTEXT ctx)
static

Definition at line 286 of file debugger.c.

287{
288#ifdef __i386__
289 return (void *)ctx->Eip;
290#elif defined(__x86_64__)
291 return (void *)ctx->Rip;
292#else
293 return NULL;
294#endif
295}

Referenced by check_breakpoint_exception_(), single_step_(), and test_debugger().

◆ HANDLE()

static HANDLE ( WINAPI pDbgUiGetThreadDebugObject)
static

◆ next_event_()

static void next_event_ ( unsigned  line,
struct debugger_context ctx,
unsigned  timeout 
)
static

Definition at line 336 of file debugger.c.

337{
338 BOOL ret;
339
340 ctx->current_thread = NULL;
341
342 for (;;)
343 {
344 if (ctx->process_cnt && ctx->ev.dwDebugEventCode != -1)
345 {
346 ret = ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_CONTINUE);
347 ok_(__FILE__,line)(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError());
348 }
349
351 if (!ret)
352 {
353 ok_(__FILE__,line)(GetLastError() == ERROR_SEM_TIMEOUT,
354 "WaitForDebugEvent failed, last error %ld.\n", GetLastError());
355 ctx->ev.dwDebugEventCode = -1;
356 return;
357 }
358
359 if (ctx->ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
360 {
361 if (!ctx->process_cnt) ctx->pid = ctx->ev.dwProcessId;
362 ctx->process_cnt++;
363 }
364
365 if (ctx->ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) continue; /* ignore for now */
366 if (ctx->ev.dwProcessId == ctx->pid) break;
367
368 ok_(__FILE__,line)(ctx->process_cnt > 1, "unexpected event pid\n");
369 }
370
371 switch (ctx->ev.dwDebugEventCode)
372 {
374 add_thread(ctx, ctx->ev.dwThreadId);
375 ctx->image_base = ctx->ev.u.CreateProcessInfo.lpBaseOfImage;
376 break;
378 remove_thread(ctx, ctx->ev.dwThreadId);
379 return;
381 add_thread(ctx, ctx->ev.dwThreadId);
382 break;
384 remove_thread(ctx, ctx->ev.dwThreadId);
385 return;
387 ok(ctx->ev.u.LoadDll.lpBaseOfDll != ctx->image_base, "process image reported as DLL load event\n");
388 ctx->dll_cnt++;
389 break;
391 ctx->dll_cnt--;
392 break;
393 }
394
395 ctx->current_thread = get_debuggee_thread(ctx, ctx->ev.dwThreadId);
396}
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
Definition: debugger.c:413
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
Definition: debugger.c:590
#define EXIT_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:37
#define OUTPUT_DEBUG_STRING_EVENT
Definition: minwinbase.h:40
#define CREATE_THREAD_DEBUG_EVENT
Definition: minwinbase.h:34
#define EXIT_THREAD_DEBUG_EVENT
Definition: minwinbase.h:36
static void remove_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:277
static void add_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:258
#define DBG_CONTINUE
Definition: ntstatus.h:98
Definition: dhcpd.h:248
#define ERROR_SEM_TIMEOUT
Definition: winerror.h:315

Referenced by next_event_filter_().

◆ next_event_filter_()

static void next_event_filter_ ( unsigned  line,
struct debugger_context ctx,
DWORD  timeout,
DWORD  mask 
)
static

Definition at line 404 of file debugger.c.

405{
406 do
407 {
409 } while (event_mask(ctx->ev.dwDebugEventCode) & mask);
410}
GLenum GLint GLuint mask
Definition: glext.h:6028
static DWORD event_mask(DWORD ev)
Definition: debugger.c:398
static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout)
Definition: debugger.c:336

Referenced by wait_for_breakpoint_().

◆ NTSTATUS()

static NTSTATUS ( WINAPI pNtSuspendProcess)
static

◆ process_attach_events()

static void process_attach_events ( struct debugger_context ctx,
BOOL  pass_exception 
)
static

Definition at line 436 of file debugger.c.

437{
438 DEBUG_EVENT ev;
439 BOOL ret;
440 HANDLE prev_thread;
441
442 ctx->ev.dwDebugEventCode = -1;
443 next_event(ctx, 0);
444 ok(ctx->ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode);
445
447 check_thread_suspended(ctx->ev.u.CreateProcessInfo.hThread);
448 prev_thread = ctx->ev.u.CreateProcessInfo.hThread;
449 next_event(ctx, 0);
450
451 if (ctx->ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) /* Vista+ reports ntdll.dll before reporting threads */
452 {
453 ok(ctx->ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode);
454 ok(ctx->ev.u.LoadDll.lpBaseOfDll == ntdll, "The first reported DLL is not ntdll.dll\n");
455 next_event(ctx, 0);
456 }
457
458 while (ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
459 {
461 check_thread_suspended(ctx->ev.u.CreateThread.hThread);
462 check_thread_running(prev_thread);
463 prev_thread = ctx->ev.u.CreateThread.hThread;
464 next_event(ctx, 0);
465 }
466
467 do
468 {
469 /* even when there are more pending events, they are not reported until current event is continued */
470 ret = WaitForDebugEvent(&ev, 10);
471 ok(GetLastError() == ERROR_SEM_TIMEOUT, "WaitForDebugEvent returned %x(%lu)\n", ret, GetLastError());
472
474 if (ctx->ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
475 ok(ctx->ev.u.LoadDll.lpBaseOfDll != ntdll, "ntdll.dll reported out of order\n");
476 } while (ctx->ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT || ctx->ev.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT);
477 ok(ctx->dll_cnt > 2, "dll_cnt = %d\n", ctx->dll_cnt);
478
479 /* a new thread is created and it executes DbgBreakPoint, which causes the exception */
480 /* Win11 doesn't generate it at this point (Win <= 10 do) */
481 if (ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
482 {
483 DWORD last_threads[5];
484 unsigned thd_idx = 0, i;
485
486 check_thread_running(prev_thread);
487
488 /* sometimes (at least Win10) several thread creations are reported here */
489 do
490 {
491 check_thread_running(ctx->ev.u.CreateThread.hThread);
492 if (thd_idx < ARRAY_SIZE(last_threads))
493 last_threads[thd_idx++] = ctx->ev.dwThreadId;
495 } while (ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT);
496 ok(thd_idx <= ARRAY_SIZE(last_threads), "too many threads created\n");
497 for (i = 0; i < thd_idx; i++)
498 if (last_threads[i] == ctx->ev.dwThreadId) break;
499 ok(i < thd_idx, "unexpected thread\n");
500
501 ok(ctx->ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode);
502 ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
503 ctx->ev.u.Exception.ExceptionRecord.ExceptionCode);
504 ok(ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress == pDbgBreakPoint, "ExceptionAddress != DbgBreakPoint\n");
505
506 if (pass_exception)
507 {
508 ret = ContinueDebugEvent(ctx->ev.dwProcessId, ctx->ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
509 ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError());
510 ctx->ev.dwDebugEventCode = -1;
511 }
512 }
513
514 /* flush debug events */
516 while (ctx->ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT || ctx->ev.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT
517 || ctx->ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT || ctx->ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT);
518 ok(ctx->ev.dwDebugEventCode == -1, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode);
519}
#define todo_wine
Definition: minitest.h:80
#define check_thread_running(h)
Definition: debugger.c:423
#define check_thread_suspended(h)
Definition: debugger.c:424
static HMODULE ntdll
Definition: debugger.c:59
#define POLL_EVENT_TIMEOUT
Definition: debugger.c:333
#define DBG_EXCEPTION_NOT_HANDLED
Definition: ntstatus.h:109

Referenced by doDebugger(), and test_debug_children().

◆ remove_thread()

static void remove_thread ( struct debugger_context ctx,
DWORD  tid 
)
static

Definition at line 277 of file debugger.c.

278{
280
281 wine_rb_remove(&ctx->threads, &thread->entry);
282 if (thread->handle) CloseHandle(thread->handle);
284}
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define wine_rb_remove
Definition: rbtree.h:411

Referenced by next_event_().

◆ restore_value()

static void restore_value ( HKEY  hkey,
reg_save_value saved 
)
static

Definition at line 104 of file debugger.c.

105{
106 if (saved->data)
107 {
108 RegSetValueExA(hkey, saved->name, 0, saved->type, saved->data, saved->size);
109 HeapFree(GetProcessHeap(), 0, saved->data);
110 }
111 else
112 RegDeleteValueA(hkey, saved->name);
113}
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
const char * name
Definition: debugger.c:83

Referenced by test_ExitCode().

◆ run_background_thread()

static void run_background_thread ( void  )
static

Definition at line 190 of file debugger.c.

191{
192 DWORD tid;
194 ok(thread != NULL, "CreateThread failed\n");
196}
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
static DWORD WINAPI thread_proc(void *arg)
Definition: debugger.c:183

Referenced by doChildren(), and doCrash().

◆ run_child_wait()

static DWORD run_child_wait ( char cmd,
HANDLE  event 
)
static

Definition at line 2282 of file debugger.c.

2283{
2285 STARTUPINFOA si = { sizeof(si) };
2286 BOOL ret;
2288
2290 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
2291 Sleep(200);
2292 CloseHandle( pDbgUiGetThreadDebugObject() );
2293 pDbgUiSetThreadDebugObject( 0 );
2294 SetEvent( event );
2297 ok( ret, "GetExitCodeProcess failed err=%ld\n", GetLastError());
2300 return exit_code;
2301}

Referenced by test_kill_on_exit().

◆ save_blackbox()

static void save_blackbox ( const char logfile,
void blackbox,
int  size,
const char dbgtrace 
)
static

Definition at line 131 of file debugger.c.

132{
134 DWORD written;
135 BOOL ret;
136
138 ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create %s: %lu\n", logfile, GetLastError());
140 return;
141 ret = WriteFile(hFile, blackbox, size, &written, NULL);
142 ok(ret && written == size, "Error writing\n");
143 if (dbgtrace && dbgtrace[0])
144 {
145 ret = WriteFile(hFile, dbgtrace, strlen(dbgtrace), &written, NULL);
146 ok(ret && written == strlen(dbgtrace), "Error writing\n");
147 }
149}
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define CREATE_ALWAYS
Definition: disk.h:72
#define GENERIC_WRITE
Definition: nt_native.h:90

Referenced by doChild(), doChildren(), and doDebugger().

◆ save_value()

static DWORD save_value ( HKEY  hkey,
const char value,
reg_save_value saved 
)
static

Definition at line 89 of file debugger.c.

90{
91 DWORD ret;
92 saved->name=value;
93 saved->data=0;
94 saved->size=0;
95 ret=RegQueryValueExA(hkey, value, NULL, &saved->type, NULL, &saved->size);
96 if (ret == ERROR_SUCCESS)
97 {
98 saved->data=HeapAlloc(GetProcessHeap(), 0, saved->size);
99 RegQueryValueExA(hkey, value, NULL, &saved->type, saved->data, &saved->size);
100 }
101 return ret;
102}
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
Definition: pdh_main.c:96

Referenced by test_ExitCode().

◆ set_ip()

static void set_ip ( CONTEXT ctx,
void ip 
)
static

Definition at line 297 of file debugger.c.

298{
299#ifdef __i386__
300 ctx->Eip = (DWORD_PTR)ip;
301#elif defined(__x86_64__)
302 ctx->Rip = (DWORD_PTR)ip;
303#endif
304}
Definition: dhcpd.h:62
#define DWORD_PTR
Definition: treelist.c:76

Referenced by test_debugger().

◆ set_thread_context_()

static void set_thread_context_ ( unsigned  line,
struct debugger_context ctx,
struct debuggee_thread thread 
)
static

Definition at line 325 of file debugger.c.

326{
327 BOOL ret;
328 ret = SetThreadContext(thread->handle, &thread->ctx);
329 ok_(__FILE__,line)(ret, "SetThreadContext failed: %lu\n", GetLastError());
330}
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:521

◆ single_step_()

static void single_step_ ( unsigned  line,
struct debugger_context ctx,
struct debuggee_thread thread,
void expect_addr 
)
static

Definition at line 1569 of file debugger.c.

1570{
1571#if defined(__i386__) || defined(__x86_64__)
1573 thread->ctx.EFlags |= 0x100;
1576 ok_(__FILE__,line)(ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress == expect_addr,
1577 "ExceptionAddress = %p expected %p\n", ctx->ev.u.Exception.ExceptionRecord.ExceptionAddress, expect_addr);
1579 ok_(__FILE__,line)(get_ip(&thread->ctx) == expect_addr, "unexpected instruction pointer %p expected %p\n",
1580 get_ip(&thread->ctx), expect_addr);
1581 ok_(__FILE__,line)(!(thread->ctx.EFlags & 0x100), "EFlags = %lx\n", thread->ctx.EFlags);
1582#endif
1583}
#define EXCEPTION_SINGLE_STEP
Definition: minwinbase.h:47
#define set_thread_context(a, b)
Definition: debugger.c:324

◆ START_TEST()

START_TEST ( debugger  )

Definition at line 2499 of file debugger.c.

2500{
2501 HMODULE hdll;
2502
2503 hdll=GetModuleHandleA("kernel32.dll");
2504 pCheckRemoteDebuggerPresent=(void*)GetProcAddress(hdll, "CheckRemoteDebuggerPresent");
2505 pIsWow64Process=(void*)GetProcAddress(hdll, "IsWow64Process");
2506 pGetMappedFileNameW = (void*)GetProcAddress(hdll, "GetMappedFileNameW");
2507 if (!pGetMappedFileNameW) pGetMappedFileNameW = (void*)GetProcAddress(LoadLibraryA("psapi.dll"),
2508 "GetMappedFileNameW");
2509 ntdll = GetModuleHandleA("ntdll.dll");
2510 pDbgBreakPoint = (void*)GetProcAddress(ntdll, "DbgBreakPoint");
2511 pNtSuspendProcess = (void*)GetProcAddress(ntdll, "NtSuspendProcess");
2512 pNtResumeProcess = (void*)GetProcAddress(ntdll, "NtResumeProcess");
2513 pNtCreateDebugObject = (void*)GetProcAddress(ntdll, "NtCreateDebugObject");
2514 pNtSetInformationDebugObject = (void*)GetProcAddress(ntdll, "NtSetInformationDebugObject");
2515 pDbgUiConnectToDbg = (void*)GetProcAddress(ntdll, "DbgUiConnectToDbg");
2516 pDbgUiGetThreadDebugObject = (void*)GetProcAddress(ntdll, "DbgUiGetThreadDebugObject");
2517 pDbgUiSetThreadDebugObject = (void*)GetProcAddress(ntdll, "DbgUiSetThreadDebugObject");
2518
2519#ifdef __arm__
2520 /* mask thumb bit for address comparisons */
2521 pDbgBreakPoint = (void *)((ULONG_PTR)pDbgBreakPoint & ~1);
2522#endif
2523
2524 if (pIsWow64Process) pIsWow64Process( GetCurrentProcess(), &is_wow64 );
2525
2527 if (myARGC >= 3 && strcmp(myARGV[2], "crash") == 0)
2528 {
2529 doCrash();
2530 }
2531 else if (myARGC >= 3 && strncmp(myARGV[2], "dbg,", 4) == 0)
2532 {
2534 }
2535 else if (myARGC >= 5 && !strcmp(myARGV[2], "child"))
2536 {
2538 }
2539 else if (myARGC >= 4 && !strcmp(myARGV[2], "children"))
2540 {
2542 }
2543 else if (myARGC >= 4 && !strcmp(myARGV[2], "wait"))
2544 {
2545 DWORD event, cnt = 1;
2546 sscanf(myARGV[3], "%lx", &event);
2547 if (myARGC >= 5) cnt = atoi(myARGV[4]);
2549 }
2550 else
2551 {
2552 test_ExitCode();
2564 }
2565}
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP int __cdecl strncmp(const char *, const char *, size_t)
Definition: string.c:3330
static void test_debug_loop_wow64(void)
Definition: debugger.c:1159
static void doCrash(void)
Definition: debugger.c:198
static void test_ExitCode(void)
Definition: debugger.c:770
static void test_debug_loop(int argc, char **argv)
Definition: debugger.c:1025
static int myARGC
Definition: debugger.c:39
static void doChildren(int argc, char **argv)
Definition: debugger.c:1299
static void test_kill_on_exit(const char *argv0)
Definition: debugger.c:2355
static void doDebugger(int argc, char **argv)
Definition: debugger.c:521
static void test_debugger(const char *argv0)
Definition: debugger.c:1645
static void doChild(int argc, char **argv)
Definition: debugger.c:897
static void test_debug_children(const char *name, DWORD flag, BOOL debug_child, BOOL pass_exception)
Definition: debugger.c:1357
static void wait_debugger(HANDLE event, unsigned int cnt)
Definition: debugger.c:1526
static void test_RemoteDebugger(void)
Definition: debugger.c:862
int winetest_get_mainargs(char ***pargv)
static PVOID hdll
Definition: shimdbg.c:126
uint32_t DWORD_PTR
Definition: typedefs.h:65
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ size_t cnt
Definition: wcstombs.cpp:43
#define DEBUG_ONLY_THIS_PROCESS
Definition: winbase.h:181

◆ test_debug_children()

static void test_debug_children ( const char name,
DWORD  flag,
BOOL  debug_child,
BOOL  pass_exception 
)
static

Definition at line 1357 of file debugger.c.

1358{
1359 const char *arguments = "debugger children";
1360#ifdef __REACTOS__
1361 struct child_blackbox blackbox = {0};
1362#else
1363 struct child_blackbox blackbox;
1364#endif
1365 char blackbox_file[MAX_PATH], *p;
1366 char event_name[MAX_PATH];
1369 HANDLE event_init, event_attach;
1370 char *cmd;
1371 BOOL debug, ret;
1372 struct debugger_context ctx = { 0 };
1373
1374 if (!pCheckRemoteDebuggerPresent)
1375 {
1376 win_skip("CheckRemoteDebuggerPresent not available, skipping test.\n");
1377 return;
1378 }
1379
1380 get_file_name(blackbox_file);
1381 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(name) + strlen(arguments) + strlen(blackbox_file) + 5);
1382 sprintf(cmd, "%s %s \"%s\"", name, arguments, blackbox_file);
1383
1384 p = strrchr(blackbox_file, '\\');
1385 p = p ? p+1 : blackbox_file;
1386 strcpy(event_name, p);
1387 strcat(event_name, "_init");
1388 event_init = CreateEventA(NULL, FALSE, FALSE, event_name);
1389 ok(event_init != NULL, "OpenEvent failed, last error %ld.\n", GetLastError());
1390
1391 p = strrchr(blackbox_file, '\\');
1392 p = p ? p+1 : blackbox_file;
1393 strcpy(event_name, p);
1394 strcat(event_name, "_attach");
1395 event_attach = CreateEventA(NULL, FALSE, flag!=0, event_name);
1396 ok(event_attach != NULL, "CreateEvent failed, last error %ld.\n", GetLastError());
1397
1398 memset(&si, 0, sizeof(si));
1399 si.cb = sizeof(si);
1400
1402 ok(ret, "CreateProcess failed, last error %ld.\n", GetLastError());
1404 if (!flag)
1405 {
1406 WaitForSingleObject(event_init, INFINITE);
1407 Sleep(100);
1409 ok(ret, "DebugActiveProcess failed, last error %ld.\n", GetLastError());
1410 }
1411
1412 ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
1413 ok(ret, "CheckRemoteDebuggerPresent failed, last error %ld.\n", GetLastError());
1414 ok(debug, "Expected debug != 0, got %x.\n", debug);
1415
1416 trace("starting debugger loop\n");
1417
1418 if (flag)
1419 {
1420 DWORD last_thread;
1421
1423 ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1424 ok(ctx.pid == pi.dwProcessId, "unexpected dwProcessId %x\n", ctx.ev.dwProcessId == ctx.pid);
1425
1427 ok(ctx.ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1428 last_thread = ctx.ev.dwThreadId;
1429
1431 ok(ctx.dll_cnt > 2, "dll_cnt = %d\n", ctx.dll_cnt);
1432
1433 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1434 ok(ctx.ev.dwThreadId == last_thread, "unexpected thread\n");
1435 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
1436 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
1437
1438 /* Except for wxppro and w2008, the initial breakpoint is now somewhere else, possibly within LdrInitShimEngineDynamic,
1439 * It's also catching exceptions and ContinueDebugEvent(DBG_EXCEPTION_NOT_HANDLED) should not crash the child now */
1440#ifdef __REACTOS__
1441 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress != pDbgBreakPoint || broken(GetNTVersion() <= _WIN32_WINNT_VISTA), "ExceptionAddress == pDbgBreakPoint\n");
1442#else
1443 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress != pDbgBreakPoint, "ExceptionAddress == pDbgBreakPoint\n");
1444#endif
1445
1446 if (pass_exception)
1447 {
1448 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
1449 ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError());
1450 ctx.ev.dwDebugEventCode = -1;
1451
1453#ifdef __REACTOS__
1454 ok(ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT || broken(GetNTVersion() <= _WIN32_WINNT_WS03), "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1455#else
1456 ok(ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1457#endif
1458 }
1459 }
1460 else
1461 {
1462 DWORD last_thread;
1463
1464 process_attach_events(&ctx, pass_exception);
1465 ok(ctx.pid == pi.dwProcessId, "unexpected dwProcessId %lx\n", ctx.pid);
1466
1468 ok(ret, "BreakProcess failed: %lu\n", GetLastError());
1469
1470 /* a new thread, which executes DbgBreakPoint, is created */
1472 ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1473 last_thread = ctx.ev.dwThreadId;
1474
1475 if (ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
1477
1478 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1479 ok(ctx.ev.dwThreadId == last_thread, "unexpected thread\n");
1480 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
1481 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
1482 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == pDbgBreakPoint, "ExceptionAddress != DbgBreakPoint\n");
1483
1484 ret = SetEvent(event_attach);
1485 ok(ret, "SetEvent failed, last error %ld.\n", GetLastError());
1486
1487 if (pass_exception)
1488 {
1489 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
1490 ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError());
1491 ctx.ev.dwDebugEventCode = -1;
1492 }
1493 }
1494
1496 while (ctx.ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT || ctx.ev.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT
1497 || ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT || ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT);
1498
1499#ifdef __REACTOS__
1500 ok(ctx.ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT || broken(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) /* WS03 */, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1501#else
1502 ok(ctx.ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1503#endif
1504 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_CONTINUE);
1505 ok(ret, "ContinueDebugEvent failed, last error %ld.\n", GetLastError());
1506
1507 if(debug_child)
1508 ok(ctx.process_cnt == 2, "didn't get any child events (flag: %lx).\n", flag);
1509 else
1510 ok(ctx.process_cnt == 1, "got child event (flag: %lx).\n", flag);
1511 CloseHandle(event_init);
1512 CloseHandle(event_attach);
1513
1515 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1517 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1518
1519 load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
1520 ok(!blackbox.failures, "Got %ld failures from child process.\n", blackbox.failures);
1521
1522 ret = DeleteFileA(blackbox_file);
1523 ok(ret, "DeleteFileA failed, last error %ld.\n", GetLastError());
1524}
#define GetNTVersion()
Definition: apitest.h:17
BOOL WINAPI DebugBreakProcess(IN HANDLE Process)
Definition: debugger.c:520
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
#define wait_for_breakpoint(a)
Definition: debugger.c:412
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25

Referenced by START_TEST().

◆ test_debug_loop()

static void test_debug_loop ( int  argc,
char **  argv 
)
static

Definition at line 1025 of file debugger.c.

1026{
1027 const char *arguments = " debugger child ";
1028 struct child_blackbox blackbox;
1029 char blackbox_file[MAX_PATH];
1032 BOOL debug;
1033 DWORD pid;
1034 char *cmd;
1035 BOOL ret;
1036
1037 if (!pCheckRemoteDebuggerPresent)
1038 {
1039 win_skip("CheckRemoteDebuggerPresent not available, skipping test.\n");
1040 return;
1041 }
1042#if defined(__REACTOS__) && defined(_WIN64)
1043 if (is_reactos()) {
1044 /* In theory this should be caught below and exit. In practice stack
1045 * corruption occurs and the test crashes after exiting this function. */
1046 skip("FIXME: Skipping test on ReactOS x64 because it is 64bit only!\n");
1047 return;
1048 }
1049#endif
1050 if (sizeof(void *) > sizeof(int))
1051 {
1054 wcscat( buffer, L"\\oleacc.dll" );
1056 {
1057 skip("Skipping test on 64bit only configuration\n");
1058 return;
1059 }
1060 }
1061
1064 ok(!ret, "DebugActiveProcess() succeeded on own process.\n");
1065
1066 get_file_name(blackbox_file);
1067 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 2 + 10);
1068 sprintf(cmd, "%s%s%08lx \"%s\"", argv[0], arguments, pid, blackbox_file);
1069
1070 memset(&si, 0, sizeof(si));
1071 si.cb = sizeof(si);
1073 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
1074
1076
1077 ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
1078 ok(ret, "CheckRemoteDebuggerPresent failed, last error %#lx.\n", GetLastError());
1079 ok(debug, "Expected debug != 0, got %#x.\n", debug);
1080
1081 for (;;)
1082 {
1083 DEBUG_EVENT ev;
1084
1086 ok(ret, "WaitForDebugEvent failed, last error %#lx.\n", GetLastError());
1087 if (!ret) break;
1088
1090 check_dll_event( pi.hProcess, &ev );
1091#if defined(__i386__) || defined(__x86_64__)
1094 {
1095 BYTE byte = 0;
1097 ok(byte == 0xcc, "got %02x\n", byte);
1098 }
1099#endif
1101 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
1102 if (!ret) break;
1103 }
1104
1105 /* sometimes not all unload events are sent on win7 */
1106 ok( ole32_mod == (HMODULE)1 || broken( ole32_mod != NULL ), "ole32.dll was not reported\n" );
1107 ok( oleaut32_mod == (HMODULE)1, "oleaut32.dll was not reported\n" );
1108#ifdef _WIN64
1109 ok( oleacc_mod == (HMODULE)1, "oleacc.dll was not reported\n" );
1110#else
1111 ok( oleacc_mod == NULL, "oleacc.dll was reported\n" );
1112#endif
1113
1115 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
1117 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
1118
1119 load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
1120 ok(!blackbox.failures, "Got %ld failures from child process.\n", blackbox.failures);
1121
1122 ret = DeleteFileA(blackbox_file);
1123 ok(ret, "DeleteFileA failed, last error %#lx.\n", GetLastError());
1124}
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
GLuint buffer
Definition: glext.h:5915
static void check_dll_event(HANDLE process, DEBUG_EVENT *ev)
Definition: debugger.c:1001
NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
Definition: virtual.c:2781
#define is_reactos()
Definition: test.h:1041
DWORD dwThreadId
Definition: minwinbase.h:198
DWORD dwProcessId
Definition: minwinbase.h:197
EXCEPTION_DEBUG_INFO Exception
Definition: minwinbase.h:201
EXCEPTION_RECORD ExceptionRecord
Definition: minwinbase.h:152
DWORD ExceptionCode
Definition: compat.h:208
PVOID ExceptionAddress
Definition: compat.h:211
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158

Referenced by START_TEST().

◆ test_debug_loop_wow64()

static void test_debug_loop_wow64 ( void  )
static

Definition at line 1159 of file debugger.c.

1160{
1164 BOOL ret;
1165 unsigned order = 0, bp_order = 0, bpwx_order = 0, num_ntdll = 0, num_wow64 = 0;
1166
1167 /* checking conditions for running this test */
1168#if defined(__REACTOS__) && defined(_WIN64)
1169 if (is_reactos()) {
1170 skip("FIXME: ReactOS x64 does not have WoW64 yet!\n");
1171 return;
1172 }
1173#endif
1174 if (GetSystemWow64DirectoryW( buffer, ARRAY_SIZE(buffer) ) && sizeof(void*) > sizeof(int) && pGetMappedFileNameW)
1175 {
1176 wcscat( buffer, L"\\msinfo32.exe" );
1178 }
1179 else ret = FALSE;
1180 if (!ret)
1181 {
1182 skip("Skipping test on incompatible config\n");
1183 return;
1184 }
1185 memset( &si, 0, sizeof(si) );
1186 si.cb = sizeof(si);
1188 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
1189
1190 for (;;)
1191 {
1192 DEBUG_EVENT ev;
1193
1194 ++order;
1195 ret = WaitForDebugEvent( &ev, 2000 );
1196 if (!ret) break;
1197
1198 switch (ev.dwDebugEventCode)
1199 {
1201 break;
1203 if (!pGetMappedFileNameW( pi.hProcess, ev.u.LoadDll.lpBaseOfDll, buffer, ARRAY_SIZE(buffer) )) buffer[0] = L'\0';
1204 if ((p = wcsrchr( buffer, '\\' ))) p++;
1205 else p = buffer;
1206 if (!wcsnicmp( p, L"wow64", 5 ) || !wcsicmp( p, L"xtajit.dll" ))
1207 {
1208 /* on Win10, wow64cpu's load dll event is received after first exception */
1209 ok(bpwx_order == 0, "loaddll for wow64 DLLs should appear before exception\n");
1210 num_wow64++;
1211 }
1212 else if (!wcsicmp( p, L"ntdll.dll" ))
1213 {
1214 ok(bp_order == 0 && bpwx_order == 0, "loaddll on ntdll should appear before exception\n");
1215 num_ntdll++;
1216 }
1217 break;
1220 bp_order = order;
1222 bpwx_order = order;
1223 }
1225 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
1226 if (!ret) break;
1227 }
1228
1229 /* gracefully terminates msinfo32 */
1231
1232 /* eat up the remaining events... not generating unload dll events in case of process termination */
1233 for (;;)
1234 {
1235 DEBUG_EVENT ev;
1236
1237 ret = WaitForDebugEvent( &ev, 2000 );
1238 if (!ret || ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
1239 switch (ev.dwDebugEventCode)
1240 {
1241 default:
1242 ok(0, "Unexpected event: %lu\n", ev.dwDebugEventCode);
1243 /* fall through */
1246 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
1247 break;
1248 }
1249 }
1250
1252 if (ret != WAIT_OBJECT_0)
1253 {
1254 DWORD ec;
1256 ok(ret, "GetExitCodeProcess failed: %lu\n", GetLastError());
1257 ok(ec != STILL_ACTIVE, "GetExitCodeProcess still active\n");
1258 }
1259 for (;;)
1260 {
1261 DEBUG_EVENT ev;
1262
1263 ret = WaitForDebugEvent( &ev, 2000 );
1264 if (!ret || ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
1265 switch (ev.dwDebugEventCode)
1266 {
1267 default:
1268 ok(0, "Unexpected event: %lu\n", ev.dwDebugEventCode);
1269 /* fall through */
1272 ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError());
1273 break;
1274 }
1275 }
1277 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
1279 ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError());
1280
1281 if (strcmp( winetest_platform, "wine" ) || num_wow64) /* windows or new wine wow */
1282 {
1283 ok(num_ntdll == 2, "Expecting two ntdll instances\n");
1284 ok(num_wow64 >= 3, "Expecting more than 3 wow64*.dll\n");
1285 }
1286 else /* Wine's old wow, or 32/64 bit only configurations */
1287 {
1288 ok(num_ntdll == 1, "Expecting one ntdll instances\n");
1289 ok(num_wow64 == 0, "Expecting more no wow64*.dll\n");
1290 }
1291 ok(bp_order, "Expecting 1 bp exceptions\n");
1292 todo_wine
1293 {
1294 ok(bpwx_order, "Expecting 1 bpwx exceptions\n");
1295 ok(bp_order < bpwx_order, "Out of order bp exceptions\n");
1296 }
1297}
#define wcsnicmp
Definition: compat.h:14
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4600
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
const char * winetest_platform
#define STILL_ACTIVE
Definition: minwinbase.h:43
static void close_main_windows(DWORD pid)
Definition: debugger.c:1148
#define STATUS_WX86_BREAKPOINT
Definition: ntstatus.h:220

Referenced by START_TEST().

◆ test_debugger()

static void test_debugger ( const char argv0)
static

Definition at line 1645 of file debugger.c.

1646{
1647 static const char arguments[] = " debugger wait ";
1648 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
1649 struct debugger_context ctx = { 0 };
1654 BYTE *mem, buf[4096], *proc_code, *thread_proc, byte;
1655 unsigned int i, worker_cnt, exception_cnt, skip_reply_later;
1657 char *cmd;
1658 BOOL ret;
1659
1660 event = CreateEventW(&sa, FALSE, FALSE, NULL);
1661 ok(event != NULL, "CreateEvent failed: %lu\n", GetLastError());
1662
1663 cmd = heap_alloc(strlen(argv0) + strlen(arguments) + 16);
1664 sprintf(cmd, "%s%s%lx %u\n", argv0, arguments, (DWORD)(DWORD_PTR)event, OP_BP ? 3 : 1);
1665
1666 memset(&si, 0, sizeof(si));
1667 si.cb = sizeof(si);
1669 ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError());
1670 heap_free(cmd);
1671
1673 ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1674
1675 if ((skip_reply_later = !ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER)))
1676 win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
1677 else
1678 {
1679 DEBUG_EVENT de;
1680
1681 de = ctx.ev;
1682 ctx.ev.dwDebugEventCode = -1;
1684 ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1685 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode);
1686 ok(de.dwProcessId == ctx.ev.dwProcessId,
1687 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de.dwProcessId);
1688 ok(de.dwThreadId == ctx.ev.dwThreadId,
1689 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de.dwThreadId);
1690
1691 /* Suspending the thread should prevent other attach debug events
1692 * to be received until it's resumed */
1693 thread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ctx.ev.dwThreadId);
1694 ok(thread != INVALID_HANDLE_VALUE, "OpenThread failed, last error:%lu\n", GetLastError());
1695
1697 ok(!status, "NtSuspendThread failed, last error:%lu\n", GetLastError());
1698
1699 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER);
1700 ok(ret, "ContinueDebugEvent failed, last error:%lu\n", GetLastError());
1701 ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n");
1702
1704 ok(!status, "NtResumeThread failed, last error:%lu\n", GetLastError());
1705
1707 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1708
1709 ok(WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent failed.\n");
1710 ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1711 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode);
1712
1714 ok(ctx.ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1715 de = ctx.ev;
1716
1717 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER);
1718 ok(ret, "ContinueDebugEvent failed, last error:%lu\n", GetLastError());
1719
1720 ctx.ev.dwDebugEventCode = -1;
1722 ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1723 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode);
1724 ok(de.dwProcessId == ctx.ev.dwProcessId,
1725 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de.dwProcessId);
1726 ok(de.dwThreadId == ctx.ev.dwThreadId,
1727 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de.dwThreadId);
1728 }
1729
1732 while(ctx.ev.dwDebugEventCode != -1);
1733
1735 ok(mem != NULL, "VirtualAllocEx failed: %lu\n", GetLastError());
1736 proc_code = buf + 1024;
1737 thread_proc = mem + 1024;
1738
1739 if (sizeof(loop_code) > 1)
1740 {
1741 /* test single-step exceptions */
1742 memset(buf, OP_BP, sizeof(buf));
1743 memcpy(proc_code, &loop_code, sizeof(loop_code));
1744 proc_code[0] = OP_BP; /* set a breakpoint */
1746 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1747
1749 ok(thread != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
1750
1752 debuggee_thread = get_debuggee_thread(&ctx, ctx.ev.dwThreadId);
1753
1756 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == thread_proc,
1757 "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress);
1758 ok(get_ip(&debuggee_thread->ctx) == thread_proc + 1, "unexpected instruction pointer %p\n",
1760
1764
1765 byte = 0xc3; /* ret */
1767 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1768
1770 }
1771 else todo_wine win_skip("loop_code not supported on this architecture\n");
1772
1773 if (sizeof(call_debug_service_code) > 1)
1774 {
1775 /* test debug service exceptions */
1776 memset(buf, OP_BP, sizeof(buf));
1779 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1780
1781 /* BREAKPOINT_PRINT */
1782#ifndef __REACTOS__ // These tests don't pass on WS03-Win10 1607
1783 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, (void*)2, 0, NULL);
1784 ok(thread != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
1788#endif
1789
1790 /* BREAKPOINT_PROMPT */
1791 thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, (void*)1, 0, NULL);
1792 ok(thread != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
1795 /* some 32-bit Windows versions report exception to the debugger */
1796 if (sizeof(void *) == 4 && ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) next_event(&ctx, WAIT_EVENT_TIMEOUT);
1797#if defined(__REACTOS__) && defined(_WIN64)
1798 ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT || broken(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) /* Win8+ x64 */, "unexpected debug event %lu\n", ctx.ev.dwDebugEventCode);
1799#else
1800 ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT, "unexpected debug event %lu\n", ctx.ev.dwDebugEventCode);
1801#endif
1802 }
1803 else todo_wine win_skip("call_debug_service_code not supported on this architecture\n");
1804
1805 if (skip_reply_later)
1806 win_skip("Skipping unsupported DBG_REPLY_LATER tests\n");
1807 else if (sizeof(loop_code) > 1)
1808 {
1809 HANDLE thread_a, thread_b;
1810 DEBUG_EVENT de_a, de_b;
1811
1812 memset(buf, OP_BP, sizeof(buf));
1813 memcpy(proc_code, &loop_code, sizeof(loop_code));
1815 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1816
1817 byte = OP_BP;
1818 ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL);
1819 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1820
1821 thread_a = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, NULL, 0, NULL);
1822 ok(thread_a != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
1824 ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1825 de_a = ctx.ev;
1826
1827 thread_b = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, NULL, 0, NULL);
1828 ok(thread_b != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
1830 while(ctx.ev.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT);
1831 de_b = ctx.ev;
1832
1833 status = NtSuspendThread(thread_b, NULL);
1834 ok(!status, "NtSuspendThread failed, last error:%lu\n", GetLastError());
1835 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER);
1836 ok(ret, "ContinueDebugEvent failed, last error:%lu\n", GetLastError());
1837
1838 ctx.ev.dwDebugEventCode = -1;
1840 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT,
1841 "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1842 ok(de_a.dwProcessId == ctx.ev.dwProcessId,
1843 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_a.dwProcessId);
1844 ok(de_a.dwThreadId == ctx.ev.dwThreadId,
1845 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_a.dwThreadId);
1846 de_a = ctx.ev;
1847
1848 byte = 0xc3; /* ret */
1849 ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL);
1850 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
1851
1852 ok(pNtSuspendProcess != NULL, "NtSuspendProcess not found\n");
1853 ok(pNtResumeProcess != NULL, "pNtResumeProcess not found\n");
1854 if (pNtSuspendProcess && pNtResumeProcess)
1855 {
1857 status = pNtSuspendProcess(pi.hProcess);
1858 ok(!status, "NtSuspendProcess failed, last error:%lu\n", GetLastError());
1859 do
1860 {
1861 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, action);
1862 ok(ret, "ContinueDebugEvent failed, last error:%lu\n", GetLastError());
1864 ok(!ret || ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "WaitForDebugEvent succeeded.\n");
1865 if (ret) add_thread(&ctx, ctx.ev.dwThreadId);
1867 } while (ret);
1868
1869 status = NtResumeThread(thread_b, NULL);
1870 ok(!status, "NtResumeThread failed, last error:%lu\n", GetLastError());
1872 {
1873 ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "Unexpected debug event %lx\n", ctx.ev.dwDebugEventCode);
1874 if (ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
1875 {
1876 add_thread(&ctx, ctx.ev.dwThreadId);
1877 ret = ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_CONTINUE);
1878 ok(ret, "ContinueDebugEvent failed, last error:%lu\n", GetLastError());
1879 }
1880 }
1881
1882 status = pNtResumeProcess(pi.hProcess);
1883 ok(!status, "pNtResumeProcess failed, last error:%lu\n", GetLastError());
1884 }
1885 else
1886 {
1887 status = NtResumeThread(thread_b, NULL);
1888 ok(!status, "NtResumeThread failed, last error:%lu\n", GetLastError());
1889 ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n");
1890 }
1891
1892 /* Testing shows that on windows the debug event order between threads
1893 * is not guaranteed.
1894 *
1895 * Now we expect thread_a to report:
1896 * - its delayed EXCEPTION_DEBUG_EVENT
1897 * - EXIT_THREAD_DEBUG_EVENT
1898 *
1899 * and thread_b to report:
1900 * - its delayed CREATE_THREAD_DEBUG_EVENT
1901 * - EXIT_THREAD_DEBUG_EVENT
1902 *
1903 * We should not get EXCEPTION_DEBUG_EVENT from thread_b as we updated
1904 * its instructions before continuing CREATE_THREAD_DEBUG_EVENT.
1905 */
1906 ctx.ev.dwDebugEventCode = -1;
1908
1909 if (ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
1910 {
1911 ok(de_a.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1912 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de_a.dwDebugEventCode);
1913 ok(de_a.dwProcessId == ctx.ev.dwProcessId,
1914 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_a.dwProcessId);
1915 ok(de_a.dwThreadId == ctx.ev.dwThreadId,
1916 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_a.dwThreadId);
1917
1919 if (ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
1920 {
1921 ok(de_a.dwProcessId == ctx.ev.dwProcessId,
1922 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_a.dwProcessId);
1923 ok(de_a.dwThreadId == ctx.ev.dwThreadId,
1924 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_a.dwThreadId);
1925
1926 ret = CloseHandle(thread_a);
1927 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1928 thread_a = NULL;
1929
1931 }
1932
1933 ok(de_b.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1934 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de_b.dwDebugEventCode);
1935 ok(de_b.dwProcessId == ctx.ev.dwProcessId,
1936 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_b.dwProcessId);
1937 ok(de_b.dwThreadId == ctx.ev.dwThreadId,
1938 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_b.dwThreadId);
1939 }
1940 else
1941 {
1942 ok(de_b.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1943 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de_b.dwDebugEventCode);
1944 ok(de_b.dwProcessId == ctx.ev.dwProcessId,
1945 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_b.dwProcessId);
1946 ok(de_b.dwThreadId == ctx.ev.dwThreadId,
1947 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_b.dwThreadId);
1948
1950 if (ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
1951 {
1952 ok(de_b.dwProcessId == ctx.ev.dwProcessId,
1953 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_b.dwProcessId);
1954 ok(de_b.dwThreadId == ctx.ev.dwThreadId,
1955 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_b.dwThreadId);
1956
1957 ret = CloseHandle(thread_b);
1958 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1959 thread_b = NULL;
1960
1962 }
1963
1964 ok(de_a.dwDebugEventCode == ctx.ev.dwDebugEventCode,
1965 "dwDebugEventCode differs: %lx (was %lx)\n", ctx.ev.dwDebugEventCode, de_a.dwDebugEventCode);
1966 ok(de_a.dwProcessId == ctx.ev.dwProcessId,
1967 "dwProcessId differs: %lx (was %lx)\n", ctx.ev.dwProcessId, de_a.dwProcessId);
1968 ok(de_a.dwThreadId == ctx.ev.dwThreadId,
1969 "dwThreadId differs: %lx (was %lx)\n", ctx.ev.dwThreadId, de_a.dwThreadId);
1970 }
1971
1972 if (thread_a)
1973 {
1975 ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT,
1976 "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1977
1978 ret = CloseHandle(thread_a);
1979 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1980 }
1981
1982
1983 if (thread_b)
1984 {
1986 ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT,
1987 "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
1988
1989 ret = CloseHandle(thread_b);
1990 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
1991 }
1992 }
1993
1994 if (sizeof(loop_code) > 1)
1995 {
1996 unsigned event_order = 0;
1997
1998 memset(buf, OP_BP, sizeof(buf));
1999 memcpy(proc_code, &loop_code, sizeof(loop_code));
2001 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2002
2003 ctx.thread_tag = 1;
2004
2005 worker_cnt = 20;
2006 for (i = 0; i < worker_cnt; i++)
2007 {
2008 DWORD tid;
2010 ok(thread != NULL, "CreateRemoteThread failed: %lu\n", GetLastError());
2011
2012 do
2013 {
2015#if defined(__REACTOS__) && defined(_WIN64)
2016 ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT || broken(GetNTVersion() >= EXCEPTION_DEBUG_EVENT) /* Win8+ x64 */, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
2017#else
2018 ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
2019#endif
2020 } while (ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT && ctx.ev.dwThreadId != tid);
2021#if defined(__REACTOS__) && defined(_WIN64)
2022 ok(ctx.ev.u.CreateThread.lpStartAddress == (void*)thread_proc || broken(GetNTVersion() != _WIN32_WINNT_WIN7), "Unexpected thread's start address\n");
2023#elif defined(__REACTOS__)
2024 ok(ctx.ev.u.CreateThread.lpStartAddress == (void*)thread_proc || broken(GetNTVersion() <= _WIN32_WINNT_VISTA), "Unexpected thread's start address\n");
2025#else
2026 ok(ctx.ev.u.CreateThread.lpStartAddress == (void*)thread_proc, "Unexpected thread's start address\n");
2027#endif
2028
2030 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
2031 }
2032
2033 byte = OP_BP;
2034 ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL);
2035 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2036
2038#if defined(__REACTOS__) && defined(_WIN64)
2040#endif
2042 exception_cnt = 1;
2043
2044 byte = 0xc3; /* ret */
2045 ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL);
2046 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2047
2048 /* One would expect that we get all exception debug events (for the worker threads
2049 * that hit the BP instruction), then the exit thread events for all created threads.
2050 * It happens that on Windows, the exception & exit thread events can be intertwined.
2051 * So detect this situation.
2052 */
2053#if defined(__REACTOS__) && defined(_WIN64)
2055 skip("These tests run far too long on Windows 8+ x64 and ReactOS x64.\n");
2056 } else {
2057#endif
2058 for (;;)
2059 {
2060 DEBUG_EVENT ev;
2061
2062 fetch_thread_context(ctx.current_thread);
2063 ok(get_ip(&ctx.current_thread->ctx) == thread_proc + 2
2064 || broken(get_ip(&ctx.current_thread->ctx) == thread_proc), /* sometimes observed on win10 */
2065 "unexpected instruction pointer2 %p (%p)\n", get_ip(&ctx.current_thread->ctx), thread_proc);
2066 /* even when there are more pending events, they are not reported until current event is continued */
2067 ret = WaitForDebugEvent(&ev, 10);
2068 ok(GetLastError() == ERROR_SEM_TIMEOUT, "WaitForDebugEvent returned %x(%lu)\n", ret, GetLastError());
2069
2070 for (;;)
2071 {
2073 if (ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) break;
2074 if (ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
2075 {
2076 if (event_order == 0) event_order = 1; /* first exit thread event */
2077 if (!--worker_cnt) break;
2078 }
2079 }
2080 if (!worker_cnt) break;
2081
2082 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
2083 trace("exception at %p in thread %04lx\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress, ctx.ev.dwThreadId);
2084 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
2085 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
2086 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == thread_proc + 1,
2087 "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress);
2088 exception_cnt++;
2089 if (event_order == 1) event_order = 2; /* exception debug event after exit thread event */
2090 }
2091
2092 trace("received %u exceptions\n", exception_cnt);
2093 ok(!worker_cnt, "Missing %u exit thread events\n", worker_cnt);
2094 ok(event_order == 1 || broken(event_order == 2), "Intertwined exit thread & exception debug events\n");
2095 }
2096#if defined(__REACTOS__) && defined(_WIN64)
2097 }
2098#endif
2099
2100 if (OP_BP)
2101 {
2102 CONTEXT orig_context;
2103 char instr, *ip;
2104
2105 /* main thread sleeps inside ntdll waiting for the event. set breakpoint there and make sure
2106 * ntdll can handle that. */
2107 SuspendThread(ctx.main_thread->handle);
2108
2109 fetch_thread_context(ctx.main_thread);
2110 ret = ReadProcessMemory(pi.hProcess, get_ip(&ctx.main_thread->ctx), &instr, 1, NULL);
2111 ok(ret, "ReadProcessMemory failed: %lu\n", GetLastError());
2112
2113 orig_context = ctx.main_thread->ctx;
2114 ip = get_ip(&ctx.main_thread->ctx);
2115
2116#if defined(__i386__)
2117 ctx.main_thread->ctx.Eax = 101;
2118 ctx.main_thread->ctx.Ebx = 102;
2119 ctx.main_thread->ctx.Ecx = 103;
2120 ctx.main_thread->ctx.Edx = 104;
2121 ctx.main_thread->ctx.Esi = 105;
2122 ctx.main_thread->ctx.Edi = 106;
2123#elif defined(__x86_64__)
2124 ctx.main_thread->ctx.Rax = 101;
2125 ctx.main_thread->ctx.Rbx = 102;
2126 ctx.main_thread->ctx.Rcx = 103;
2127 ctx.main_thread->ctx.Rdx = 104;
2128 ctx.main_thread->ctx.Rsi = 105;
2129 ctx.main_thread->ctx.Rdi = 106;
2130 ctx.main_thread->ctx.R8 = 107;
2131 ctx.main_thread->ctx.R9 = 108;
2132 ctx.main_thread->ctx.R10 = 109;
2133 ctx.main_thread->ctx.R11 = 110;
2134 ctx.main_thread->ctx.R12 = 111;
2135 ctx.main_thread->ctx.R13 = 112;
2136 ctx.main_thread->ctx.R14 = 113;
2137 ctx.main_thread->ctx.R15 = 114;
2138#endif
2139 set_thread_context(&ctx, ctx.main_thread);
2140
2141 fetch_thread_context(ctx.main_thread);
2142#if defined(__i386__)
2143 /* win2k8 do not preserve eax, rcx and edx; newer versions do */
2144 ok(ctx.main_thread->ctx.Ebx == 102, "Ebx = %lx\n", ctx.main_thread->ctx.Ebx);
2145 ok(ctx.main_thread->ctx.Esi == 105, "Esi = %lx\n", ctx.main_thread->ctx.Esi);
2146 ok(ctx.main_thread->ctx.Edi == 106, "Edi = %lx\n", ctx.main_thread->ctx.Edi);
2147#elif defined(__x86_64__)
2148 ok(ctx.main_thread->ctx.Rax == 101, "Rax = %I64x\n", ctx.main_thread->ctx.Rax);
2149 ok(ctx.main_thread->ctx.Rbx == 102, "Rbx = %I64x\n", ctx.main_thread->ctx.Rbx);
2150 ok(ctx.main_thread->ctx.Rcx == 103, "Rcx = %I64x\n", ctx.main_thread->ctx.Rcx);
2151 ok(ctx.main_thread->ctx.Rdx == 104, "Rdx = %I64x\n", ctx.main_thread->ctx.Rdx);
2152 ok(ctx.main_thread->ctx.Rsi == 105, "Rsi = %I64x\n", ctx.main_thread->ctx.Rsi);
2153 ok(ctx.main_thread->ctx.Rdi == 106, "Rdi = %I64x\n", ctx.main_thread->ctx.Rdi);
2154 ok(ctx.main_thread->ctx.R8 == 107, "R8 = %I64x\n", ctx.main_thread->ctx.R8);
2155 ok(ctx.main_thread->ctx.R9 == 108, "R9 = %I64x\n", ctx.main_thread->ctx.R9);
2156 ok(ctx.main_thread->ctx.R10 == 109, "R10 = %I64x\n", ctx.main_thread->ctx.R10);
2157 ok(ctx.main_thread->ctx.R11 == 110, "R11 = %I64x\n", ctx.main_thread->ctx.R11);
2158 ok(ctx.main_thread->ctx.R12 == 111, "R12 = %I64x\n", ctx.main_thread->ctx.R12);
2159 ok(ctx.main_thread->ctx.R13 == 112, "R13 = %I64x\n", ctx.main_thread->ctx.R13);
2160 ok(ctx.main_thread->ctx.R14 == 113, "R14 = %I64x\n", ctx.main_thread->ctx.R14);
2161 ok(ctx.main_thread->ctx.R15 == 114, "R15 = %I64x\n", ctx.main_thread->ctx.R15);
2162#endif
2163
2164 byte = OP_BP;
2165 ret = WriteProcessMemory(pi.hProcess, ip, &byte, 1, NULL);
2166 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2167
2168 SetEvent(event);
2169 ResumeThread(ctx.main_thread->handle);
2170
2172 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
2173 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
2174 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
2175 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == ip,
2176 "ExceptionAddress = %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress);
2177
2178 fetch_thread_context(ctx.main_thread);
2179 ok(get_ip(&ctx.main_thread->ctx) == ip + 1, "unexpected instruction pointer %p\n", get_ip(&ctx.main_thread->ctx));
2180
2181#if defined(__i386__)
2182 ok(ctx.main_thread->ctx.Eax == 0, "Eax = %lx\n", ctx.main_thread->ctx.Eax);
2183 ok(ctx.main_thread->ctx.Ebx == 102, "Ebx = %lx\n", ctx.main_thread->ctx.Ebx);
2184 ok(ctx.main_thread->ctx.Ecx != 103, "Ecx = %lx\n", ctx.main_thread->ctx.Ecx);
2185 ok(ctx.main_thread->ctx.Edx != 104, "Edx = %lx\n", ctx.main_thread->ctx.Edx);
2186 ok(ctx.main_thread->ctx.Esi == 105, "Esi = %lx\n", ctx.main_thread->ctx.Esi);
2187 ok(ctx.main_thread->ctx.Edi == 106, "Edi = %lx\n", ctx.main_thread->ctx.Edi);
2188#elif defined(__x86_64__)
2189 ok(ctx.main_thread->ctx.Rax == 0, "Rax = %I64x\n", ctx.main_thread->ctx.Rax);
2190 ok(ctx.main_thread->ctx.Rbx == 102, "Rbx = %I64x\n", ctx.main_thread->ctx.Rbx);
2191 ok(ctx.main_thread->ctx.Rcx != 103, "Rcx = %I64x\n", ctx.main_thread->ctx.Rcx);
2192 ok(ctx.main_thread->ctx.Rdx != 104, "Rdx = %I64x\n", ctx.main_thread->ctx.Rdx);
2193 ok(ctx.main_thread->ctx.Rsi == 105, "Rsi = %I64x\n", ctx.main_thread->ctx.Rsi);
2194 ok(ctx.main_thread->ctx.Rdi == 106, "Rdi = %I64x\n", ctx.main_thread->ctx.Rdi);
2195 ok(ctx.main_thread->ctx.R8 != 107, "R8 = %I64x\n", ctx.main_thread->ctx.R8);
2196 ok(ctx.main_thread->ctx.R9 != 108, "R9 = %I64x\n", ctx.main_thread->ctx.R9);
2197 ok(ctx.main_thread->ctx.R10 != 109, "R10 = %I64x\n", ctx.main_thread->ctx.R10);
2198 ok(ctx.main_thread->ctx.R11 != 110, "R11 = %I64x\n", ctx.main_thread->ctx.R11);
2199 ok(ctx.main_thread->ctx.R12 == 111, "R12 = %I64x\n", ctx.main_thread->ctx.R12);
2200 ok(ctx.main_thread->ctx.R13 == 112, "R13 = %I64x\n", ctx.main_thread->ctx.R13);
2201 ok(ctx.main_thread->ctx.R14 == 113, "R14 = %I64x\n", ctx.main_thread->ctx.R14);
2202 ok(ctx.main_thread->ctx.R15 == 114, "R15 = %I64x\n", ctx.main_thread->ctx.R15);
2203#endif
2204
2205 ctx.main_thread->ctx = orig_context;
2206 set_ip(&ctx.main_thread->ctx, ip);
2207 set_thread_context(&ctx, ctx.main_thread);
2208
2209 ret = WriteProcessMemory(pi.hProcess, ip, &instr, 1, NULL);
2210 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2211
2212 memset(buf + 10, 0x90, 10); /* nop */
2213 ret = WriteProcessMemory(pi.hProcess, mem + 10, buf + 10, 10, NULL);
2214 ok(ret, "WriteProcessMemory failed: %lu\n", GetLastError());
2215
2217
2218 /* try single step while debuggee is in a syscall */
2219 fetch_thread_context(ctx.main_thread);
2220 orig_context = ctx.main_thread->ctx;
2221 ip = get_ip(&ctx.main_thread->ctx);
2222
2223#if defined(__i386__)
2224 ctx.main_thread->ctx.EFlags |= 0x100;
2225 ctx.main_thread->ctx.Eip = (ULONG_PTR)mem + 10;
2226#elif defined(__x86_64__)
2227 ctx.main_thread->ctx.EFlags |= 0x100;
2228 ctx.main_thread->ctx.Rip = (ULONG64)mem + 10;
2229#endif
2230 set_thread_context(&ctx, ctx.main_thread);
2231
2232 SetEvent(event);
2233
2235 if (sizeof(void*) != 4 || ctx.ev.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)
2236 {
2237 ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx.ev.dwDebugEventCode);
2238 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP, "ExceptionCode = %lx\n",
2239 ctx.ev.u.Exception.ExceptionRecord.ExceptionCode);
2240 ok(ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == mem + 10 ||
2241 ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress == mem + 11,
2242 "ExceptionAddress = %p expected %p\n", ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress, mem + 10);
2243
2244 fetch_thread_context(ctx.main_thread);
2245 ok(get_ip(&ctx.main_thread->ctx) == ctx.ev.u.Exception.ExceptionRecord.ExceptionAddress,
2246 "ip = %p\n", get_ip(&ctx.main_thread->ctx));
2247
2248 }
2249 else win_skip("got breakpoint instead of single step exception\n");
2250
2251 ctx.main_thread->ctx = orig_context;
2252 set_thread_context(&ctx, ctx.main_thread);
2253 }
2254
2255 SetEvent(event);
2256
2257#if defined(__REACTOS__) && defined(_MSC_VER)
2258 if (is_reactos()) {
2259 skip("This test doesn't work correctly on MSVC ReactOS.\n");
2260 } else {
2261#endif
2262 do
2263 {
2265 ok (ctx.ev.dwDebugEventCode != EXCEPTION_DEBUG_EVENT, "got exception\n");
2266 if (ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) break;
2267 }
2268 while (ctx.ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
2269 if (ctx.ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) TerminateProcess(pi.hProcess, 0);
2270#if defined(__REACTOS__) && defined(_MSC_VER)
2271 }
2272#endif
2273
2275 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
2277 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
2279 ok(ret, "CloseHandle failed, last error %ld.\n", GetLastError());
2280}
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:758
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:2064
HANDLE WINAPI CreateRemoteThread(IN HANDLE hProcess, IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:159
#define byte(x, n)
Definition: tomcrypt.h:118
action
Definition: namespace.c:707
#define ULONG_PTR
Definition: config.h:101
#define THREAD_SUSPEND_RESUME
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned __int64 ULONG64
Definition: imports.h:198
#define expect_event(a, b)
Definition: debugger.c:1532
static const BYTE call_debug_service_code[]
Definition: debugger.c:1594
static void set_ip(CONTEXT *ctx, void *ip)
Definition: debugger.c:297
#define next_event_filter(a, b, c)
Definition: debugger.c:403
static const BYTE loop_code[]
Definition: debugger.c:1585
#define check_breakpoint_exception(a, b)
Definition: debugger.c:1548
#define OP_BP
Definition: debugger.c:1642
#define expect_breakpoint_exception(a, b)
Definition: debugger.c:1561
#define single_step(a, b, c)
Definition: debugger.c:1568
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1311
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL)
Definition: state.c:352
#define DBG_REPLY_LATER
Definition: ntstatus.h:99
#define _WIN32_WINNT_WIN8
Definition: sdkddkver.h:29
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
ULONG Edx
Definition: nt_native.h:1469
ULONG Esi
Definition: nt_native.h:1467
ULONG R8
Definition: ke.h:263
ULONG Ecx
Definition: nt_native.h:1470
ULONG Eip
Definition: nt_native.h:1479
ULONG R12
Definition: ke.h:267
ULONG R9
Definition: ke.h:264
ULONG EFlags
Definition: nt_native.h:1481
ULONG R10
Definition: ke.h:265
ULONG Eax
Definition: nt_native.h:1471
ULONG Ebx
Definition: nt_native.h:1468
ULONG Edi
Definition: nt_native.h:1466
ULONG R11
Definition: ke.h:266
CONTEXT ctx
Definition: debugger.c:248
Definition: mem.c:349
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
CONTEXT ctx
LPVOID NTAPI VirtualAllocEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:23

Referenced by START_TEST().

◆ test_ExitCode()

static void test_ExitCode ( void  )
static

Definition at line 770 of file debugger.c.

771{
772 static const char* AeDebug="Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
773 static const char* WineDbg="Software\\Wine\\WineDbg";
774 char test_exe[MAX_PATH];
775 DWORD ret;
776 HKEY hkey;
777 DWORD disposition;
778 reg_save_value auto_value;
779 reg_save_value debugger_value;
780
781 GetModuleFileNameA(GetModuleHandleA(NULL), test_exe, sizeof(test_exe));
783 strcat(test_exe, ".so");
785 {
786 ok(0, "could not find the test executable '%s'\n", test_exe);
787 return;
788 }
789
791 if (ret == ERROR_SUCCESS)
792 {
793 save_value(hkey, "auto", &auto_value);
794 save_value(hkey, "debugger", &debugger_value);
795 trace("HKLM\\%s\\debugger is set to '%s'\n", AeDebug, debugger_value.data);
796 }
797 else if (ret == ERROR_ACCESS_DENIED)
798 {
799 skip("not enough privileges to change the debugger\n");
800 return;
801 }
802 else if (ret != ERROR_FILE_NOT_FOUND)
803 {
804 ok(0, "could not open the AeDebug key: %ld\n", ret);
805 return;
806 }
807 else
808 {
809 auto_value.data = NULL;
810 debugger_value.data = NULL;
811 }
812
813 if (debugger_value.data && debugger_value.type == REG_SZ &&
814 strstr((char*)debugger_value.data, "winedbg --auto"))
815 {
816 HKEY hkeyWinedbg;
817 ret=RegCreateKeyA(HKEY_CURRENT_USER, WineDbg, &hkeyWinedbg);
818 if (ret == ERROR_SUCCESS)
819 {
820 static DWORD zero;
821 reg_save_value crash_dlg_value;
822 save_value(hkeyWinedbg, "ShowCrashDialog", &crash_dlg_value);
823 RegSetValueExA(hkeyWinedbg, "ShowCrashDialog", 0, REG_DWORD, (BYTE *)&zero, sizeof(DWORD));
825 crash_and_winedbg(hkey, test_exe);
827 restore_value(hkeyWinedbg, &crash_dlg_value);
828 RegCloseKey(hkeyWinedbg);
829 }
830 else
831 ok(0, "Couldn't access WineDbg Key - error %lu\n", ret);
832 }
833
835 /* Since the debugging process never sets the debug event, it isn't recognized
836 as a valid debugger and, after the debugger exits, Windows will show a dialog box
837 asking the user what to do */
838 crash_and_debug(hkey, test_exe, "dbg,none");
839 else
840 skip("\"none\" debugger test needs user interaction\n");
841 ok(disposition == REG_OPENED_EXISTING_KEY, "expected REG_OPENED_EXISTING_KEY, got %ld\n", disposition);
842 crash_and_debug(hkey, test_exe, "dbg,event,order");
843 crash_and_debug(hkey, test_exe, "dbg,attach,event,code2");
844 crash_and_debug(hkey, test_exe, "dbg,attach,event,nokill");
845 crash_and_debug(hkey, test_exe, "dbg,attach,event,detach");
846 crash_and_debug(hkey, test_exe, "dbg,attach,detach,late");
847 crash_and_debug(hkey, test_exe, "dbg,attach,process,event,detach");
848
849 if (disposition == REG_CREATED_NEW_KEY)
850 {
851 RegCloseKey(hkey);
853 }
854 else
855 {
856 restore_value(hkey, &auto_value);
857 restore_value(hkey, &debugger_value);
858 RegCloseKey(hkey);
859 }
860}
#define RegCloseKey(hKey)
Definition: registry.h:49
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegCreateKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD Reserved, _In_ LPSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_ LPDWORD lpdwDisposition)
Definition: reg.c:1034
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
int winetest_interactive
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static void crash_and_winedbg(HKEY hkey, const char *argv0)
Definition: debugger.c:738
static void crash_and_debug(HKEY hkey, const char *argv0, const char *dbgtasks)
Definition: debugger.c:621
static DWORD save_value(HKEY hkey, const char *value, reg_save_value *saved)
Definition: debugger.c:89
static void restore_value(HKEY hkey, reg_save_value *saved)
Definition: debugger.c:104
#define KEY_ALL_ACCESS
Definition: nt_native.h:1044
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1060
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1087
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1088
#define REG_DWORD
Definition: sdbapi.c:615
#define ignore_exceptions
Definition: test.h:178
int zero
Definition: sehframes.cpp:29
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11

Referenced by START_TEST().

◆ test_kill_on_exit()

static void test_kill_on_exit ( const char argv0)
static

Definition at line 2355 of file debugger.c.

2356{
2357 static const char arguments[] = " debugger wait ";
2358 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
2359 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
2363 ULONG val;
2364 BOOL ret;
2365
2366 event = CreateEventW(&sa, FALSE, FALSE, NULL);
2367 ok(event != NULL, "CreateEvent failed: %lu\n", GetLastError());
2368
2369 cmd = heap_alloc(strlen(argv0) + strlen(arguments) + 16);
2370 sprintf(cmd, "%s%s%lx\n", argv0, arguments, (DWORD)(DWORD_PTR)event);
2371
2372 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0 );
2373 ok( !status, "NtCreateDebugObject failed %lx\n", status );
2374 pDbgUiSetThreadDebugObject( debug );
2376 ok( exit_code == 0, "exit code = %08lx\n", exit_code);
2377
2378 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
2379 ok( !status, "NtCreateDebugObject failed %lx\n", status );
2380 pDbgUiSetThreadDebugObject( debug );
2382 ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08lx\n", exit_code);
2383
2384 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0xfffe );
2385 ok( status == STATUS_INVALID_PARAMETER, "NtCreateDebugObject failed %lx\n", status );
2386
2387 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, 0 );
2388 ok( !status, "NtCreateDebugObject failed %lx\n", status );
2389 pDbgUiSetThreadDebugObject( debug );
2391 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2392 &val, sizeof(val), NULL );
2393 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
2395 ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08lx\n", exit_code);
2396
2397 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
2398 ok( !status, "NtCreateDebugObject failed %lx\n", status );
2399 pDbgUiSetThreadDebugObject( debug );
2400 val = 0;
2401 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2402 &val, sizeof(val), NULL );
2403 ok( !status, "NtSetInformationDebugObject failed %lx\n", status );
2405 ok( exit_code == 0, "exit code = %08lx\n", exit_code);
2406
2407 status = pDbgUiConnectToDbg();
2408 ok( !status, "DbgUiConnectToDbg failed %lx\n", status );
2410 ok( exit_code == STATUS_DEBUGGER_INACTIVE, "exit code = %08lx\n", exit_code);
2411
2412 /* test that threads close the debug port on exit */
2414 WaitForSingleObject( thread, 1000 );
2415 ok( debug != 0, "no debug port\n" );
2416 val = 0;
2417 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2418 &val, sizeof(val), NULL );
2420 "NtSetInformationDebugObject failed %lx\n", status );
2421 SetEvent( event );
2422 if (!status)
2423 {
2426 ok( exit_code == STILL_ACTIVE, "exit code = %08lx\n", exit_code);
2427 CloseHandle( debug );
2428 }
2431 ok( exit_code == 0, "exit code = %08lx\n", exit_code);
2435
2436 /* checking on forced exit */
2437 status = pNtCreateDebugObject( &debug, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
2438 ok( !status, "NtCreateDebugObject failed %lx\n", status );
2440 Sleep( 100 );
2441 ok( debug != 0, "no debug port\n" );
2443 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2444 &val, sizeof(val), NULL );
2445 ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status );
2446 TerminateThread( thread, 0 );
2447
2449 if (status != WAIT_OBJECT_0)
2450 {
2451 todo_wine /* Wine doesn't handle debug port of TerminateThread */
2452 ok(broken(sizeof(void*) == sizeof(int)), /* happens consistently on 32bit on Win7, 10 & 11 */
2453 "Terminating thread should terminate debuggee\n");
2454
2456 ok(ret, "TerminateProcess failed: %lu\n", GetLastError());
2457 CloseHandle( debug );
2458 }
2459 else
2460 {
2461 ok(status == WAIT_OBJECT_0, "debuggee didn't terminate %lx\n", status);
2463 ok(ret, "No exit code: %lu\n", GetLastError());
2464 todo_wine
2466 "exit code = %08lx\n", exit_code);
2467 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2468 &val, sizeof(val), NULL );
2469 todo_wine
2470 ok( status == STATUS_INVALID_HANDLE, "NtSetInformationDebugObject failed %lx\n", status );
2471 }
2472
2476
2477 debug = 0;
2479 Sleep(100);
2480 ok( debug != 0, "no debug port\n" );
2481 val = 0;
2482 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2483 &val, sizeof(val), NULL );
2484 ok( status == STATUS_SUCCESS, "NtSetInformationDebugObject failed %lx\n", status );
2485 TerminateThread( thread, 0 );
2486 Sleep( 200 );
2487 status = pNtSetInformationDebugObject( debug, DebugObjectKillProcessOnExitInformation,
2488 &val, sizeof(val), NULL );
2489 todo_wine
2491 "NtSetInformationDebugObject failed %lx\n", status );
2494
2495 CloseHandle( event );
2496 heap_free(cmd);
2497}
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
#define DEBUG_KILL_ON_CLOSE
Definition: winternl.h:4377
#define DEBUG_ALL_ACCESS
Definition: winternl.h:4375
static DWORD WINAPI create_debug_port(void *arg)
Definition: debugger.c:2344
static DWORD WINAPI debug_and_wait(void *arg)
Definition: debugger.c:2325
static DWORD WINAPI debug_and_exit(void *arg)
Definition: debugger.c:2306
static DWORD run_child_wait(char *cmd, HANDLE event)
Definition: debugger.c:2282
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cookie.c:202
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135

Referenced by START_TEST().

◆ test_RemoteDebugger()

static void test_RemoteDebugger ( void  )
static

Definition at line 862 of file debugger.c.

863{
864 BOOL bret, present;
865 if(!pCheckRemoteDebuggerPresent)
866 {
867 win_skip("CheckRemoteDebuggerPresent is not available\n");
868 return;
869 }
870 present = TRUE;
871 SetLastError(0xdeadbeef);
872 bret = pCheckRemoteDebuggerPresent(GetCurrentProcess(),&present);
873 ok(bret , "expected CheckRemoteDebuggerPresent to succeed\n");
874 ok(0xdeadbeef == GetLastError(),
875 "expected error to be unchanged, got %ld/%lx\n",GetLastError(), GetLastError());
876
877 present = TRUE;
878 SetLastError(0xdeadbeef);
879 bret = pCheckRemoteDebuggerPresent(NULL,&present);
880 ok(!bret , "expected CheckRemoteDebuggerPresent to fail\n");
881 ok(present, "expected parameter to be unchanged\n");
883 "expected error ERROR_INVALID_PARAMETER, got %ld/%lx\n",GetLastError(), GetLastError());
884
885 SetLastError(0xdeadbeef);
886 bret = pCheckRemoteDebuggerPresent(GetCurrentProcess(),NULL);
887 ok(!bret , "expected CheckRemoteDebuggerPresent to fail\n");
889 "expected error ERROR_INVALID_PARAMETER, got %ld/%lx\n",GetLastError(), GetLastError());
890}
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101

Referenced by START_TEST().

◆ thread_proc()

static DWORD WINAPI thread_proc ( void arg)
static

Definition at line 183 of file debugger.c.

184{
185 Sleep(10000);
186 trace("exiting\n");
187 ExitThread(1);
188}

Referenced by run_background_thread(), and test_debugger().

◆ void()

static void ( WINAPI pDbgBreakPoint)
static

◆ wait_debugger()

static void wait_debugger ( HANDLE  event,
unsigned int  cnt 
)
static

Definition at line 1526 of file debugger.c.

1527{
1529 ExitProcess(0);
1530}

Referenced by START_TEST().

◆ wait_for_breakpoint_()

static void wait_for_breakpoint_ ( unsigned  line,
struct debugger_context ctx 
)
static

Definition at line 413 of file debugger.c.

414{
417
418 ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, "dwDebugEventCode = %ld\n", ctx->ev.dwDebugEventCode);
419 ok_(__FILE__,line)(ctx->ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT, "ExceptionCode = %lx\n",
420 ctx->ev.u.Exception.ExceptionRecord.ExceptionCode);
421}
static void next_event_filter_(unsigned line, struct debugger_context *ctx, DWORD timeout, DWORD mask)
Definition: debugger.c:404

Variable Documentation

◆ ACCESS_MASK

Definition at line 49 of file debugger.c.

◆ call_debug_service_code

const BYTE call_debug_service_code[]
static

Definition at line 1594 of file debugger.c.

Referenced by test_debugger().

◆ child_failures

LONG child_failures
static

Definition at line 57 of file debugger.c.

Referenced by __WINE_PRINTF_ATTR(), doChild(), and doChildren().

◆ cmd

◆ DEBUGOBJECTINFOCLASS

Definition at line 50 of file debugger.c.

◆ DWORD

Definition at line 54 of file debugger.c.

◆ is_wow64

BOOL is_wow64
static

Definition at line 41 of file debugger.c.

Referenced by doChild(), and START_TEST().

◆ loop_code

const BYTE loop_code[]
static
Initial value:
= {
}

Definition at line 1585 of file debugger.c.

Referenced by test_debugger().

◆ myARGC

int myARGC
static

Definition at line 39 of file debugger.c.

Referenced by START_TEST().

◆ myARGV

char** myARGV
static

Definition at line 40 of file debugger.c.

Referenced by doDebugger(), and START_TEST().

◆ ntdll

◆ ole32_mod

HMODULE ole32_mod
static

Definition at line 999 of file debugger.c.

Referenced by check_dll_event(), and test_debug_loop().

◆ oleacc_mod

HMODULE oleacc_mod
static

Definition at line 999 of file debugger.c.

Referenced by check_dll_event(), and test_debug_loop().

◆ oleaut32_mod

HMODULE oleaut32_mod
static

Definition at line 999 of file debugger.c.

Referenced by check_dll_event(), and test_debug_loop().

◆ PBOOL

Definition at line 43 of file debugger.c.

◆ pi

Definition at line 2303 of file debugger.c.

Referenced by _create_process(), _ILCreatePrinterItem(), _tWinMain(), _wpopen(), acos(), acosf(), alloc_console(), apc_deadlock_thread(), APPINFO_QueryOption(), atan2(), atan2f(), AudioDlgProc(), CallUninstall(), CheckX64System(), Close(), cmd_available(), Compress(), CompressBegin(), CompressEnd(), CompressGetFormat(), CompressGetSize(), CompressQuery(), computeInternalFrame(), Configure(), create_pi(), create_proc(), create_process(), create_pseudo_console(), create_target_process(), CreateCallProc(), CreateClientProcess(), CPrintersEnum::CreatePrintersEnumList(), CreateTipText(), custom_start_server(), debug_and_exit(), debug_and_wait(), Decompress(), DecompressBegin(), DecompressEnd(), DecompressGetFormat(), DecompressGetPalette(), DecompressQuery(), DestroyProcessClasses(), doChildren(), domdoc_createProcessingInstruction(), DosCreateProcess(), DoTestEntry(), find_installed_ports(), find_portinfo2(), fork_helper(), FullPathExec(), GetInfo(), HotkeyThread(), IDirectInputAImpl_RunControlPanel(), ImageListImpl_Add(), ImageListImpl_AddMasked(), ImageListImpl_GetImageCount(), ImageListImpl_ReplaceIcon(), install_wine_gecko(), IntCheckProcessDesktopClasses(), IntCreateClass(), IntDereferenceClass(), InternetSetOptionA(), InternetSetOptionW(), IntGetClassAtom(), IntNtUserSetClassLongPtr(), CNetConnectionPropertyUi::LANPropertiesUIDlg(), launch_exe(), LaunchProcess(), LocalAddPortEx(), LocalmonAddPortEx(), main(), MD_ListView_OnGetColumnOrderArray(), MD_ListView_OnSetColumnOrderArray(), MSRLE32_CompressRLE4(), MSRLE32_CompressRLE4Line(), MSRLE32_CompressRLE8(), MSRLE32_CompressRLE8Line(), MSRLE32_DecompressRLE4(), MSRLE32_DecompressRLE8(), MSRLE32_DriverProc(), msvcrt_spawn(), CNewMenu::NewItemByCommand(), Telnet::NewProcess(), NtUserGetWOWClass(), Telnet::Open(), Open(), parse_patch_summary(), PrepAndLaunchRedirectedChild(), PRINTDLG_SetUpPrinterListComboA(), PRINTDLG_SetUpPrinterListComboW(), PRINTDLG_UpdatePrintDlgA(), PRINTDLG_UpdatePrintDlgW(), PRINTDLG_UpdatePrinterInfoTextsA(), PRINTDLG_UpdatePrinterInfoTextsW(), PrintDlgA(), PrintDlgW(), ProcessPage_OnDebug(), query_global_option(), read_reg_output_(), register_dll(), request_set_option(), restart_as_admin_elevated(), run_child_process(), run_child_process_two_dll(), run_child_wait(), run_cmd(), run_ex(), run_rapps(), run_reg_exe_(), run_regedit_exe_(), run_script_file(), run_winemenubuilder(), runcmd(), runscriptfile(), ScreenSaverConfig(), ScreenSaverPreview(), session_set_option(), SpawnProcess(), start_server(), START_TEST(), StartApplication(), StartProcess(), TaskManager_OnFileNew(), test_AddPortEx(), test_alloc_shared(), test_apc_deadlock(), test_authentication(), test_BreakawayOk(), test_child_env(), Test_CommandLine(), test_CompletionPort(), test_createProcessingInstruction(), test_CreateProcessWithDesktop(), test_dead_process(), test_debug_children(), test_debug_loop(), test_debug_loop_wow64(), test_debugger(), test_EnumProcessModules(), test_exit_process_async(), test_ExitProcess(), test_fls_exit_deadlock(), test_get_xml(), test_GetProcessVersion(), test_internet_features(), test_ip_pktinfo(), test_IsProcessInJob(), test_IsWow64Process(), test_IsWow64Process2(), test_job_list_attribute(), test_jobInheritance(), test_kill_on_exit(), test_KillOnJobClose(), test_marshal_basetypes(), test_marshal_struct(), test_nested_jobs_child(), test_nodeTypedValue(), test_NtQueryValueKey(), test_OpenPrinter_defaults(), test_pe_os_version(), test_process_access(), test_put_data(), test_query_process_debug_flags(), test_query_process_debug_object_handle(), test_query_process_debug_port(), test_QueryInformationJobObject(), test_section_access(), test_shared_memory(), test_shared_memory_ro(), test_TerminateJobObject(), test_TerminateProcess(), test_WaitForInputIdle(), test_WaitForJobObject(), testAuth(), TestStaticDestruct(), ToolsPageWndProc(), unz64local_getByte(), UserRegisterClass(), UserUnregisterClass(), wait_and_close_child_process(), xmldoc_encoding(), xsltProcessingInstruction(), and zip64local_getByte().

◆ ULONG

Definition at line 49 of file debugger.c.