ReactOS 0.4.15-dev-8102-g108db8f
debugger.c File Reference
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <winternl.h>
#include <winreg.h>
#include "wine/test.h"
Include dependency graph for debugger.c:

Go to the source code of this file.

Classes

struct  tag_reg_save_value
 
struct  crash_blackbox_t
 
struct  debugger_blackbox_t
 
struct  child_blackbox
 

Macros

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

Typedefs

typedef struct tag_reg_save_value reg_save_value
 

Functions

static BOOL (WINAPI *pCheckRemoteDebuggerPresent)(HANDLE
 
static void WINETEST_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)
 
static int load_blackbox (const char *logfile, void *blackbox, int size)
 
static void doCrash (int argc, char **argv)
 
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 test_debug_loop (int argc, char **argv)
 
static void doChildren (int argc, char **argv)
 
static void test_debug_children (char *name, DWORD flag, BOOL debug_child)
 
 START_TEST (debugger)
 

Variables

static int myARGC
 
static char ** myARGV
 
static PBOOL
 
static LONG child_failures
 

Macro Definition Documentation

◆ child_ok

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

Definition at line 33 of file debugger.c.

◆ STATUS_DEBUGGER_INACTIVE

#define STATUS_DEBUGGER_INACTIVE   ((NTSTATUS) 0xC0000354)

Definition at line 30 of file debugger.c.

Typedef Documentation

◆ reg_save_value

Function Documentation

◆ BOOL()

static BOOL ( WINAPI pCheckRemoteDebuggerPresent)
static

◆ crash_and_debug()

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

Definition at line 260 of file debugger.c.

