From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/module.c | 91 ++++++++++++++++++++++++++++++++++++++++++- dlls/psapi/tests/Makefile.in | 1 + dlls/psapi/tests/psapi_main.c | 67 +++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 6f123ca..ac1f45f 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -1493,10 +1493,56 @@ FARPROC WINAPI DelayLoadFailureHook( LPCSTR name, LPCSTR function ) return NULL; }
+typedef struct _PEB32 +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN SpareBool; + DWORD Mutant; + DWORD ImageBaseAddress; + DWORD LdrData; +} PEB32; + +typedef struct _LIST_ENTRY32 +{ + DWORD Flink; + DWORD Blink; +} LIST_ENTRY32; + +typedef struct _PEB_LDR_DATA32 +{ + ULONG Length; + BOOLEAN Initialized; + DWORD SsHandle; + LIST_ENTRY32 InLoadOrderModuleList; +} PEB_LDR_DATA32; + +typedef struct _UNICODE_STRING32 +{ + USHORT Length; + USHORT MaximumLength; + DWORD Buffer; +} UNICODE_STRING32; + +typedef struct _LDR_MODULE32 +{ + LIST_ENTRY32 InLoadOrderModuleList; + LIST_ENTRY32 InMemoryOrderModuleList; + LIST_ENTRY32 InInitializationOrderModuleList; + DWORD BaseAddress; + DWORD EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING32 FullDllName; + UNICODE_STRING32 BaseDllName; +} LDR_MODULE32; + typedef struct { HANDLE process; PLIST_ENTRY head, current; LDR_MODULE ldr_module; + BOOL wow64; + LDR_MODULE32 ldr_module32; } MODULE_ITERATOR;
static BOOL init_module_iterator(MODULE_ITERATOR *iter, HANDLE process) @@ -1505,6 +1551,9 @@ static BOOL init_module_iterator(MODULE_ITERATOR *iter, HANDLE process) PPEB_LDR_DATA ldr_data; NTSTATUS status;
+ if (!IsWow64Process(process, &iter->wow64)) + return FALSE; + /* Get address of PEB */ status = NtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); @@ -1514,6 +1563,30 @@ static BOOL init_module_iterator(MODULE_ITERATOR *iter, HANDLE process) return FALSE; }
+ if (sizeof(void *) == 8 && iter->wow64) + { + PEB_LDR_DATA32 *ldr_data32_ptr; + DWORD ldr_data32, first_module; + PEB32 *peb32; + + peb32 = (PEB32 *)(DWORD_PTR)pbi.PebBaseAddress; + + if (!ReadProcessMemory(process, &peb32->LdrData, &ldr_data32, + sizeof(ldr_data32), NULL)) + return FALSE; + ldr_data32_ptr = (PEB_LDR_DATA32 *)(DWORD_PTR) ldr_data32; + + if (!ReadProcessMemory(process, + &ldr_data32_ptr->InLoadOrderModuleList.Flink, + &first_module, sizeof(first_module), NULL)) + return FALSE; + iter->head = (LIST_ENTRY *)&ldr_data32_ptr->InLoadOrderModuleList; + iter->current = (LIST_ENTRY *)(DWORD_PTR) first_module; + iter->process = process; + + return TRUE; + } + /* Read address of LdrData from PEB */ if (!ReadProcessMemory(process, &pbi.PebBaseAddress->LdrData, &ldr_data, sizeof(ldr_data), NULL)) @@ -1536,6 +1609,19 @@ static int module_iterator_next(MODULE_ITERATOR *iter) if (iter->current == iter->head) return 0;
+ if (sizeof(void *) == 8 && iter->wow64) + { + LIST_ENTRY32 *entry32 = (LIST_ENTRY32 *)iter->current; + + if (!ReadProcessMemory(iter->process, + CONTAINING_RECORD(entry32, LDR_MODULE32, InLoadOrderModuleList), + &iter->ldr_module32, sizeof(iter->ldr_module32), NULL)) + return -1; + + iter->current = (LIST_ENTRY *)(DWORD_PTR) iter->ldr_module32.InLoadOrderModuleList.Flink; + return 1; + } + if (!ReadProcessMemory(iter->process, CONTAINING_RECORD(iter->current, LDR_MODULE, InLoadOrderModuleList), &iter->ldr_module, sizeof(iter->ldr_module), NULL)) @@ -1594,7 +1680,10 @@ BOOL WINAPI K32EnumProcessModules(HANDLE process, HMODULE *lphModule, { if (cb >= sizeof(HMODULE)) { - *lphModule++ = iter.ldr_module.BaseAddress; + if (sizeof(void *) == 8 && iter.wow64) + *lphModule++ = (HMODULE) (DWORD_PTR)iter.ldr_module32.BaseAddress; + else + *lphModule++ = iter.ldr_module.BaseAddress; cb -= sizeof(HMODULE); } size += sizeof(HMODULE); diff --git a/dlls/psapi/tests/Makefile.in b/dlls/psapi/tests/Makefile.in index 535fb54..980ed0a 100644 --- a/dlls/psapi/tests/Makefile.in +++ b/dlls/psapi/tests/Makefile.in @@ -1,4 +1,5 @@ TESTDLL = psapi.dll +IMPORTS = user32
C_SRCS = \ psapi_main.c diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c index 8638d73..169f9b0 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c @@ -33,6 +33,7 @@ #include "winnt.h" #include "winternl.h" #include "winnls.h" +#include "winuser.h" #include "psapi.h" #include "wine/test.h"
@@ -62,6 +63,11 @@ static BOOL (WINAPI *pInitializeProcessForWsWatch)(HANDLE); static BOOL (WINAPI *pQueryWorkingSet)(HANDLE, PVOID, DWORD); static NTSTATUS (WINAPI *pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI *pNtQueryVirtualMemory)(HANDLE, LPCVOID, ULONG, PVOID, SIZE_T, SIZE_T *); +static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *); +static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(void **); +static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(void *); + +static BOOL wow64;
static BOOL InitFunctionPtrs(HMODULE hpsapi) { @@ -87,6 +93,9 @@ static BOOL InitFunctionPtrs(HMODULE hpsapi) (void *)GetProcAddress(hpsapi, "GetProcessImageFileNameW"); pNtQuerySystemInformation = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); pNtQueryVirtualMemory = (void *)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryVirtualMemory"); + pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); + pWow64DisableWow64FsRedirection = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "Wow64DisableWow64FsRedirection"); + pWow64RevertWow64FsRedirection = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "Wow64RevertWow64FsRedirection"); return TRUE; }
@@ -110,6 +119,10 @@ static void test_EnumProcesses(void)
static void test_EnumProcessModules(void) { + char buffer[200] = "C:\windows\system32\notepad.exe"; + PROCESS_INFORMATION pi = {0}; + STARTUPINFOA si = {0}; + void *cookie; HMODULE hMod; DWORD ret, cbNeeded = 0xdeadbeef;
@@ -151,6 +164,57 @@ static void test_EnumProcessModules(void) ok(hMod == GetModuleHandleA(NULL), "hMod=%p GetModuleHandleA(NULL)=%p\n", hMod, GetModuleHandleA(NULL)); ok(cbNeeded % sizeof(hMod) == 0, "not a multiple of sizeof(HMODULE) cbNeeded=%d\n", cbNeeded); + + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "CreateProcess failed: %u\n", GetLastError()); + + ret = WaitForInputIdle(pi.hProcess, 1000); + ok(!ret, "wait timed out\n"); + + SetLastError(0xdeadbeef); + hMod = NULL; + ret = pEnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); + ok(ret == 1, "got %d, error %u\n", ret, GetLastError()); + ok(!!hMod, "expeced non-NULL module\n"); + ok(cbNeeded % sizeof(hMod) == 0, "got %u\n", cbNeeded); + + TerminateProcess(pi.hProcess, 0); + + if (sizeof(void *) == 8) + { + strcpy(buffer, "C:\windows\syswow64\notepad.exe"); + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "CreateProcess failed: %u\n", GetLastError()); + + ret = WaitForInputIdle(pi.hProcess, 1000); + ok(!ret, "wait timed out\n"); + + SetLastError(0xdeadbeef); + hMod = NULL; + ret = pEnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); + ok(ret == 1, "got %d, error %u\n", ret, GetLastError()); + ok(!!hMod, "expeced non-NULL module\n"); + ok(cbNeeded % sizeof(hMod) == 0, "got %u\n", cbNeeded); + + TerminateProcess(pi.hProcess, 0); + } + else if (wow64) + { + pWow64DisableWow64FsRedirection(&cookie); + ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + pWow64RevertWow64FsRedirection(cookie); + ok(ret, "CreateProcess failed: %u\n", GetLastError()); + + ret = WaitForInputIdle(pi.hProcess, 1000); + ok(!ret, "wait timed out\n"); + + SetLastError(0xdeadbeef); + ret = pEnumProcessModules(pi.hProcess, &hMod, sizeof(HMODULE), &cbNeeded); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_PARTIAL_COPY, "got error %u\n", GetLastError()); + + TerminateProcess(pi.hProcess, 0); + } }
static void test_GetModuleInformation(void) @@ -781,6 +845,9 @@ START_TEST(psapi_main) { DWORD pid = GetCurrentProcessId();
+ if (pIsWow64Process) + IsWow64Process(GetCurrentProcess(), &wow64); + hpSR = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, pid); hpQI = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); hpVR = OpenProcess(PROCESS_VM_READ, FALSE, pid);
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/module.c | 52 ++++++++++++++++++++++++++++++++++++++----- dlls/psapi/tests/psapi_main.c | 6 +++++ 2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index ac1f45f..41080aa 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -1654,6 +1654,29 @@ static BOOL get_ldr_module(HANDLE process, HMODULE module, LDR_MODULE *ldr_modul return FALSE; }
+static BOOL get_ldr_module32(HANDLE process, HMODULE module, LDR_MODULE32 *ldr_module) +{ + MODULE_ITERATOR iter; + INT ret; + + if (!init_module_iterator(&iter, process)) + return FALSE; + + while ((ret = module_iterator_next(&iter)) > 0) + /* When hModule is NULL we return the process image - which will be + * the first module since our iterator uses InLoadOrderModuleList */ + if (!module || (DWORD)(DWORD_PTR) module == iter.ldr_module32.BaseAddress) + { + *ldr_module = iter.ldr_module32; + return TRUE; + } + + if (ret == 0) + SetLastError(ERROR_INVALID_HANDLE); + + return FALSE; +} + /*********************************************************************** * K32EnumProcessModules (KERNEL32.@) * @@ -1720,14 +1743,33 @@ DWORD WINAPI K32GetModuleBaseNameW(HANDLE process, HMODULE module, LPWSTR base_name, DWORD size) { LDR_MODULE ldr_module; + BOOL wow64;
- if (!get_ldr_module(process, module, &ldr_module)) + if (!IsWow64Process(process, &wow64)) return 0;
- size = min(ldr_module.BaseDllName.Length / sizeof(WCHAR), size); - if (!ReadProcessMemory(process, ldr_module.BaseDllName.Buffer, - base_name, size * sizeof(WCHAR), NULL)) - return 0; + if (sizeof(void *) == 8 && wow64) + { + LDR_MODULE32 ldr_module32; + + if (!get_ldr_module32(process, module, &ldr_module32)) + return 0; + + size = min(ldr_module32.BaseDllName.Length / sizeof(WCHAR), size); + if (!ReadProcessMemory(process, (void *)(DWORD_PTR)ldr_module32.BaseDllName.Buffer, + base_name, size * sizeof(WCHAR), NULL)) + return 0; + } + else + { + if (!get_ldr_module(process, module, &ldr_module)) + return 0; + + size = min(ldr_module.BaseDllName.Length / sizeof(WCHAR), size); + if (!ReadProcessMemory(process, ldr_module.BaseDllName.Buffer, + base_name, size * sizeof(WCHAR), NULL)) + return 0; + }
base_name[size] = 0; return size; diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c index 169f9b0..782fb6f 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c @@ -182,6 +182,8 @@ static void test_EnumProcessModules(void)
if (sizeof(void *) == 8) { + char name[40]; + strcpy(buffer, "C:\windows\syswow64\notepad.exe"); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ok(ret, "CreateProcess failed: %u\n", GetLastError()); @@ -196,6 +198,10 @@ static void test_EnumProcessModules(void) ok(!!hMod, "expeced non-NULL module\n"); ok(cbNeeded % sizeof(hMod) == 0, "got %u\n", cbNeeded);
+ ret = GetModuleBaseNameA(pi.hProcess, hMod, name, sizeof(name)); + ok(ret, "got error %u\n", GetLastError()); + ok(!strcmp(name, "notepad.exe"), "got %s\n", name); + TerminateProcess(pi.hProcess, 0); } else if (wow64)
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/module.c | 29 ++++++++++++++++++++++++----- dlls/psapi/tests/psapi_main.c | 5 +++++ 2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 41080aa..01d28a8 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -1812,17 +1812,36 @@ DWORD WINAPI K32GetModuleFileNameExW(HANDLE process, HMODULE module, LPWSTR file_name, DWORD size) { LDR_MODULE ldr_module; + BOOL wow64; DWORD len;
if (!size) return 0;
- if(!get_ldr_module(process, module, &ldr_module)) + if (!IsWow64Process(process, &wow64)) return 0;
- len = ldr_module.FullDllName.Length / sizeof(WCHAR); - if (!ReadProcessMemory(process, ldr_module.FullDllName.Buffer, - file_name, min( len, size ) * sizeof(WCHAR), NULL)) - return 0; + if (sizeof(void *) == 8 && wow64) + { + LDR_MODULE32 ldr_module32; + + if (!get_ldr_module32(process, module, &ldr_module32)) + return 0; + + len = ldr_module32.FullDllName.Length / sizeof(WCHAR); + if (!ReadProcessMemory(process, (void *)(DWORD_PTR)ldr_module32.FullDllName.Buffer, + file_name, min( len, size ) * sizeof(WCHAR), NULL)) + return 0; + } + else + { + if (!get_ldr_module(process, module, &ldr_module)) + return 0; + + len = ldr_module.FullDllName.Length / sizeof(WCHAR); + if (!ReadProcessMemory(process, ldr_module.FullDllName.Buffer, + file_name, min( len, size ) * sizeof(WCHAR), NULL)) + return 0; + }
if (len < size) { diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c index 782fb6f..8f65296 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c @@ -202,6 +202,11 @@ static void test_EnumProcessModules(void) ok(ret, "got error %u\n", GetLastError()); ok(!strcmp(name, "notepad.exe"), "got %s\n", name);
+ ret = GetModuleFileNameExA(pi.hProcess, hMod, name, sizeof(name)); + ok(ret, "got error %u\n", GetLastError()); +todo_wine + ok(!strcmp(name, buffer), "got %s\n", name); + TerminateProcess(pi.hProcess, 0); } else if (wow64)
Hi,
While running your changed tests on Windows, 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=38782
Your paranoid android.
=== wvistau64_zh_CN (32 bit psapi_main) === psapi_main.c:361: Test failed: expected approximately 8417 but got 8368
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernel32/module.c | 26 ++++++++++++++++++++++---- dlls/psapi/tests/psapi_main.c | 7 +++++++ 2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 01d28a8..3ab70e8 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -1907,6 +1907,7 @@ BOOL WINAPI K32GetModuleInformation(HANDLE process, HMODULE module, MODULEINFO *modinfo, DWORD cb) { LDR_MODULE ldr_module; + BOOL wow64;
if (cb < sizeof(MODULEINFO)) { @@ -1914,12 +1915,29 @@ BOOL WINAPI K32GetModuleInformation(HANDLE process, HMODULE module, return FALSE; }
- if (!get_ldr_module(process, module, &ldr_module)) + if (!IsWow64Process(process, &wow64)) return FALSE;
- modinfo->lpBaseOfDll = ldr_module.BaseAddress; - modinfo->SizeOfImage = ldr_module.SizeOfImage; - modinfo->EntryPoint = ldr_module.EntryPoint; + if (sizeof(void *) == 8 && wow64) + { + LDR_MODULE32 ldr_module32; + + if (!get_ldr_module32(process, module, &ldr_module32)) + return FALSE; + + modinfo->lpBaseOfDll = (void *)(DWORD_PTR)ldr_module32.BaseAddress; + modinfo->SizeOfImage = ldr_module32.SizeOfImage; + modinfo->EntryPoint = (void *)(DWORD_PTR)ldr_module32.EntryPoint; + } + else + { + if (!get_ldr_module(process, module, &ldr_module)) + return FALSE; + + modinfo->lpBaseOfDll = ldr_module.BaseAddress; + modinfo->SizeOfImage = ldr_module.SizeOfImage; + modinfo->EntryPoint = ldr_module.EntryPoint; + } return TRUE; }
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c index 8f65296..7e874a0 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c @@ -182,6 +182,7 @@ static void test_EnumProcessModules(void)
if (sizeof(void *) == 8) { + MODULEINFO info; char name[40];
strcpy(buffer, "C:\windows\syswow64\notepad.exe"); @@ -207,6 +208,12 @@ static void test_EnumProcessModules(void) todo_wine ok(!strcmp(name, buffer), "got %s\n", name);
+ ret = GetModuleInformation(pi.hProcess, hMod, &info, sizeof(info)); + ok(ret, "got error %u\n", GetLastError()); + ok(info.lpBaseOfDll == hMod, "expected %p, got %p\n", hMod, info.lpBaseOfDll); + ok(info.SizeOfImage, "image size was 0\n"); + ok(info.EntryPoint >= info.lpBaseOfDll, "got entry point %p\n", info.EntryPoint); + TerminateProcess(pi.hProcess, 0); } else if (wow64)
Hi,
While running your changed tests on Windows, 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=38780
Your paranoid android.
=== w2008s64 (64 bit psapi_main) === psapi_main.c:296: Test failed: expected approximately 149226 but got 149844