diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 6f123ca2197..ac1f45f9bbc 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 535fb54bac8..980ed0a36bf 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 8638d73e7e7..31414902bbb 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);