261{
262 static BOOL skip_crash_and_debug = FALSE;
263 BOOL bRet;
264 DWORD ret;
265 HANDLE start_event, done_event;
266 char* cmd;
267 char dbglog[MAX_PATH];
268 char childlog[MAX_PATH];
272 crash_blackbox_t crash_blackbox;
273 debugger_blackbox_t dbg_blackbox;
274 DWORD wait_code;
275
276 if (skip_crash_and_debug)
277 {
278 win_skip("Skipping crash_and_debug\n");
279 return;
280 }
281
282 ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
284 {
285 skip_crash_and_debug = TRUE;
286 skip("No write access to change the debugger\n");
287 return;
288 }
289
290 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%d\n", ret);
291
292 get_file_name(dbglog);
293 get_events(dbglog, &start_event, &done_event);
294 cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+10+strlen(dbgtasks)+1+strlen(dbglog)+2+34+1);
295 sprintf(cmd, "%s debugger %s \"%s\" %%ld %%ld", argv0, dbgtasks, dbglog);
296 ret=RegSetValueExA(hkey, "debugger", 0, REG_SZ, (BYTE*)cmd, strlen(cmd)+1);
297 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/debugger: ret=%d\n", ret);
299
300 get_file_name(childlog);
301 cmd=HeapAlloc(GetProcessHeap(), 0, strlen(argv0)+16+strlen(dbglog)+2+1);
302 sprintf(cmd, "%s debugger crash \"%s\"", argv0, childlog);
303
304 memset(&startup, 0, sizeof(startup));
305 startup.cb = sizeof(startup);
307 startup.wShowWindow = SW_SHOWNORMAL;
309 ok(ret, "CreateProcess: err=%d\n", GetLastError());
311 CloseHandle(info.hThread);
312
313 /* The process exits... */
314 trace("waiting for child exit...\n");
315 wait_code = WaitForSingleObject(info.hProcess, 30000);
316#if defined(_WIN64) && defined(__MINGW32__)
317 /* Mingw x64 doesn't output proper unwind info */
318 skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
319 if (skip_crash_and_debug)
320 {
322 WaitForSingleObject(info.hProcess, 5000);
323 CloseHandle(info.hProcess);
324 DeleteFileA(dbglog);
325 DeleteFileA(childlog);
326 win_skip("Giving up on child process\n");
327 return;
328 }
329#endif
330 ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
331 bRet = GetExitCodeProcess(info.hProcess, &exit_code);
332 ok(bRet, "GetExitCodeProcess failed: err=%d\n", GetLastError());
333 if (strstr(dbgtasks, "code2"))
334 {
335 /* If, after attaching to the debuggee, the debugger exits without
336 * detaching, then the debuggee gets a special exit code.
337 */
339 broken(exit_code == STATUS_ACCESS_VIOLATION) || /* Intermittent Vista+ */
340 broken(exit_code == WAIT_ABANDONED), /* NT4, W2K */
341 "wrong exit code : %08x\n", exit_code);
342 }
343 else
345 broken(exit_code == WAIT_ABANDONED), /* NT4, W2K, W2K3 */
346 "wrong exit code : %08x\n", exit_code);
347 CloseHandle(info.hProcess);
348
349 /* ...before the debugger */
350 if (strstr(dbgtasks, "order"))
351 ok(SetEvent(start_event), "SetEvent(start_event) failed\n");
352
353 trace("waiting for the debugger...\n");
354 wait_code = WaitForSingleObject(done_event, 5000);
355#if defined(_WIN64) && defined(__MINGW32__)
356 /* Mingw x64 doesn't output proper unwind info */
357 skip_crash_and_debug = broken(wait_code == WAIT_TIMEOUT);
358 if (skip_crash_and_debug)
359 {
360 DeleteFileA(dbglog);
361 DeleteFileA(childlog);
362 win_skip("Giving up on debugger\n");
363 return;
364 }
365#endif
366 ok(wait_code == WAIT_OBJECT_0, "Timed out waiting for the debugger\n");
367
368 ok(load_blackbox(childlog, &crash_blackbox, sizeof(crash_blackbox)), "failed to open: %s\n", childlog);
369 ok(load_blackbox(dbglog, &dbg_blackbox, sizeof(dbg_blackbox)), "failed to open: %s\n", dbglog);
370
371 ok(dbg_blackbox.argc == 6, "wrong debugger argument count: %d\n", dbg_blackbox.argc);
372 ok(dbg_blackbox.pid == crash_blackbox.pid, "the child and debugged pids don't match: %d != %d\n", crash_blackbox.pid, dbg_blackbox.pid);
373 ok(dbg_blackbox.debug_rc, "debugger: SetEvent(debug_event) failed err=%d\n", dbg_blackbox.debug_err);
374 ok(dbg_blackbox.attach_rc, "DebugActiveProcess(%d) failed err=%d\n", dbg_blackbox.pid, dbg_blackbox.attach_err);
375 ok(dbg_blackbox.nokill_rc, "DebugSetProcessKillOnExit(FALSE) failed err=%d\n", dbg_blackbox.nokill_err);
376 ok(dbg_blackbox.detach_rc, "DebugActiveProcessStop(%d) failed err=%d\n", dbg_blackbox.pid, dbg_blackbox.detach_err);
377
378 DeleteFileA(dbglog);
379 DeleteFileA(childlog);
380}
#define broken(x)
Definition: _sntprintf.h:21
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static void startup(void)
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#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 CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#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:4741
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define REG_SZ
Definition: layer.c:22
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:30
static void get_events(const char *name, HANDLE *start_event, HANDLE *done_event)
Definition: debugger.c:99
static int load_blackbox(const char *logfile, void *blackbox, int size)
Definition: debugger.c:127
static UINT exit_code
Definition: process.c:78
static HANDLE start_event
Definition: thread.c:135
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define get_file_name
Definition: regproc.h:51
#define win_skip
Definition: test.h:163
#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
int ret
#define WAIT_ABANDONED
Definition: winbase.h:412
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:491
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define SW_SHOWNORMAL
Definition: winuser.h:770
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 382 of file debugger.c.

383{
384 BOOL bRet;
385 DWORD ret;
386 char* cmd;
390
391 ret=RegSetValueExA(hkey, "auto", 0, REG_SZ, (BYTE*)"1", 2);
392 ok(ret == ERROR_SUCCESS, "unable to set AeDebug/auto: ret=%d\n", ret);
393
395 sprintf(cmd, "%s debugger crash", argv0);
396
397 memset(&startup, 0, sizeof(startup));
398 startup.cb = sizeof(startup);
400 startup.wShowWindow = SW_SHOWNORMAL;
402 ok(ret, "CreateProcess: err=%d\n", GetLastError());
404 CloseHandle(info.hThread);
405
406 trace("waiting for child exit...\n");
407 ok(WaitForSingleObject(info.hProcess, 60000) == WAIT_OBJECT_0, "Timed out waiting for the child to crash\n");
408 bRet = GetExitCodeProcess(info.hProcess, &exit_code);
409 ok(bRet, "GetExitCodeProcess failed: err=%d\n", GetLastError());
410 ok(exit_code == STATUS_ACCESS_VIOLATION, "exit code = %08x\n", exit_code);
411 CloseHandle(info.hProcess);
412}

