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:
parent
4303464475
commit
54186a4c9f
|
@ -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);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
TESTDLL = psapi.dll
|
||||
IMPORTS = user32
|
||||
|
||||
C_SRCS = \
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue