kernel32: Allow EnumProcessModules() to succeed on a WoW64 process.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2018-05-29 09:33:03 -05:00 committed by Alexandre Julliard
parent 4303464475
commit 54186a4c9f
3 changed files with 158 additions and 1 deletions

View File

@ -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);

View File

@ -1,4 +1,5 @@
TESTDLL = psapi.dll
IMPORTS = user32
C_SRCS = \
psapi_main.c

View File

@ -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);