Referenced by test_ExitCode().

◆ doChild()

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

Definition at line 539 of file debugger.c.

540{
541 struct child_blackbox blackbox;
542 const char *blackbox_file;
544 DWORD ppid;
545 BOOL debug;
546 BOOL ret;
547
548 blackbox_file = argv[4];
549 sscanf(argv[3], "%08x", &ppid);
550
552 child_ok(!!parent, "OpenProcess failed, last error %#x.\n", GetLastError());
553
554 ret = pCheckRemoteDebuggerPresent(parent, &debug);
555 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
556 child_ok(!debug, "Expected debug == 0, got %#x.\n", debug);
557
558 ret = DebugActiveProcess(ppid);
559 child_ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
560
561 ret = pCheckRemoteDebuggerPresent(parent, &debug);
562 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
563 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
564
565 ret = pDebugActiveProcessStop(ppid);
566 child_ok(ret, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError());
567
568 ret = pCheckRemoteDebuggerPresent(parent, &debug);
569 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
570 child_ok(!debug, "Expected debug == 0, got %#x.\n", debug);
571
573 child_ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
574
575 ret = pIsDebuggerPresent();
576 child_ok(ret, "Expected ret != 0, got %#x.\n", ret);
577 ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug);
578 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
579 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
580
581 NtCurrentTeb()->Peb->BeingDebugged = FALSE;
582
583 ret = pIsDebuggerPresent();
584 child_ok(!ret, "Expected ret != 0, got %#x.\n", ret);
585 ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug);
586 child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
587 child_ok(debug, "Expected debug != 0, got %#x.\n", debug);
588
589 NtCurrentTeb()->Peb->BeingDebugged = TRUE;
590
591 blackbox.failures = child_failures;
592 save_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
593}
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI DebugActiveProcess(IN DWORD dwProcessId)
Definition: debugger.c:445
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
r parent
Definition: btrfs.c:3010
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
#define NtCurrentTeb
#define debug(msg)
Definition: key_call.c:71
static LONG child_failures
Definition: debugger.c:43
#define child_ok
Definition: debugger.c:33
static void save_blackbox(const char *logfile, void *blackbox, int size)
Definition: debugger.c:115
#define argv
Definition: mplay32.c:18

Referenced by START_TEST().

◆ doChildren()

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

Definition at line 659 of file debugger.c.

660{
661 const char *arguments = "debugger children last";
662 struct child_blackbox blackbox;
663 const char *blackbox_file, *p;
664 char event_name[MAX_PATH];
666 STARTUPINFOA si;
668 char *cmd;
669 BOOL ret;
670
671 if (!strcmp(argv[3], "last")) return;
672
673 blackbox_file = argv[3];
674
675 p = strrchr(blackbox_file, '\\');
676 p = p ? p+1 : blackbox_file;
677 strcpy(event_name, p);
678 strcat(event_name, "_init");
679 event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
680 child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
683
684 p = strrchr(blackbox_file, '\\');
685 p = p ? p+1 : blackbox_file;
686 strcpy(event_name, p);
687 strcat(event_name, "_attach");
688 event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
689 child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
692
693 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + 2);
694 sprintf(cmd, "%s %s", argv[0], arguments);
695
696 memset(&si, 0, sizeof(si));
697 si.cb = sizeof(si);
698 ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
699 child_ok(ret, "CreateProcess failed, last error %d.\n", GetLastError());
700
701 child_ok(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0,
702 "Timed out waiting for the child to exit\n");
703
704 ret = CloseHandle(pi.hThread);
705 child_ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
706 ret = CloseHandle(pi.hProcess);
707 child_ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
708
709 blackbox.failures = child_failures;
710 save_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
711
713}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define INFINITE
Definition: serial.h:102
struct _cl_event * event
Definition: glext.h:7739
GLfloat GLfloat p
Definition: glext.h:8902
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
static refpint_t pi[]
Definition: server.c:96
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
DWORD cb
Definition: winbase.h:831
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 ( int  argc,
char **  argv 
)
static

