From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/dbghelp/tests/Makefile.in | 2 +- dlls/dbghelp/tests/dbghelp.c | 168 ++++++++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/tests/Makefile.in b/dlls/dbghelp/tests/Makefile.in index 31e5b01e8a8..40ec97eca8c 100644 --- a/dlls/dbghelp/tests/Makefile.in +++ b/dlls/dbghelp/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = dbghelp.dll -IMPORTS = dbghelp +IMPORTS = dbghelp user32
C_SRCS = \ dbghelp.c diff --git a/dlls/dbghelp/tests/dbghelp.c b/dlls/dbghelp/tests/dbghelp.c index 8b65ef68670..c7e2b675b02 100644 --- a/dlls/dbghelp/tests/dbghelp.c +++ b/dlls/dbghelp/tests/dbghelp.c @@ -16,7 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include "windef.h" +#include "windows.h" +#include "psapi.h" #include "verrsrc.h" #include "dbghelp.h" #include "wine/test.h" @@ -201,6 +202,67 @@ static const USHORT machines[2] = #endif };
+struct module_aggregation +{ + HANDLE process; + unsigned int num32; + unsigned int num64; + unsigned int num_exe; + unsigned int num_ntdll; + unsigned int num_wow; +}; + +static BOOL CALLBACK aggregate_cb(PCWSTR imagename, DWORD64 base, ULONG sz, PVOID usr) +{ + struct module_aggregation* aggregation = usr; + WCHAR buffer[MAX_PATH]; + IMAGEHLP_MODULEW64 im; + size_t image_len; + BOOL ret; + + memset(&im, 0, sizeof(im)); + im.SizeOfStruct = sizeof(im); + + /* MSDN states that first paramter of callback is a module name... + * Testing on Win10 show it looks more like an image pathname... sigh... + * Wine still passes module here. + * So: if that first parameter doesn't look as an imagename, get imagename from process. + */ + if (!wcschr(imagename, L'.')) + { + ret = GetModuleFileNameExW(aggregation->process, (HMODULE)(ULONG_PTR)base, buffer, ARRAY_SIZE(buffer)); + ok(ret, "GetModuleFileNameW failed: %lu\n", GetLastError()); + imagename = buffer; + } + image_len = wcslen(imagename); + + ret = SymGetModuleInfoW64(aggregation->process, base, &im); + if (ret) + ok(aggregation->num_exe && image_len >= 4 && !wcscmp(imagename + image_len - 4, L".exe"), + "%ls shouldn't already be loaded\n", imagename); + else + { + ok(!ret, "Module %ls shouldn't be loaded\n", imagename); + ret = SymLoadModuleExW(aggregation->process, NULL, imagename, NULL, base, sz, NULL, 0); + ok(ret, "SymLoadModuleExW failed on %ls: %lu\n", imagename, GetLastError()); + } + ret = SymGetModuleInfoW64(aggregation->process, base, &im); + ok(ret, "SymGetModuleInfoW64 failed: %lu\n", GetLastError()); + + if (im.MachineType == machines[1]) + aggregation->num32++; + if (im.MachineType == machines[0]) + aggregation->num64++; + if (image_len >= 4 && !wcscmp(imagename + image_len - 4, L".exe")) + aggregation->num_exe++; + if (!wcsicmp(im.ModuleName, L"ntdll")) + aggregation->num_ntdll++; + if (!memcmp(im.ModuleName, L"wow", 3 * sizeof(WCHAR))) + aggregation->num_wow++; + + return TRUE; +} + static void test_modules(void) { BOOL ret; @@ -208,6 +270,10 @@ static void test_modules(void) const DWORD64 base1 = 0x00010000; const DWORD64 base2 = 0x08010000; IMAGEHLP_MODULEW64 im; + char buffer[200] = "C:\windows\system32\notepad.exe"; + PROCESS_INFORMATION pi = {0}; + STARTUPINFOA si = {0}; + struct module_aggregation aggregation = {0};
im.SizeOfStruct = sizeof(im);
@@ -250,6 +316,104 @@ static void test_modules(void)
ret = SymCleanup(GetCurrentProcess()); ok(ret, "SymCleanup failed: %lu\n", GetLastError()); + + /* testing with child process of different machines */ + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "CreateProcess failed: %lu\n", GetLastError()); + + ret = WaitForInputIdle(pi.hProcess, 5000); + ok(!ret, "wait timed out\n"); + + ret = SymInitialize(pi.hProcess, NULL, FALSE); + ok(ret, "SymInitialize failed: %lu\n", GetLastError()); + memset(&aggregation, 0, sizeof(aggregation)); + aggregation.process = pi.hProcess; + + ret = EnumerateLoadedModulesW64(pi.hProcess, aggregate_cb, &aggregation); + ok(ret, "EnumeteLoadedModulesW64 failed: %lu\n", GetLastError()); + + if (sizeof(void *) == 8) + { + ok(!aggregation.num32 && aggregation.num64 && aggregation.num_exe == 1 && aggregation.num_ntdll == 1 && !aggregation.num_wow, + "Wrong aggreation count %u %u %u %u %u\n", + aggregation.num32, aggregation.num64, aggregation.num_exe, aggregation.num_ntdll, aggregation.num_wow); + } + else + { + ok(aggregation.num32 && !aggregation.num64 && aggregation.num_exe == 1 && aggregation.num_ntdll == 1 && !aggregation.num_wow, + "Wrong aggreation count %u %u %u %u %u\n", + aggregation.num32, aggregation.num64, aggregation.num_exe, aggregation.num_ntdll, aggregation.num_wow); + } + + SymCleanup(pi.hProcess); + TerminateProcess(pi.hProcess, 0); + + if (sizeof(void *) == 8) + { + strcpy(buffer, "C:\windows\syswow64\notepad.exe"); + + SymSetOptions(SymGetOptions() & ~SYMOPT_INCLUDE_32BIT_MODULES); + + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + if (ret) + { + ret = WaitForInputIdle(pi.hProcess, 5000); + ok(!ret, "wait timed out\n"); + + ret = SymInitialize(pi.hProcess, NULL, FALSE); + ok(ret, "SymInitialize failed: %lu\n", GetLastError()); + memset(&aggregation, 0, sizeof(aggregation)); + aggregation.process = pi.hProcess; + ret = EnumerateLoadedModulesW64(pi.hProcess, aggregate_cb, &aggregation); + ok(ret, "EnumeteLoadedModulesW64 failed: %lu\n", GetLastError()); + + todo_wine + ok(aggregation.num32 && aggregation.num64 && aggregation.num_exe == 1 && aggregation.num_ntdll == 1 && aggregation.num_wow, + "Wrong aggreation count %u %u %u %u %u\n", + aggregation.num32, aggregation.num64, aggregation.num_exe, aggregation.num_ntdll, aggregation.num_wow); + + SymCleanup(pi.hProcess); + TerminateProcess(pi.hProcess, 0); + } + else + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + skip("Skip wow64 test on non compatible platform\n"); + else + ok(ret, "CreateProcess failed: %lu\n", GetLastError()); + } + + SymSetOptions(SymGetOptions() | SYMOPT_INCLUDE_32BIT_MODULES); + + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + if (ret) + { + ret = WaitForInputIdle(pi.hProcess, 5000); + ok(!ret, "wait timed out\n"); + + ret = SymInitialize(pi.hProcess, NULL, FALSE); + ok(ret, "SymInitialize failed: %lu\n", GetLastError()); + memset(&aggregation, 0, sizeof(aggregation)); + aggregation.process = pi.hProcess; + ret = EnumerateLoadedModulesW64(pi.hProcess, aggregate_cb, &aggregation); + ok(ret, "EnumerateLoadedModulesW64 failed: %lu\n", GetLastError()); + + todo_wine + ok(aggregation.num32 && aggregation.num64 && aggregation.num_exe == 2 && aggregation.num_ntdll == 2 && aggregation.num_wow, + "Wrong aggreation count %u %u %u %u %u\n", + aggregation.num32, aggregation.num64, aggregation.num_exe, aggregation.num_ntdll, aggregation.num_wow); + + SymCleanup(pi.hProcess); + TerminateProcess(pi.hProcess, 0); + } + else + { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + skip("Skip wow64 test on non compatible platform\n"); + else + ok(ret, "CreateProcess failed: %lu\n", GetLastError()); + } + } }
START_TEST(dbghelp) @@ -261,7 +425,7 @@ START_TEST(dbghelp) SetEnvironmentVariableA("_NT_ALT_SYMBOL_PATH", NULL);
ret = SymInitialize(GetCurrentProcess(), NULL, TRUE); - ok(ret, "got error %lu\n", GetLastError()); + ok(ret, "SymInitialize failed: %lu\n", GetLastError());
test_stack_walk(); test_search_path();