Since b780e5f5b1bd018629bfa31431e216c7579fe9aa, as get_language_sort is now called from init_locale, this raises an unexpected exception at process startup, before the initial breakpoint exception.
It was causing some kernel32 debugger test failures.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernelbase/locale.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 623cb01280b6..06ad6ad01683 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -658,7 +658,7 @@ static const struct sortguid *get_language_sort( const WCHAR *locale ) const struct sortguid *ret; UNICODE_STRING str; GUID guid; - HKEY key; + HKEY key = INVALID_HANDLE_VALUE; DWORD size, type;
if (locale == LOCALE_NAME_USER_DEFAULT) @@ -690,7 +690,8 @@ static const struct sortguid *get_language_sort( const WCHAR *locale ) } ret = find_sortguid( &default_sort_guid ); done: - RegCloseKey( key ); + if (key != INVALID_HANDLE_VALUE) + RegCloseKey( key ); return ret; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This is now doing dedicated tests for DBG_REPLY_LATER instead of trying to inject it within the existing tests.
Testing on Windows shows that delayed events are not immediately re-raised when the corresponding thread is resumed and that the ordering of delayed events between concurrent threads is not guaranteed, but it can still be the same as the initial reception.
The Wine implementation in next patch keeps always keep delayed events in the same order as the initial reception.
dlls/kernel32/tests/debugger.c | 237 ++++++++++++++++++++++++++++++++- 1 file changed, 236 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index a2b5d1f410e6..8062c2946126 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -41,6 +41,9 @@ static BOOL (WINAPI *pCheckRemoteDebuggerPresent)(HANDLE,PBOOL);
static void (WINAPI *pDbgBreakPoint)(void);
+static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE process); +static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE process); + static LONG child_failures;
static HMODULE ntdll; @@ -1251,9 +1254,10 @@ static void test_debugger(const char *argv0) struct debugger_context ctx = { 0 }; PROCESS_INFORMATION pi; STARTUPINFOA si; + NTSTATUS status; HANDLE event, thread; BYTE *mem, buf[4096], *proc_code, *thread_proc, byte; - unsigned int i, worker_cnt, exception_cnt; + unsigned int i, worker_cnt, exception_cnt, skip_reply_later; struct debuggee_thread *debuggee_thread; char *cmd; BOOL ret; @@ -1272,6 +1276,62 @@ static void test_debugger(const char *argv0)
next_event(&ctx, WAIT_EVENT_TIMEOUT); ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + + if ((skip_reply_later = !ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER))) + todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + else + { + DEBUG_EVENT de; + + de = ctx.ev; + ctx.ev.dwDebugEventCode = -1; + next_event(&ctx, WAIT_EVENT_TIMEOUT); + ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode); + ok(de.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de.dwProcessId); + ok(de.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de.dwThreadId); + + /* Suspending the thread should prevent other attach debug events + * to be received until it's resumed */ + thread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, ctx.ev.dwThreadId); + ok(thread != INVALID_HANDLE_VALUE, "OpenThread failed, last error:%u\n", GetLastError()); + + status = NtSuspendThread(thread, NULL); + ok(!status, "NtSuspendThread failed, last error:%u\n", GetLastError()); + + ok(ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n"); + + status = NtResumeThread(thread, NULL); + ok(!status, "NtResumeThread failed, last error:%u\n", GetLastError()); + + ret = CloseHandle(thread); + ok(ret, "CloseHandle failed, last error %d.\n", GetLastError()); + + ok(WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent failed.\n"); + ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode); + + next_event(&ctx, WAIT_EVENT_TIMEOUT); + ok(ctx.ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + de = ctx.ev; + + ok(ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + + ctx.ev.dwDebugEventCode = -1; + next_event(&ctx, WAIT_EVENT_TIMEOUT); + ok(de.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de.dwDebugEventCode); + ok(de.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de.dwProcessId); + ok(de.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de.dwThreadId); + } + wait_for_breakpoint(&ctx); do next_event(&ctx, POLL_EVENT_TIMEOUT); while(ctx.ev.dwDebugEventCode != -1); @@ -1341,6 +1401,179 @@ static void test_debugger(const char *argv0) } else win_skip("call_debug_service_code not supported on this architecture\n");
+ if (skip_reply_later) + todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + else if (sizeof(loop_code) > 1) + { + HANDLE thread_a, thread_b; + DEBUG_EVENT de_a, de_b; + + memset(buf, OP_BP, sizeof(buf)); + memcpy(proc_code, &loop_code, sizeof(loop_code)); + ret = WriteProcessMemory(pi.hProcess, mem, buf, sizeof(buf), NULL); + ok(ret, "WriteProcessMemory failed: %u\n", GetLastError()); + + byte = OP_BP; + ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL); + ok(ret, "WriteProcessMemory failed: %u\n", GetLastError()); + + thread_a = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, NULL, 0, NULL); + ok(thread_a != NULL, "CreateRemoteThread failed: %u\n", GetLastError()); + next_event(&ctx, WAIT_EVENT_TIMEOUT); + ok(ctx.ev.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + de_a = ctx.ev; + + thread_b = CreateRemoteThread(pi.hProcess, NULL, 0, (void*)thread_proc, NULL, 0, NULL); + ok(thread_b != NULL, "CreateRemoteThread failed: %u\n", GetLastError()); + do next_event(&ctx, POLL_EVENT_TIMEOUT); + while(ctx.ev.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT); + de_b = ctx.ev; + + status = NtSuspendThread(thread_b, NULL); + ok(!status, "NtSuspendThread failed, last error:%u\n", GetLastError()); + ok(ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + + ctx.ev.dwDebugEventCode = -1; + next_event(&ctx, WAIT_EVENT_TIMEOUT); + ok(ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT, + "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + ok(de_a.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_a.dwProcessId); + ok(de_a.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_a.dwThreadId); + de_a = ctx.ev; + + byte = 0xc3; /* ret */ + ret = WriteProcessMemory(pi.hProcess, thread_proc + 1, &byte, 1, NULL); + ok(ret, "WriteProcessMemory failed: %u\n", GetLastError()); + + ok(pNtSuspendProcess != NULL, "NtSuspendProcess not found\n"); + ok(pNtResumeProcess != NULL, "pNtResumeProcess not found\n"); + if (pNtSuspendProcess && pNtResumeProcess) + { + status = pNtSuspendProcess(pi.hProcess); + ok(!status, "NtSuspendProcess failed, last error:%u\n", GetLastError()); + ok(ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER), + "ContinueDebugEvent failed, last error:%u\n", GetLastError()); + ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n"); + + status = NtResumeThread(thread_b, NULL); + ok(!status, "NtResumeThread failed, last error:%u\n", GetLastError()); + ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n"); + + status = pNtResumeProcess(pi.hProcess); + ok(!status, "pNtResumeProcess failed, last error:%u\n", GetLastError()); + } + else + { + status = NtResumeThread(thread_b, NULL); + ok(!status, "NtResumeThread failed, last error:%u\n", GetLastError()); + ok(!WaitForDebugEvent(&ctx.ev, POLL_EVENT_TIMEOUT), "WaitForDebugEvent succeeded.\n"); + } + + /* Testing shows that on windows the debug event order between threads + * is not guaranteed. + * + * Now we expect thread_a to report: + * - its delayed EXCEPTION_DEBUG_EVENT + * - EXIT_THREAD_DEBUG_EVENT + * + * and thread_b to report: + * - its delayed CREATE_THREAD_DEBUG_EVENT + * - EXIT_THREAD_DEBUG_EVENT + * + * We should not get EXCEPTION_DEBUG_EVENT from thread_b as we updated + * its instructions before continuing CREATE_THREAD_DEBUG_EVENT. + */ + ctx.ev.dwDebugEventCode = -1; + next_event(&ctx, POLL_EVENT_TIMEOUT); + + if (ctx.ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) + { + ok(de_a.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de_a.dwDebugEventCode); + ok(de_a.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_a.dwProcessId); + ok(de_a.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_a.dwThreadId); + + next_event(&ctx, POLL_EVENT_TIMEOUT); + if (ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT) + { + ok(de_a.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_a.dwProcessId); + ok(de_a.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_a.dwThreadId); + + ret = CloseHandle(thread_a); + ok(ret, "CloseHandle failed, last error %d.\n", GetLastError()); + thread_a = NULL; + + next_event(&ctx, POLL_EVENT_TIMEOUT); + } + + ok(de_b.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de_b.dwDebugEventCode); + ok(de_b.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_b.dwProcessId); + ok(de_b.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_b.dwThreadId); + } + else + { + ok(de_b.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de_b.dwDebugEventCode); + ok(de_b.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_b.dwProcessId); + ok(de_b.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_b.dwThreadId); + + next_event(&ctx, POLL_EVENT_TIMEOUT); + if (ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT) + { + ok(de_b.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_b.dwProcessId); + ok(de_b.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_b.dwThreadId); + + ret = CloseHandle(thread_b); + ok(ret, "CloseHandle failed, last error %d.\n", GetLastError()); + thread_b = NULL; + + next_event(&ctx, POLL_EVENT_TIMEOUT); + } + + ok(de_a.dwDebugEventCode == ctx.ev.dwDebugEventCode, + "dwDebugEventCode differs: %x (was %x)\n", ctx.ev.dwDebugEventCode, de_a.dwDebugEventCode); + ok(de_a.dwProcessId == ctx.ev.dwProcessId, + "dwProcessId differs: %x (was %x)\n", ctx.ev.dwProcessId, de_a.dwProcessId); + ok(de_a.dwThreadId == ctx.ev.dwThreadId, + "dwThreadId differs: %x (was %x)\n", ctx.ev.dwThreadId, de_a.dwThreadId); + } + + if (thread_a) + { + next_event(&ctx, POLL_EVENT_TIMEOUT); + ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT, + "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + + ret = CloseHandle(thread_a); + ok(ret, "CloseHandle failed, last error %d.\n", GetLastError()); + } + + + if (thread_b) + { + next_event(&ctx, POLL_EVENT_TIMEOUT); + ok(ctx.ev.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT, + "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode); + + ret = CloseHandle(thread_b); + ok(ret, "CloseHandle failed, last error %d.\n", GetLastError()); + } + } + if (sizeof(loop_code) > 1) { struct debuggee_thread *prev_thread; @@ -1444,6 +1677,8 @@ START_TEST(debugger)
ntdll = GetModuleHandleA("ntdll.dll"); pDbgBreakPoint = (void*)GetProcAddress(ntdll, "DbgBreakPoint"); + pNtSuspendProcess = (void*)GetProcAddress(ntdll, "NtSuspendProcess"); + pNtResumeProcess = (void*)GetProcAddress(ntdll, "NtResumeProcess");
myARGC=winetest_get_mainargs(&myARGV); if (myARGC >= 3 && strcmp(myARGV[2], "crash") == 0)
This flag causes the debug event to be replayed after the target thread continues. It can be used, after suspending the thread, to resume other threads and later return to the breaking.
This will help implementing gdb continue/step packets correctly.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernel32/tests/debugger.c | 4 +- server/debugger.c | 73 ++++++++++++++++++++++++++++++++-- server/object.h | 1 + server/thread.c | 3 +- 4 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 8062c2946126..33e18d82e620 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -1278,7 +1278,7 @@ static void test_debugger(const char *argv0) ok(ctx.ev.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT, "dwDebugEventCode = %d\n", ctx.ev.dwDebugEventCode);
if ((skip_reply_later = !ContinueDebugEvent(ctx.ev.dwProcessId, ctx.ev.dwThreadId, DBG_REPLY_LATER))) - todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); else { DEBUG_EVENT de; @@ -1402,7 +1402,7 @@ static void test_debugger(const char *argv0) else win_skip("call_debug_service_code not supported on this architecture\n");
if (skip_reply_later) - todo_wine win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); + win_skip("Skipping unsupported DBG_REPLY_LATER tests\n"); else if (sizeof(loop_code) > 1) { HANDLE thread_a, thread_b; diff --git a/server/debugger.c b/server/debugger.c index 5b06b73b4be4..5ff63b92b9c0 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -38,7 +38,7 @@ #include "thread.h" #include "request.h"
-enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_CONTINUED }; +enum debug_event_state { EVENT_QUEUED, EVENT_SENT, EVENT_DELAYED, EVENT_CONTINUED };
/* debug event */ struct debug_event @@ -265,6 +265,31 @@ static void link_event( struct debug_event *event ) } }
+/* resume a delayed debug event already in the queue */ +static void resume_event( struct debug_event *event ) +{ + struct debug_ctx *debug_ctx = event->debugger->debug_ctx; + + assert( debug_ctx ); + event->state = EVENT_QUEUED; + if (!event->sender->process->debug_event) + { + grab_object( debug_ctx ); + wake_up( &debug_ctx->obj, 0 ); + release_object( debug_ctx ); + } +} + +/* delay a debug event already in the queue to be replayed when thread wakes up */ +static void delay_event( struct debug_event *event ) +{ + struct debug_ctx *debug_ctx = event->debugger->debug_ctx; + + assert( debug_ctx ); + event->state = EVENT_DELAYED; + if (event->sender->process->debug_event == event) event->sender->process->debug_event = NULL; +} + /* find the next event that we can send to the debugger */ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx ) { @@ -273,6 +298,7 @@ static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx ) LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { if (event->state == EVENT_SENT) continue; /* already sent */ + if (event->state == EVENT_DELAYED) continue; /* delayed until thread resumes */ if (event->sender->process->debug_event) continue; /* process busy with another one */ return event; } @@ -365,6 +391,29 @@ static int continue_debug_event( struct process *process, struct thread *thread, { struct debug_event *event;
+ if (status == DBG_REPLY_LATER) + { + /* if thread is suspended, delay all its events and resume process + * if not, reset the event for immediate replay */ + LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) + { + if (event->sender != thread) continue; + if (thread->suspend) + { + delay_event( event ); + resume_process( process ); + } + else if (event->state == EVENT_SENT) + { + assert( event->sender->process->debug_event == event ); + event->sender->process->debug_event = NULL; + resume_event( event ); + return 1; + } + } + return 1; + } + /* find the event in the queue */ LIST_FOR_EACH_ENTRY( event, &debug_ctx->event_queue, struct debug_event, entry ) { @@ -372,7 +421,6 @@ static int continue_debug_event( struct process *process, struct thread *thread, if (event->sender == thread) { assert( event->sender->process->debug_event == event ); - event->status = status; event->state = EVENT_CONTINUED; wake_up( &event->obj, 0 ); @@ -430,6 +478,24 @@ void generate_debug_event( struct thread *thread, int code, const void *arg ) } }
+void resume_delayed_debug_events( struct thread *thread ) +{ + struct thread *debugger = thread->process->debugger; + struct debug_event *event; + + if (debugger) + { + assert( debugger->debug_ctx ); + LIST_FOR_EACH_ENTRY( event, &debugger->debug_ctx->event_queue, struct debug_event, entry ) + { + if (event->sender != thread) continue; + if (event->state != EVENT_DELAYED) continue; + resume_event( event ); + suspend_process( thread->process ); + } + } +} + /* attach a process to a debugger thread and suspend it */ static int debugger_attach( struct process *process, struct thread *debugger ) { @@ -615,7 +681,8 @@ DECL_HANDLER(continue_debug_event) struct process *process;
if (req->status != DBG_EXCEPTION_NOT_HANDLED && - req->status != DBG_CONTINUE) + req->status != DBG_CONTINUE && + req->status != DBG_REPLY_LATER) { set_error( STATUS_INVALID_PARAMETER ); return; diff --git a/server/object.h b/server/object.h index 4a486e0d6334..7f664ad28218 100644 --- a/server/object.h +++ b/server/object.h @@ -206,6 +206,7 @@ extern void sock_init(void);
extern int set_process_debugger( struct process *process, struct thread *debugger ); extern void generate_debug_event( struct thread *thread, int code, const void *arg ); +extern void resume_delayed_debug_events( struct thread *thread ); extern void generate_startup_debug_events( struct process *process, client_ptr_t entry ); extern void debug_exit_thread( struct thread *thread );
diff --git a/server/thread.c b/server/thread.c index edf70c61bde9..6e677c8cf291 100644 --- a/server/thread.c +++ b/server/thread.c @@ -612,7 +612,8 @@ int resume_thread( struct thread *thread ) int old_count = thread->suspend; if (thread->suspend > 0) { - if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread ); + if (!(--thread->suspend)) resume_delayed_debug_events( thread ); + if (!(thread->suspend + thread->process->suspend)) wake_thread( thread ); } return old_count; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=68005
Your paranoid android.
=== w1064v1809_ar (32 bit report) ===
kernel32: debugger.c:145: Test failed: unable to open 'C:\Users\winetest\AppData\Local\Temp\wt32C8.tmp' debugger.c:145: Test failed: failed to open: C:\Users\winetest\AppData\Local\Temp\wt32C8.tmp debugger.c:657: Test failed: the child and debugged pids don't match: 6236 != 6892
=== w1064v1809_ja (32 bit report) ===
kernel32: debugger.c:145: Test failed: unable to open 'C:\Users\winetest\AppData\Local\Temp\wt3170.tmp' debugger.c:145: Test failed: failed to open: C:\Users\winetest\AppData\Local\Temp\wt3170.tmp debugger.c:657: Test failed: the child and debugged pids don't match: 6476 != 7076
On 3/24/20 4:05 PM, Rémi Bernon wrote:
Since b780e5f5b1bd018629bfa31431e216c7579fe9aa, as get_language_sort is now called from init_locale, this raises an unexpected exception at process startup, before the initial breakpoint exception.
It was causing some kernel32 debugger test failures.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com
dlls/kernelbase/locale.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 623cb01280b6..06ad6ad01683 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -658,7 +658,7 @@ static const struct sortguid *get_language_sort( const WCHAR *locale ) const struct sortguid *ret; UNICODE_STRING str; GUID guid;
- HKEY key;
HKEY key = INVALID_HANDLE_VALUE; DWORD size, type;
if (locale == LOCALE_NAME_USER_DEFAULT)
@@ -690,7 +690,8 @@ static const struct sortguid *get_language_sort( const WCHAR *locale ) } ret = find_sortguid( &default_sort_guid ); done:
- RegCloseKey( key );
- if (key != INVALID_HANDLE_VALUE)
}RegCloseKey( key ); return ret;
This first patch is not needed anymore, please ignore it.