Definition at line 152 of file debugger.c.

153{
154 volatile char* p;
155
156 /* make sure the exception gets to the debugger */
157 SetErrorMode( 0 );
159
160 if (argc >= 4)
161 {
162 crash_blackbox_t blackbox;
163 blackbox.pid=GetCurrentProcessId();
164 save_blackbox(argv[3], &blackbox, sizeof(blackbox));
165 }
166
167 /* Just crash */
168 trace("child: crashing...\n");
169 p=NULL;
170 *p=0;
171}
static int argc
Definition: ServiceArgs.c:12
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
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158

Referenced by START_TEST().

◆ doDebugger()

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

Definition at line 187 of file debugger.c.

188{
189 const char* logfile;
190 debugger_blackbox_t blackbox;
191 HANDLE start_event = 0, done_event = 0, debug_event;
192
193 blackbox.argc=argc;
194 logfile=(argc >= 4 ? argv[3] : NULL);
195 blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0);
196
197 blackbox.attach_err=0;
198 if (strstr(myARGV[2], "attach"))
199 {
200 blackbox.attach_rc=DebugActiveProcess(blackbox.pid);
201 if (!blackbox.attach_rc)
202 blackbox.attach_err=GetLastError();
203 }
204 else
205 blackbox.attach_rc=TRUE;
206
207 debug_event=(argc >= 6 ? (HANDLE)(INT_PTR)atol(argv[5]) : NULL);
208 blackbox.debug_err=0;
209 if (debug_event && strstr(myARGV[2], "event"))
210 {
211 blackbox.debug_rc=SetEvent(debug_event);
212 if (!blackbox.debug_rc)
213 blackbox.debug_err=GetLastError();
214 }
215 else
216 blackbox.debug_rc=TRUE;
217
218 if (logfile)
219 {
220 get_events(logfile, &start_event, &done_event);
221 }
222
223 if (strstr(myARGV[2], "order"))
224 {
225 trace("debugger: waiting for the start signal...\n");
227 }
228
229 blackbox.nokill_err=0;
230 if (strstr(myARGV[2], "nokill"))
231 {
232 blackbox.nokill_rc=pDebugSetProcessKillOnExit(FALSE);
233 if (!blackbox.nokill_rc)
234 blackbox.nokill_err=GetLastError();
235 }
236 else
237 blackbox.nokill_rc=TRUE;
238
239 blackbox.detach_err=0;
240 if (strstr(myARGV[2], "detach"))
241 {
242 blackbox.detach_rc=pDebugActiveProcessStop(blackbox.pid);
243 if (!blackbox.detach_rc)
244 blackbox.detach_err=GetLastError();
245 }
246 else
247 blackbox.detach_rc=TRUE;
248
249 if (logfile)
250 {
251 save_blackbox(logfile, &blackbox, sizeof(blackbox));
252 }
253 trace("debugger: done debugging...\n");
254 SetEvent(done_event);
255
256 /* Just exit with a known value */
257 ExitProcess(0xdeadbeef);
258}
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
static char ** myARGV
Definition: debugger.c:36
int32_t INT_PTR
Definition: typedefs.h:64
PVOID HANDLE
Definition: typedefs.h:73

Referenced by START_TEST().

◆ get_events()

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

Definition at line 99 of file debugger.c.

100{
101 const char* basename;
102 char* event_name;
103
104 basename=strrchr(name, '\\');
106 event_name=HeapAlloc(GetProcessHeap(), 0, 6+strlen(basename)+1);
107
108 sprintf(event_name, "start_%s", basename);
109 *start_event=CreateEventA(NULL, 0,0, event_name);
110 sprintf(event_name, "done_%s", basename);
111 *done_event=CreateEventA(NULL, 0,0, event_name);
112 HeapFree(GetProcessHeap(), 0, event_name);
113}
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 56 of file debugger.c.

