From: Eric Pouech eric.pouech@gmail.com
Showing that: - load/unload events for 64bit DLLs are generated for a WOW64 process. - 64bit startup exception is generated as well (with a specific exception code)
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/kernel32/tests/debugger.c | 94 ++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 2491b1093f1..f27db2872d1 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -1077,6 +1077,99 @@ static void test_debug_loop(int argc, char **argv) ok(ret, "DeleteFileA failed, last error %#lx.\n", GetLastError()); }
+static void test_debug_loop_wow64(void) +{ + WCHAR buffer[MAX_PATH], *p; + PROCESS_INFORMATION pi; + STARTUPINFOW si; + BOOL ret; + unsigned order = 0, bp_order = 0, bpwx_order = 0, num_ntdll = 0, num_wow64 = 0; + + /* checking conditions for running this test */ + if (GetSystemWow64DirectoryW( buffer, ARRAY_SIZE(buffer) ) && sizeof(void*) > sizeof(int) && pGetMappedFileNameW) + { + wcscat( buffer, L"\msinfo32.exe" ); + ret = GetFileAttributesW( buffer ) != INVALID_FILE_ATTRIBUTES; + } + else ret = FALSE; + if (!ret) + { + skip("Skipping test on incompatible config\n"); + return; + } + memset( &si, 0, sizeof(si) ); + si.cb = sizeof(si); + ret = CreateProcessW( NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi ); + ok(ret, "CreateProcess failed, last error %#lx.\n", GetLastError()); + + for (;;) + { + DEBUG_EVENT ev; + + ++order; + ret = WaitForDebugEvent( &ev, 2000 ); + if (!ret) break; + + switch (ev.dwDebugEventCode) + { + case CREATE_PROCESS_DEBUG_EVENT: + break; + case LOAD_DLL_DEBUG_EVENT: + if (!pGetMappedFileNameW( pi.hProcess, ev.u.LoadDll.lpBaseOfDll, buffer, ARRAY_SIZE(buffer) )) buffer[0] = L'\0'; + if ((p = wcsrchr( buffer, '\' ))) p++; + else p = buffer; + if (!memcmp( p, L"wow64", 5 * sizeof(WCHAR) )) + { + /* on Win10, wow64cpu's load dll event is received after first exception */ + ok(bpwx_order == 0, "loaddll for wow64 DLLs should appear before exception\n"); + num_wow64++; + } + else if (!wcsicmp( p, L"ntdll.dll" )) + { + ok(bp_order == 0 && bpwx_order == 0, "loaddll on ntdll should appear before exception\n"); + num_ntdll++; + } + break; + case EXCEPTION_DEBUG_EVENT: + if (ev.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) + bp_order = order; + else if (ev.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT) + bpwx_order = order; + } + ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); + ok(ret, "ContinueDebugEvent failed, last error %#lx.\n", GetLastError()); + if (!ret) break; + } + + ret = TerminateProcess( pi.hProcess, 0 ); + ok(ret, "TerminateProcess failed: %lu\n", GetLastError()); + + /* eat up the remaining events */ + for (;;) + { + DEBUG_EVENT ev; + + if (!WaitForDebugEvent( &ev, 2000 )) break; + } + + ret = CloseHandle(pi.hThread); + ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError()); + ret = CloseHandle(pi.hProcess); + ok(ret, "CloseHandle failed, last error %#lx.\n", GetLastError()); + + todo_wine + { + ok(num_ntdll == 2, "Expecting two ntdll instances\n"); + ok(num_wow64 >= 3, "Expecting more than 3 wow64*.dll\n"); + } + ok(bp_order, "Expecting 1 bp exceptions\n"); + todo_wine + { + ok(bpwx_order, "Expecting 1 bpwx exceptions\n"); + ok(bp_order < bpwx_order, "Out of order bp exceptions\n"); + } +} + static void doChildren(int argc, char **argv) { const char *arguments = "debugger children last"; @@ -2284,6 +2377,7 @@ START_TEST(debugger) test_ExitCode(); test_RemoteDebugger(); test_debug_loop(myARGC, myARGV); + test_debug_loop_wow64(); test_debug_children(myARGV[0], DEBUG_PROCESS, TRUE, FALSE); test_debug_children(myARGV[0], DEBUG_ONLY_THIS_PROCESS, FALSE, FALSE); test_debug_children(myARGV[0], DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS, FALSE, FALSE);