ReactOS 0.4.16-dev-2206-gc56950d
debugger.c
Go to the documentation of this file.
1/*
2 * Unit tests for the debugger facility
3 *
4 * Copyright (c) 2007 Francois Gouget for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdio.h>
22#include <assert.h>
23
24#include <ntstatus.h>
25#define WIN32_NO_STATUS
26#include <windows.h>
27#include <winternl.h>
28#include <winreg.h>
29#include "wine/test.h"
30#include "wine/heap.h"
31#include "wine/rbtree.h"
32
33#ifndef STATUS_DEBUGGER_INACTIVE
34#define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354)
35#endif
36
37#define child_ok (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : test_child_ok
38
39static int myARGC;
40static char** myARGV;
42
43static BOOL (WINAPI *pCheckRemoteDebuggerPresent)(HANDLE,PBOOL);
44
45static void (WINAPI *pDbgBreakPoint)(void);
46
47static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE process);
48static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE process);
49static NTSTATUS (WINAPI *pNtCreateDebugObject)(HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG);
50static NTSTATUS (WINAPI *pNtSetInformationDebugObject)(HANDLE,DEBUGOBJECTINFOCLASS,void *,ULONG,ULONG*);
51static NTSTATUS (WINAPI *pDbgUiConnectToDbg)(void);
52static HANDLE (WINAPI *pDbgUiGetThreadDebugObject)(void);
53static void (WINAPI *pDbgUiSetThreadDebugObject)(HANDLE);
54static DWORD (WINAPI *pGetMappedFileNameW)(HANDLE,void*,WCHAR*,DWORD);
55static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
56
58
60
61static void WINAPIV __WINE_PRINTF_ATTR(2, 3) test_child_ok(int condition, const char *msg, ...)
62{
64
69}
70
71/* Copied from the process test */
72static void get_file_name(char* buf)
73{
74 char path[MAX_PATH];
75
76 buf[0] = '\0';
77 GetTempPathA(sizeof(path), path);
78 GetTempFileNameA(path, "wt", 0, buf);
79}
80
81typedef struct tag_reg_save_value
82{
83 const char *name;
88
89static DWORD save_value(HKEY hkey, const char *value, reg_save_value *saved)
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}
103
104static void restore_value(HKEY hkey, reg_save_value *saved)
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}
114
115static void get_events(const char* name, HANDLE *start_event, HANDLE *done_event)
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}
130
131static void save_blackbox(const char* logfile, void* blackbox, int size, const char *dbgtrace)
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}
150
151#define load_blackbox(a, b, c) _load_blackbox(__LINE__, (a), (b), (c))
152static int _load_blackbox(unsigned int line, const char* logfile, void* blackbox, int size)
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}
182
184{
185 Sleep(10000);
186 trace("exiting\n");
187 ExitThread(1);
188}
189
190static void run_background_thread(void)
191{
192 DWORD tid;
194 ok(thread != NULL, "CreateThread failed\n");
196}
197
198static void doCrash(void)
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}
213
214typedef struct
215{
216 int argc;
228
230{
233 unsigned process_cnt;
234 unsigned dll_cnt;
237 unsigned thread_cnt;
241};
242
244{
250};
251
252int debuggee_thread_compare(const void *key, const struct wine_rb_entry *entry)
253{
255 return memcmp(key, &thread->tid, sizeof(thread->tid));
256}
257
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}
269
271{
272 struct wine_rb_entry *entry = wine_rb_get(&ctx->threads, &tid);
273 ok(entry != NULL, "unknown thread %lx\n", tid);
275}
276
278{
280
281 wine_rb_remove(&ctx->threads, &thread->entry);
282 if (thread->handle) CloseHandle(thread->handle);
284}
285
286static void *get_ip(const CONTEXT *ctx)
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}
296
297static void set_ip(CONTEXT *ctx, void *ip)
298{
299#ifdef __i386__
300 ctx->Eip = (DWORD_PTR)ip;
301#elif defined(__x86_64__)
302 ctx->Rip = (DWORD_PTR)ip;
303#endif
304}
305
306#define fetch_thread_context(a) fetch_thread_context_(__LINE__,a)
307static void fetch_thread_context_(unsigned line, struct debuggee_thread *thread)
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}
323
324#define set_thread_context(a,b) set_thread_context_(__LINE__,a,b)
325static void set_thread_context_(unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread)
326{
327 BOOL ret;
328 ret = SetThreadContext(thread->handle, &thread->ctx);
329 ok_(__FILE__,line)(ret, "SetThreadContext failed: %lu\n", GetLastError());
330}
331
332#define WAIT_EVENT_TIMEOUT 20000
333#define POLL_EVENT_TIMEOUT 200
334
335#define next_event(a,b) next_event_(__LINE__,a,b)
336static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout)
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}
397
399{
400 return (ev >= 1 && ev <= 7) ? (1LU << ev) : 0;
401}
402
403#define next_event_filter(a, b,c) next_event_filter_(__LINE__, (a), (b), (c))
405{
406 do
407 {
409 } while (event_mask(ctx->ev.dwDebugEventCode) & mask);
410}
411
412#define wait_for_breakpoint(a) wait_for_breakpoint_(__LINE__,a)
413static void wait_for_breakpoint_(unsigned line, struct debugger_context *ctx)
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}
422
423#define check_thread_running(h) ok(_check_thread_suspend_count(h) == 0, "Expecting running thread\n")
424#define check_thread_suspended(h) ok(_check_thread_suspend_count(h) > 0, "Expecting suspended thread\n")
425
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}
435
436static void process_attach_events(struct debugger_context *ctx, BOOL pass_exception)
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}
520
521static void doDebugger(int argc, char** argv)
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}
620
621static void crash_and_debug(HKEY hkey, const char* argv0, const char* dbgtasks)
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}
737
738static void crash_and_winedbg(HKEY hkey, const char* argv0)
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}
769
770static void test_ExitCode(void)
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}
861
862static void test_RemoteDebugger(void)
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}
891
893{
895};
896
897static void doChild(int argc, char **argv)
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}
998
1000
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}
1024
1025static void test_debug_loop(int argc, char **argv)
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}
1125
1127{
1129 unsigned count;
1131};
1132
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}
1147
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}
1158
1159static void test_debug_loop_wow64(void)
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}
1298
1299static void doChildren(int argc, char **argv)
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}
1356
1357static void test_debug_children(const char *name, DWORD flag, BOOL debug_child, BOOL pass_exception)
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}
1525
1526static void wait_debugger(HANDLE event, unsigned int cnt)
1527{
1529 ExitProcess(0);
1530}
1531
1532#define expect_event(a,b) expect_event_(__LINE__,a,b)
1533static void expect_event_(unsigned line, struct debugger_context *ctx, DWORD event_code)
1534{
1536 ok_(__FILE__,line)(ctx->ev.dwDebugEventCode == event_code, "dwDebugEventCode = %ld expected %ld\n",
1537 ctx->ev.dwDebugEventCode, event_code);
1538}
1539
1540#define expect_exception(a,b) expect_exception_(__LINE__,a,b)
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}
1547
1548#define check_breakpoint_exception(a,b) expect_breakpoint_exception_(__LINE__,a,b)
1549static void check_breakpoint_exception_(unsigned line, struct debugger_context *ctx, const void *expect_addr)
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}
1560
1561#define expect_breakpoint_exception(a,b) expect_breakpoint_exception_(__LINE__,a,b)
1562static void expect_breakpoint_exception_(unsigned line, struct debugger_context *ctx, const void *expect_addr)
1563{
1565 check_breakpoint_exception_(line, ctx, expect_addr);
1566}
1567
1568#define single_step(a,b,c) single_step_(__LINE__,a,b,c)
1569static void single_step_(unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread, void *expect_addr)
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}
1584
1585static const BYTE loop_code[] = {
1586#if defined(__i386__) || defined(__x86_64__)
1587 0x90, /* nop */
1588 0x90, /* nop */
1589 0x90, /* nop */
1590 0xe9, 0xf8, 0xff, 0xff, 0xff /* jmp $-8 */
1591#endif
1592};
1593
1595#ifdef __i386__
1596 0x53, /* pushl %ebx */
1597 0x57, /* pushl %edi */
1598 0x8b, 0x44, 0x24, 0x0c, /* movl 12(%esp),%eax */
1599 0xb9, 0x11, 0x11, 0x11, 0x11, /* movl $0x11111111,%ecx */
1600 0xba, 0x22, 0x22, 0x22, 0x22, /* movl $0x22222222,%edx */
1601 0xbb, 0x33, 0x33, 0x33, 0x33, /* movl $0x33333333,%ebx */
1602 0xbf, 0x44, 0x44, 0x44, 0x44, /* movl $0x44444444,%edi */
1603 0xcd, 0x2d, /* int $0x2d */
1604 0xeb, /* jmp $+17 */
1605 0x0f, 0x1f, 0x00, /* nop */
1606 0x31, 0xc0, /* xorl %eax,%eax */
1607 0xeb, 0x0c, /* jmp $+14 */
1608 0x90, 0x90, 0x90, 0x90, /* nop */
1609 0x90, 0x90, 0x90, 0x90,
1610 0x90,
1611 0x31, 0xc0, /* xorl %eax,%eax */
1612 0x40, /* incl %eax */
1613 0x5f, /* popl %edi */
1614 0x5b, /* popl %ebx */
1615 0xc3, /* ret */
1616#elif defined(__x86_64__)
1617 0x53, /* push %rbx */
1618 0x57, /* push %rdi */
1619 0x48, 0x89, 0xc8, /* movl %rcx,%rax */
1620 0x48, 0xb9, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, /* movabs $0x1111111111111111,%rcx */
1621 0x48, 0xba, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* movabs $0x2222222222222222,%rdx */
1622 0x48, 0xbb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, /* movabs $0x3333333333333333,%rbx */
1623 0x48, 0xbf, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, /* movabs $0x4444444444444444,%rdi */
1624 0xcd, 0x2d, /* int $0x2d */
1625 0xeb, /* jmp $+17 */
1626 0x0f, 0x1f, 0x00, /* nop */
1627 0x48, 0x31, 0xc0, /* xor %rax,%rax */
1628 0xeb, 0x0e, /* jmp $+16 */
1629 0x90, 0x90, 0x90, 0x90, /* nop */
1630 0x90, 0x90, 0x90, 0x90,
1631 0x48, 0x31, 0xc0, /* xor %rax,%rax */
1632 0x48, 0xff, 0xc0, /* inc %rax */
1633 0x5f, /* pop %rdi */
1634 0x5b, /* pop %rbx */
1635 0xc3, /* ret */
1636#endif
1637};
1638
1639#if defined(__i386__) || defined(__x86_64__)
1640#define OP_BP 0xcc
1641#else
1642#define OP_BP 0
1643#endif
1644
1645static void test_debugger(const char *argv0)
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}
2281
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}
2302
2304static char *cmd;
2305
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}
2324
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}
2343
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}
2354
2355static void test_kill_on_exit(const char *argv0)
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}
2498
2499START_TEST(debugger)
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}
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:66
static int argc
Definition: ServiceArgs.c:12
#define read
Definition: acwin.h:96
static void startup(void)
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
#define GetNTVersion()
Definition: apitest.h:17
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
LONG NTSTATUS
Definition: precomp.h:26
#define ARRAY_SIZE(A)
Definition: main.h:20
#define U(x)
Definition: wordpad.c:45
static HANDLE thread
Definition: service.c:33
#define RegCloseKey(hKey)
Definition: registry.h:49
Definition: _map.h:48
LPARAM lParam
Definition: combotst.c:139
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
@ DebugObjectKillProcessOnExitInformation
Definition: dbgktypes.h:58
#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
#define NTSTATUS
Definition: precomp.h:19
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
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
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
#define CloseHandle
Definition: compat.h:739
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:758
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define wcsnicmp
Definition: compat.h:14
#define UnmapViewOfFile
Definition: compat.h:746
#define wcsrchr
Definition: compat.h:16
#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 GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define FreeLibrary(x)
Definition: compat.h:748
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define FILE_MAP_READ
Definition: compat.h:776
#define CALLBACK
Definition: compat.h:35
#define MapViewOfFile
Definition: compat.h:745
#define LoadLibraryW(x)
Definition: compat.h:747
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
#define wcsicmp
Definition: compat.h:15
BOOL WINAPI DebugSetProcessKillOnExit(IN BOOL KillOnExit)
Definition: debugger.c:542
BOOL WINAPI DebugActiveProcessStop(IN DWORD dwProcessId)
Definition: debugger.c:486
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
Definition: debugger.c:413
BOOL WINAPI DebugActiveProcess(IN DWORD dwProcessId)
Definition: debugger.c:445
BOOL WINAPI DebugBreakProcess(IN HANDLE Process)
Definition: debugger.c:520
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
Definition: debugger.c:590
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
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
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
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:2064
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
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
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
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
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
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
Definition: thread.c:521
DWORD WINAPI SuspendThread(IN HANDLE hThread)
Definition: thread.c:642
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
HANDLE WINAPI OpenThread(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwThreadId)
Definition: thread.c:403
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
BOOL WINAPI TerminateThread(IN HANDLE hThread, IN DWORD dwExitCode)
Definition: thread.c:587
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
Definition: thread.c:501
BOOL WINAPI IsDebuggerPresent(void)
Definition: debug.c:167
static void basename(LPCWSTR path, LPWSTR name)
Definition: profile.c:38
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
_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
_ACRTIMP __msvcrt_long __cdecl atol(const char *)
Definition: string.c:1782
_ACRTIMP int __cdecl atoi(const char *)
Definition: string.c:1715
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3415
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP int __cdecl strncmp(const char *, const char *, size_t)
Definition: string.c:3330
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
char * va_list
Definition: vadefs.h:50
#define byte(x, n)
Definition: tomcrypt.h:118
return ret
Definition: mutex.c:146
action
Definition: namespace.c:707
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define STATUS_ACCESS_VIOLATION
struct _cl_event * event
Definition: glext.h:7739
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum condition
Definition: glext.h:9255
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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
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
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define THREAD_QUERY_INFORMATION
Definition: pstypes.h:150
#define exception_code
Definition: excpt.h:84
#define DEBUG_KILL_ON_CLOSE
Definition: winternl.h:4377
#define DEBUG_ALL_ACCESS
Definition: winternl.h:4375
#define THREAD_SET_CONTEXT
#define THREAD_SUSPEND_RESUME
#define THREAD_GET_CONTEXT
static TfClientId tid
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define debugstr_w
Definition: kernel32.h:32
#define debug(msg)
Definition: key_call.c:71
#define REG_SZ
Definition: layer.c:22
int winetest_vok(int condition, const char *msg, va_list ap)
const char * winetest_platform
#define win_skip
Definition: minitest.h:67
LONG winetest_get_failures(void)
int winetest_interactive
#define todo_wine
Definition: minitest.h:80
#define EXCEPTION_SINGLE_STEP
Definition: minwinbase.h:47
#define STILL_ACTIVE
Definition: minwinbase.h:43
#define CREATE_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:35
#define LOAD_DLL_DEBUG_EVENT
Definition: minwinbase.h:38
#define EXIT_PROCESS_DEBUG_EVENT
Definition: minwinbase.h:37
#define OUTPUT_DEBUG_STRING_EVENT
Definition: minwinbase.h:40
#define EXCEPTION_DEBUG_EVENT
Definition: minwinbase.h:33
#define CREATE_THREAD_DEBUG_EVENT
Definition: minwinbase.h:34
#define UNLOAD_DLL_DEBUG_EVENT
Definition: minwinbase.h:39
#define EXCEPTION_BREAKPOINT
Definition: minwinbase.h:46
#define EXIT_THREAD_DEBUG_EVENT
Definition: minwinbase.h:36
LONG_PTR LPARAM
Definition: minwindef.h:175
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
unsigned __int64 ULONG64
Definition: imports.h:198
#define sprintf
Definition: sprintf.c:45
#define STATUS_DEBUGGER_INACTIVE
Definition: debugger.c:34
static ACCESS_MASK
Definition: debugger.c:49
static int _load_blackbox(unsigned int line, const char *logfile, void *blackbox, int size)
Definition: debugger.c:152
#define WAIT_EVENT_TIMEOUT
Definition: debugger.c:332
static HMODULE ole32_mod
Definition: debugger.c:999
#define expect_event(a, b)
Definition: debugger.c:1532
static void expect_breakpoint_exception_(unsigned line, struct debugger_context *ctx, const void *expect_addr)
Definition: debugger.c:1562
static void check_dll_event(HANDLE process, DEBUG_EVENT *ev)
Definition: debugger.c:1001
static void expect_exception_(unsigned line, struct debugger_context *ctx, DWORD exception_code)
Definition: debugger.c:1541
static void single_step_(unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread, void *expect_addr)
Definition: debugger.c:1569
static void test_debug_loop_wow64(void)
Definition: debugger.c:1159
static LONG child_failures
Definition: debugger.c:57
static void doCrash(void)
Definition: debugger.c:198
#define child_ok
Definition: debugger.c:37
static void crash_and_winedbg(HKEY hkey, const char *argv0)
Definition: debugger.c:738
static void test_ExitCode(void)
Definition: debugger.c:770
static void * get_ip(const CONTEXT *ctx)
Definition: debugger.c:286
static void test_debug_loop(int argc, char **argv)
Definition: debugger.c:1025
#define check_thread_running(h)
Definition: debugger.c:423
#define check_thread_suspended(h)
Definition: debugger.c:424
static struct debuggee_thread * get_debuggee_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:270
static void get_events(const char *name, HANDLE *start_event, HANDLE *done_event)
Definition: debugger.c:115
static DEBUGOBJECTINFOCLASS
Definition: debugger.c:50
static const BYTE call_debug_service_code[]
Definition: debugger.c:1594
static DWORD WINAPI create_debug_port(void *arg)
Definition: debugger.c:2344
static void crash_and_debug(HKEY hkey, const char *argv0, const char *dbgtasks)
Definition: debugger.c:621
static HMODULE oleaut32_mod
Definition: debugger.c:999
static void fetch_thread_context_(unsigned line, struct debuggee_thread *thread)
Definition: debugger.c:307
static int myARGC
Definition: debugger.c:39
static LONG _check_thread_suspend_count(HANDLE h)
Definition: debugger.c:426
static BOOL is_wow64
Definition: debugger.c:41
static void doChildren(int argc, char **argv)
Definition: debugger.c:1299
#define set_thread_context(a, b)
Definition: debugger.c:324
static void run_background_thread(void)
Definition: debugger.c:190
static void test_kill_on_exit(const char *argv0)
Definition: debugger.c:2355
static void set_ip(CONTEXT *ctx, void *ip)
Definition: debugger.c:297
static HMODULE oleacc_mod
Definition: debugger.c:999
static void doDebugger(int argc, char **argv)
Definition: debugger.c:521
static char * cmd
Definition: debugger.c:2304
#define fetch_thread_context(a)
Definition: debugger.c:306
static DWORD save_value(HKEY hkey, const char *value, reg_save_value *saved)
Definition: debugger.c:89
static void next_event_filter_(unsigned line, struct debugger_context *ctx, DWORD timeout, DWORD mask)
Definition: debugger.c:404
#define next_event_filter(a, b, c)
Definition: debugger.c:403
static void process_attach_events(struct debugger_context *ctx, BOOL pass_exception)
Definition: debugger.c:436
static DWORD WINAPI debug_and_wait(void *arg)
Definition: debugger.c:2325
static OBJECT_ATTRIBUTES ULONG
Definition: debugger.c:49
static HMODULE ntdll
Definition: debugger.c:59
static DWORD event_mask(DWORD ev)
Definition: debugger.c:398
static const BYTE loop_code[]
Definition: debugger.c:1585
static PBOOL
Definition: debugger.c:43
#define next_event(a, b)
Definition: debugger.c:335
static void test_debugger(const char *argv0)
Definition: debugger.c:1645
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static char ** myARGV
Definition: debugger.c:40
#define load_blackbox(a, b, c)
Definition: debugger.c:151
static void restore_value(HKEY hkey, reg_save_value *saved)
Definition: debugger.c:104
static void remove_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:277
static void check_breakpoint_exception_(unsigned line, struct debugger_context *ctx, const void *expect_addr)
Definition: debugger.c:1549
struct tag_reg_save_value reg_save_value
static BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
Definition: debugger.c:1133
static void expect_event_(unsigned line, struct debugger_context *ctx, DWORD event_code)
Definition: debugger.c:1533
static void next_event_(unsigned line, struct debugger_context *ctx, unsigned timeout)
Definition: debugger.c:336
static DWORD WINAPI debug_and_exit(void *arg)
Definition: debugger.c:2306
#define check_breakpoint_exception(a, b)
Definition: debugger.c:1548
int debuggee_thread_compare(const void *key, const struct wine_rb_entry *entry)
Definition: debugger.c:252
static void doChild(int argc, char **argv)
Definition: debugger.c:897
#define OP_BP
Definition: debugger.c:1642
static void save_blackbox(const char *logfile, void *blackbox, int size, const char *dbgtrace)
Definition: debugger.c:131
#define wait_for_breakpoint(a)
Definition: debugger.c:412
#define POLL_EVENT_TIMEOUT
Definition: debugger.c:333
static DWORD run_child_wait(char *cmd, HANDLE event)
Definition: debugger.c:2282
static void set_thread_context_(unsigned line, struct debugger_context *ctx, struct debuggee_thread *thread)
Definition: debugger.c:325
#define expect_breakpoint_exception(a, b)
Definition: debugger.c:1561
static void add_thread(struct debugger_context *ctx, DWORD tid)
Definition: debugger.c:258
static void wait_for_breakpoint_(unsigned line, struct debugger_context *ctx)
Definition: debugger.c:413
static DWORD WINAPI thread_proc(void *arg)
Definition: debugger.c:183
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
static void close_main_windows(DWORD pid)
Definition: debugger.c:1148
#define single_step(a, b, c)
Definition: debugger.c:1568
static UINT exit_code
Definition: process.c:80
static HANDLE start_event
Definition: thread.c:136
static SYSTEM_INFO si
Definition: virtual.c:39
#define __WINE_PRINTF_ATTR(fmt, args)
Definition: custom.c:42
static va_list valist
Definition: printf.c:46
#define argv
Definition: mplay32.c:18
_In_ HANDLE hFile
Definition: mswsock.h:90
#define SEC_IMAGE
Definition: mmtypes.h:97
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#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 BOOL
Definition: nt_native.h:43
#define DWORD
Definition: nt_native.h:44
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1088
#define CONTEXT_FULL
Definition: nt_native.h:1378
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_COMMIT
Definition: nt_native.h:1316
#define PAGE_EXECUTE_READWRITE
Definition: nt_native.h:1311
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
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 DBG_CONTINUE
Definition: ntstatus.h:98
#define STATUS_WX86_BREAKPOINT
Definition: ntstatus.h:220
#define DBG_EXCEPTION_NOT_HANDLED
Definition: ntstatus.h:109
long LONG
Definition: pedump.c:60
#define get_file_name
Definition: regproc.h:51
#define REG_DWORD
Definition: sdbapi.c:615
#define WINAPIV
Definition: sdbpapi.h:64
wcscat
wcscpy
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
#define wine_rb_entry
Definition: rbtree.h:404
#define WINE_RB_ENTRY_VALUE
Definition: rbtree.h:414
#define wine_rb_put
Definition: rbtree.h:410
#define wine_rb_tree
Definition: rbtree.h:405
#define wine_rb_init
Definition: rbtree.h:406
#define wine_rb_get
Definition: rbtree.h:409
#define wine_rb_remove
Definition: rbtree.h:411
#define is_reactos()
Definition: test.h:1041
#define ignore_exceptions
Definition: test.h:178
int winetest_get_mainargs(char ***pargv)
#define memset(x, y, z)
Definition: compat.h:39
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define _WIN32_WINNT_WIN8
Definition: sdkddkver.h:29
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
int zero
Definition: sehframes.cpp:29
#define STATUS_SUCCESS
Definition: shellext.h:65
static PVOID hdll
Definition: shimdbg.c:126
static char argv0[MAX_PATH]
Definition: shlexec.c:49
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
UNLOAD_DLL_DEBUG_INFO UnloadDll
Definition: minwinbase.h:207
union _DEBUG_EVENT::@3249 u
DWORD dwDebugEventCode
Definition: minwinbase.h:196
DWORD dwThreadId
Definition: minwinbase.h:198
DWORD dwProcessId
Definition: minwinbase.h:197
LOAD_DLL_DEBUG_INFO LoadDll
Definition: minwinbase.h:206
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
Definition: cookie.c:202
Definition: ftp_var.h:139
struct wine_rb_entry entry
Definition: debugger.c:249
HANDLE handle
Definition: debugger.c:247
CONTEXT ctx
Definition: debugger.c:248
DWORD thread_tag
Definition: debugger.c:236
struct wine_rb_tree threads
Definition: debugger.c:238
struct debuggee_thread * main_thread
Definition: debugger.c:240
DEBUG_EVENT ev
Definition: debugger.c:232
struct debuggee_thread * current_thread
Definition: debugger.c:239
void * image_base
Definition: debugger.c:235
unsigned process_cnt
Definition: debugger.c:233
unsigned dll_cnt
Definition: debugger.c:234
unsigned thread_cnt
Definition: debugger.c:237
Definition: fci.c:127
HWND windows[5]
Definition: debugger.c:1130
unsigned count
Definition: debugger.c:1129
Definition: dhcpd.h:62
Definition: copy.c:22
Definition: parser.c:49
Definition: mem.c:349
Definition: name.c:39
Definition: ps.c:97
const char * name
Definition: debugger.c:83
Definition: dhcpd.h:248
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
Definition: synch.c:669
#define DWORD_PTR
Definition: treelist.c:76
int32_t INT_PTR
Definition: typedefs.h:64
uint32_t DWORD_PTR
Definition: typedefs.h:65
PVOID HANDLE
Definition: typedefs.h:73
uint32_t ULONG_PTR
Definition: typedefs.h:65
HANDLE HMODULE
Definition: typedefs.h:77
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
CONTEXT ctx
Definition: pdh_main.c:96
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
_In_ size_t cnt
Definition: wcstombs.cpp:43
LPVOID NTAPI VirtualAllocEx(IN HANDLE hProcess, IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flAllocationType, IN DWORD flProtect)
Definition: virtmem.c:23
#define WAIT_ABANDONED
Definition: winbase.h:389
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define STARTF_USESHOWWINDOW
Definition: winbase.h:468
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
#define DEBUG_ONLY_THIS_PROCESS
Definition: winbase.h:181
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define DEBUG_PROCESS
Definition: winbase.h:180
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define WINAPI
Definition: msvc.h:6
#define ERROR_SEM_TIMEOUT
Definition: winerror.h:315
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define SW_SHOWNORMAL
Definition: winuser.h:781
#define GW_OWNER
Definition: winuser.h:777
#define WM_CLOSE
Definition: winuser.h:1649
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC lpEnumFunc, _In_ LPARAM lParam)
HWND WINAPI GetWindow(_In_ HWND, _In_ UINT)
BOOL WINAPI PostMessageA(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193
#define const
Definition: zconf.h:233