57{
58 char path[MAX_PATH];
59
60 buf[0] = '\0';
61 GetTempPathA(sizeof(path), path);
62 GetTempFileNameA(path, "wt", 0, buf);
63}
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
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751

◆ load_blackbox()

static int load_blackbox ( const char logfile,
void blackbox,
int  size 
)
static

Definition at line 127 of file debugger.c.

128{
130 DWORD read;
131 BOOL ret;
132
133 hFile=CreateFileA(logfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
135 {
136 ok(0, "unable to open '%s'\n", logfile);
137 return 0;
138 }
139 SetLastError(0xdeadbeef);
140 ret=ReadFile(hFile, blackbox, size, &read, NULL);
141 ok(ret, "ReadFile failed: %d\n", GetLastError());
142 ok(read == size, "wrong size for '%s': read=%d\n", logfile, read);
144 return 1;
145}
#define read
Definition: acwin.h:96
#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
GLsizeiptr size
Definition: glext.h:5919
_In_ HANDLE hFile
Definition: mswsock.h:90

Referenced by crash_and_debug(), test_debug_children(), and test_debug_loop().

◆ restore_value()

static void restore_value ( HKEY  hkey,
reg_save_value saved 
)
static

Definition at line 88 of file debugger.c.

89{
90 if (saved->data)
91 {
92 RegSetValueExA(hkey, saved->name, 0, saved->type, saved->data, saved->size);
93 HeapFree(GetProcessHeap(), 0, saved->data);
94 }
95 else
96 RegDeleteValueA(hkey, saved->name);
97}
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
const char * name
Definition: debugger.c:67

Referenced by test_ExitCode().

◆ save_blackbox()

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

Definition at line 115 of file debugger.c.

116{
118 DWORD written;
119
120 hFile=CreateFileA(logfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
122 return;
123 WriteFile(hFile, blackbox, size, &written, NULL);
125}
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(), doCrash(), and doDebugger().

◆ save_value()

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

Definition at line 73 of file debugger.c.

74{
75 DWORD ret;
76 saved->name=value;
77 saved->data=0;
78 saved->size=0;
79 ret=RegQueryValueExA(hkey, value, NULL, &saved->type, NULL, &saved->size);
80 if (ret == ERROR_SUCCESS)
81 {
82 saved->data=HeapAlloc(GetProcessHeap(), 0, saved->size);
83 RegQueryValueExA(hkey, value, NULL, &saved->type, saved->data, &saved->size);
84 }
85 return ret;
86}
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:94

Referenced by test_ExitCode().

◆ START_TEST()

START_TEST ( debugger  )

Definition at line 805 of file debugger.c.

806{
808
809 hdll=GetModuleHandleA("kernel32.dll");
810 pCheckRemoteDebuggerPresent=(void*)GetProcAddress(hdll, "CheckRemoteDebuggerPresent");
811 pDebugActiveProcessStop=(void*)GetProcAddress(hdll, "DebugActiveProcessStop");
812 pDebugSetProcessKillOnExit=(void*)GetProcAddress(hdll, "DebugSetProcessKillOnExit");
813 pIsDebuggerPresent=(void*)GetProcAddress(hdll, "IsDebuggerPresent");
814
816 if (myARGC >= 3 && strcmp(myARGV[2], "crash") == 0)
817 {
819 }
820 else if (myARGC >= 3 && strncmp(myARGV[2], "dbg,", 4) == 0)
821 {
823 }
824 else if (myARGC >= 5 && !strcmp(myARGV[2], "child"))
825 {
827 }
828 else if (myARGC >= 4 && !strcmp(myARGV[2], "children"))
829 {
831 }
832 else
833 {
841 }
842}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
static void test_ExitCode(void)
Definition: debugger.c:414
static void test_debug_loop(int argc, char **argv)
Definition: debugger.c:595
static int myARGC
Definition: debugger.c:35
static void doChildren(int argc, char **argv)
Definition: debugger.c:659
static void doDebugger(int argc, char **argv)
Definition: debugger.c:187
static void doCrash(int argc, char **argv)
Definition: debugger.c:152
static void doChild(int argc, char **argv)
Definition: debugger.c:539
static void test_debug_children(char *name, DWORD flag, BOOL debug_child)
Definition: debugger.c:715
static void test_RemoteDebugger(void)
Definition: debugger.c:504
int winetest_get_mainargs(char ***pargv)
static PVOID hdll
Definition: shimdbg.c:126
#define DEBUG_ONLY_THIS_PROCESS
Definition: winbase.h:177
#define DEBUG_PROCESS
Definition: winbase.h:176

◆ test_debug_children()

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

Definition at line 715 of file debugger.c.

716{
717 const char *arguments = "debugger children";
718 struct child_blackbox blackbox;
719 char blackbox_file[MAX_PATH], *p;
720 char event_name[MAX_PATH];
722 STARTUPINFOA si;
723 HANDLE event_init, event_attach;
724 char *cmd;
725 BOOL debug, ret;
726 BOOL got_child_event = FALSE;
727
728 if (!pDebugActiveProcessStop || !pCheckRemoteDebuggerPresent)
729 {
730 win_skip("DebugActiveProcessStop or CheckRemoteDebuggerPresent not available, skipping test.\n");
731 return;
732 }
733
734 get_file_name(blackbox_file);
735 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(name) + strlen(arguments) + strlen(blackbox_file) + 5);
736 sprintf(cmd, "%s %s \"%s\"", name, arguments, blackbox_file);
737
738 p = strrchr(blackbox_file, '\\');
739 p = p ? p+1 : blackbox_file;
740 strcpy(event_name, p);
741 strcat(event_name, "_init");
742 event_init = CreateEventA(NULL, FALSE, FALSE, event_name);
743 ok(event_init != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
744
745 p = strrchr(blackbox_file, '\\');
746 p = p ? p+1 : blackbox_file;
747 strcpy(event_name, p);
748 strcat(event_name, "_attach");
749 event_attach = CreateEventA(NULL, FALSE, flag!=0, event_name);
750 ok(event_attach != NULL, "CreateEvent failed, last error %d.\n", GetLastError());
751
752 memset(&si, 0, sizeof(si));
753 si.cb = sizeof(si);
754
756 ok(ret, "CreateProcess failed, last error %d.\n", GetLastError());
758 if (!flag)
759 {
760 WaitForSingleObject(event_init, INFINITE);
761 ret = DebugActiveProcess(pi.dwProcessId);
762 ok(ret, "DebugActiveProcess failed, last error %d.\n", GetLastError());
763 ret = SetEvent(event_attach);
764 ok(ret, "SetEvent failed, last error %d.\n", GetLastError());
765 }
766
767 ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
768 ok(ret, "CheckRemoteDebuggerPresent failed, last error %d.\n", GetLastError());
769 ok(debug, "Expected debug != 0, got %x.\n", debug);
770
771 for (;;)
772 {
773 DEBUG_EVENT ev;
774
776 ok(ret, "WaitForDebugEvent failed, last error %d.\n", GetLastError());
777 if (!ret) break;
778
779 if (ev.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT && ev.dwProcessId==pi.dwProcessId) break;
780 else if (ev.dwProcessId != pi.dwProcessId) got_child_event = TRUE;
781
783 ok(ret, "ContinueDebugEvent failed, last error %d.\n", GetLastError());
784 if (!ret) break;
785 }
786 if(debug_child)
787 ok(got_child_event, "didn't get any child events (flag: %x).\n", flag);
788 else
789 ok(!got_child_event, "got child event (flag: %x).\n", flag);
790 CloseHandle(event_init);
791 CloseHandle(event_attach);
792
793 ret = CloseHandle(pi.hThread);
794 ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
795 ret = CloseHandle(pi.hProcess);
796 ok(ret, "CloseHandle failed, last error %d.\n", GetLastError());
797
798 load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
799 ok(!blackbox.failures, "Got %d failures from child process.\n", blackbox.failures);
800
801 ret = DeleteFileA(blackbox_file);
802 ok(ret, "DeleteFileA failed, last error %d.\n", GetLastError());
803}
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
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 DBG_CONTINUE
Definition: ntstatus.h:47
DWORD dwDebugEventCode
Definition: winbase.h:788
DWORD dwThreadId
Definition: winbase.h:790
DWORD dwProcessId
Definition: winbase.h:789
#define EXIT_PROCESS_DEBUG_EVENT
Definition: winbase.h:106

Referenced by START_TEST().

◆ test_debug_loop()

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

Definition at line 595 of file debugger.c.

596{
597 const char *arguments = " debugger child ";
598 struct child_blackbox blackbox;
599 char blackbox_file[MAX_PATH];
601 STARTUPINFOA si;
602 BOOL debug;
603 DWORD pid;
604 char *cmd;
605 BOOL ret;
606
607 if (!pDebugActiveProcessStop || !pCheckRemoteDebuggerPresent)
608 {
609 win_skip("DebugActiveProcessStop or CheckRemoteDebuggerPresent not available, skipping test.\n");
610 return;
611 }
612
615 ok(!ret, "DebugActiveProcess() succeeded on own process.\n");
616
617 get_file_name(blackbox_file);
618 cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 2 + 10);
619 sprintf(cmd, "%s%s%08x \"%s\"", argv[0], arguments, pid, blackbox_file);
620
621 memset(&si, 0, sizeof(si));
622 si.cb = sizeof(si);
624 ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
625
627
628 ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug);
629 ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError());
630 ok(debug, "Expected debug != 0, got %#x.\n", debug);
631
632 for (;;)
633 {
634 DEBUG_EVENT ev;
635
637 ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
638 if (!ret) break;
639
641
643 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
644 if (!ret) break;
645 }
646
647 ret = CloseHandle(pi.hThread);
648 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
649 ret = CloseHandle(pi.hProcess);
650 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
651
652 load_blackbox(blackbox_file, &blackbox, sizeof(blackbox));
653 ok(!blackbox.failures, "Got %d failures from child process.\n", blackbox.failures);
654
655 ret = DeleteFileA(blackbox_file);
656 ok(ret, "DeleteFileA failed, last error %#x.\n", GetLastError());
657}
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837

