Zebediah Figura : kernel32: Allow EnumProcessModules() to succeed on a WoW64 process.
Alexandre Julliard
julliard at winehq.org
Wed May 30 15:30:51 CDT 2018
Module: wine
Branch: master
Commit: 54186a4c9f307fb59b9fe60042fe08af8de0bda4
URL: https://source.winehq.org/git/wine.git/?a=commit;h=54186a4c9f307fb59b9fe60042fe08af8de0bda4
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Tue May 29 09:33:03 2018 -0500
kernel32: Allow EnumProcessModules() to succeed on a WoW64 process.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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..3141490 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, "expected 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, "expected 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);
More information about the wine-cvs
mailing list