Referenced by START_TEST().

◆ test_ExitCode()

static void test_ExitCode ( void  )
static

Definition at line 414 of file debugger.c.

415{
416 static const char* AeDebug="Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
417 static const char* WineDbg="Software\\Wine\\WineDbg";
418 char test_exe[MAX_PATH];
419 DWORD ret;
420 HKEY hkey;
421 DWORD disposition;
422 reg_save_value auto_value;
423 reg_save_value debugger_value;
424
425 GetModuleFileNameA(GetModuleHandleA(NULL), test_exe, sizeof(test_exe));
427 strcat(test_exe, ".so");
429 {
430 ok(0, "could not find the test executable '%s'\n", test_exe);
431 return;
432 }
433
435 if (ret == ERROR_SUCCESS)
436 {
437 save_value(hkey, "auto", &auto_value);
438 save_value(hkey, "debugger", &debugger_value);
439 trace("HKLM\\%s\\debugger is set to '%s'\n", AeDebug, debugger_value.data);
440 }
441 else if (ret == ERROR_ACCESS_DENIED)
442 {
443 skip("not enough privileges to change the debugger\n");
444 return;
445 }
446 else if (ret != ERROR_FILE_NOT_FOUND)
447 {
448 ok(0, "could not open the AeDebug key: %d\n", ret);
449 return;
450 }
451 else debugger_value.data = NULL;
452
453 if (debugger_value.data && debugger_value.type == REG_SZ &&
454 strstr((char*)debugger_value.data, "winedbg --auto"))
455 {
456 HKEY hkeyWinedbg;
457 ret=RegCreateKeyA(HKEY_CURRENT_USER, WineDbg, &hkeyWinedbg);
458 if (ret == ERROR_SUCCESS)
459 {
460 static DWORD zero;
461 reg_save_value crash_dlg_value;
462 save_value(hkeyWinedbg, "ShowCrashDialog", &crash_dlg_value);
463 RegSetValueExA(hkeyWinedbg, "ShowCrashDialog", 0, REG_DWORD, (BYTE *)&zero, sizeof(DWORD));
464 crash_and_winedbg(hkey, test_exe);
465 restore_value(hkeyWinedbg, &crash_dlg_value);
466 RegCloseKey(hkeyWinedbg);
467 }
468 else
469 ok(0, "Couldn't access WineDbg Key - error %u\n", ret);
470 }
471
473 /* Since the debugging process never sets the debug event, it isn't recognized
474 as a valid debugger and, after the debugger exits, Windows will show a dialog box
475 asking the user what to do */
476 crash_and_debug(hkey, test_exe, "dbg,none");
477 else
478 skip("\"none\" debugger test needs user interaction\n");
479 ok(disposition == REG_OPENED_EXISTING_KEY, "expected REG_OPENED_EXISTING_KEY, got %d\n", disposition);
480 crash_and_debug(hkey, test_exe, "dbg,event,order");
481 crash_and_debug(hkey, test_exe, "dbg,attach,event,code2");
482 if (pDebugSetProcessKillOnExit)
483 crash_and_debug(hkey, test_exe, "dbg,attach,event,nokill");
484 else
485 win_skip("DebugSetProcessKillOnExit is not available\n");
486 if (pDebugActiveProcessStop)
487 crash_and_debug(hkey, test_exe, "dbg,attach,event,detach");
488 else
489 win_skip("DebugActiveProcessStop is not available\n");
490
491 if (disposition == REG_CREATED_NEW_KEY)
492 {
493 RegCloseKey(hkey);
495 }
496 else
497 {
498 restore_value(hkey, &auto_value);
499 restore_value(hkey, &debugger_value);
500 RegCloseKey(hkey);
501 }
502}
#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
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static void crash_and_winedbg(HKEY hkey, const char *argv0)
Definition: debugger.c:382
static void crash_and_debug(HKEY hkey, const char *argv0, const char *dbgtasks)
Definition: debugger.c:260
static DWORD save_value(HKEY hkey, const char *value, reg_save_value *saved)
Definition: debugger.c:73
static void restore_value(HKEY hkey, reg_save_value *saved)
Definition: debugger.c:88
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
#define REG_DWORD
Definition: sdbapi.c:596
int winetest_interactive
int zero
Definition: sehframes.cpp:29
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11

Referenced by START_TEST().

◆ test_RemoteDebugger()

static void test_RemoteDebugger ( void  )
static

Definition at line 504 of file debugger.c.

505{
506 BOOL bret, present;
507 if(!pCheckRemoteDebuggerPresent)
508 {
509 win_skip("CheckRemoteDebuggerPresent is not available\n");
510 return;
511 }
512 present = TRUE;
513 SetLastError(0xdeadbeef);
514 bret = pCheckRemoteDebuggerPresent(GetCurrentProcess(),&present);
515 ok(bret , "expected CheckRemoteDebuggerPresent to succeed\n");
516 ok(0xdeadbeef == GetLastError(),
517 "expected error to be unchanged, got %d/%x\n",GetLastError(), GetLastError());
518
519 present = TRUE;
520 SetLastError(0xdeadbeef);
521 bret = pCheckRemoteDebuggerPresent(NULL,&present);
522 ok(!bret , "expected CheckRemoteDebuggerPresent to fail\n");
523 ok(present, "expected parameter to be unchanged\n");
525 "expected error ERROR_INVALID_PARAMETER, got %d/%x\n",GetLastError(), GetLastError());
526
527 SetLastError(0xdeadbeef);
528 bret = pCheckRemoteDebuggerPresent(GetCurrentProcess(),NULL);
529 ok(!bret , "expected CheckRemoteDebuggerPresent to fail\n");
531 "expected error ERROR_INVALID_PARAMETER, got %d/%x\n",GetLastError(), GetLastError());
532}
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101

Referenced by START_TEST().

◆ WINETEST_PRINTF_ATTR()

static void WINETEST_PRINTF_ATTR ( ,
 
)
static

Definition at line 45 of file debugger.c.

46{
48
53}
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define msg(x)
Definition: auth_time.c:54
GLenum condition
Definition: glext.h:9255
static __ms_va_list valist
Definition: printf.c:66
int winetest_vok(int condition, const char *msg, __winetest_va_list ap)

Variable Documentation

◆ child_failures

LONG child_failures
static

Definition at line 43 of file debugger.c.

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

◆ myARGC

int myARGC
static

Definition at line 35 of file debugger.c.

Referenced by START_TEST().

◆ myARGV

char** myARGV
static

Definition at line 36 of file debugger.c.

Referenced by doDebugger(), and START_TEST().

◆ PBOOL

Definition at line 38 of file debugger.c.