v2: Add tests.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
.../api-ms-win-core-wow64-l1-1-1.spec | 1 +
dlls/kernel32/kernel32.spec | 1 +
dlls/kernel32/tests/process.c | 114 ++++++++++++++++++
dlls/kernelbase/kernelbase.spec | 2 +-
dlls/kernelbase/process.c | 92 ++++++++++++++
include/winbase.h | 1 +
6 files changed, 210 insertions(+), 1 deletion(-)
diff --git a/dlls/api-ms-win-core-wow64-l1-1-1/api-ms-win-core-wow64-l1-1-1.spec b/dlls/api-ms-win-core-wow64-l1-1-1/api-ms-win-core-wow64-l1-1-1.spec
index 08fa02c3fc..99ba713409 100644
--- a/dlls/api-ms-win-core-wow64-l1-1-1/api-ms-win-core-wow64-l1-1-1.spec
+++ b/dlls/api-ms-win-core-wow64-l1-1-1/api-ms-win-core-wow64-l1-1-1.spec
@@ -1,5 +1,6 @@
@ stdcall GetSystemWow64DirectoryA(ptr long) kernel32.GetSystemWow64DirectoryA
@ stdcall GetSystemWow64DirectoryW(ptr long) kernel32.GetSystemWow64DirectoryW
@ stdcall IsWow64Process(ptr ptr) kernel32.IsWow64Process
+@ stdcall IsWow64Process2(ptr ptr ptr) kernel32.IsWow64Process2
@ stdcall Wow64DisableWow64FsRedirection(ptr) kernel32.Wow64DisableWow64FsRedirection
@ stdcall Wow64RevertWow64FsRedirection(ptr) kernel32.Wow64RevertWow64FsRedirection
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 17322bcd90..e7a7f162b7 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -999,6 +999,7 @@
@ stdcall -import IsValidNLSVersion(long wstr ptr)
# @ stub IsValidUILanguage
@ stdcall -import IsWow64Process(ptr ptr)
+@ stdcall -import IsWow64Process2(ptr ptr ptr)
@ stdcall -import K32EmptyWorkingSet(long)
@ stdcall -import K32EnumDeviceDrivers(ptr long ptr)
@ stdcall -import K32EnumPageFilesA(ptr ptr)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 82a5bdd85d..af585c4415 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -66,6 +66,7 @@ static HINSTANCE hkernel32, hntdll;
static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
+static BOOL (WINAPI *pIsWow64Process2)(HANDLE, USHORT *, USHORT *);
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
@@ -249,6 +250,7 @@ static BOOL init(void)
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
+ pIsWow64Process2 = (void *) GetProcAddress(hkernel32, "IsWow64Process2");
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
@@ -2166,6 +2168,117 @@ static void test_IsWow64Process(void)
}
}
+static void test_IsWow64Process2(void)
+{
+ PROCESS_INFORMATION pi;
+ STARTUPINFOA si;
+ BOOL ret, is_wow64, is_win64;
+ USHORT machine, native_machine;
+ static char cmdline[] = "C:\\Program Files\\Internet Explorer\\iexplore.exe";
+ static char cmdline_wow64[] = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
+
+ if (!pIsWow64Process2)
+ {
+ skip("IsWow64Process2 is not available\n");
+ return;
+ }
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ SetLastError(0xdeadbeef);
+ ret = CreateProcessA(cmdline_wow64, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
+ if (ret)
+ {
+ is_win64 = TRUE;
+
+ SetLastError(0xdeadbeef);
+ machine = native_machine = 0xdead;
+ ret = pIsWow64Process2(pi.hProcess, &machine, &native_machine);
+ ok(ret, "IsWow64Process2 error %u\n", GetLastError());
+
+#if defined(__i386__) || defined(__x86_64__)
+ ok(machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", machine);
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+#else
+ skip("not supportted architecture\n");
+#endif
+
+ ret = TerminateProcess(pi.hProcess, 0);
+ ok(ret, "TerminateProcess error\n");
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+ else
+ is_win64 = FALSE;
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ SetLastError(0xdeadbeef);
+ ret = CreateProcessA(cmdline, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
+ ok(ret, "CreateProcess error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pIsWow64Process(pi.hProcess, &is_wow64);
+ ok(ret, "IsWow64Process error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ machine = native_machine = 0xdead;
+ ret = pIsWow64Process2(pi.hProcess, &machine, &native_machine);
+ ok(ret, "IsWow64Process2 error %u\n", GetLastError());
+
+ ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
+#ifdef __i386__
+ if (is_win64)
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+ else
+ ok(native_machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", native_machine);
+#elif defined __x86_64__
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+#else
+ skip("not supportted architecture\n");
+#endif
+
+ ret = TerminateProcess(pi.hProcess, 0);
+ ok(ret, "TerminateProcess error\n");
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ SetLastError(0xdeadbeef);
+ ret = pIsWow64Process(GetCurrentProcess(), &is_wow64);
+ ok(ret, "IsWow64Process error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ machine = native_machine = 0xdead;
+ ret = pIsWow64Process2(GetCurrentProcess(), &machine, &native_machine);
+ ok(ret, "IsWow64Process2 error %u\n", GetLastError());
+
+ if (is_wow64)
+ {
+#if defined(__i386__) || defined(__x86_64__)
+ ok(machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", machine);
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+#else
+ skip("not supportted architecture\n");
+#endif
+ }
+ else
+ {
+ ok(machine == IMAGE_FILE_MACHINE_UNKNOWN, "got %#x\n", machine);
+#ifdef __i386__
+ if (is_win64)
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+ else
+ ok(native_machine == IMAGE_FILE_MACHINE_I386, "got %#x\n", native_machine);
+#elif defined __x86_64__
+ ok(native_machine == IMAGE_FILE_MACHINE_AMD64, "got %#x\n", native_machine);
+#else
+ skip("not supportted architecture\n");
+#endif
+ }
+}
+
static void test_SystemInfo(void)
{
SYSTEM_INFO si, nsi;
@@ -4065,6 +4178,7 @@ START_TEST(process)
test_QueryFullProcessImageNameW();
test_Handles();
test_IsWow64Process();
+ test_IsWow64Process2();
test_SystemInfo();
test_RegistryQuota();
test_DuplicateHandle();
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 5e177a4932..a05bf223e8 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -884,7 +884,7 @@
@ stdcall IsValidSid(ptr)
@ stdcall IsWellKnownSid(ptr long)
@ stdcall IsWow64Process(ptr ptr)
-# @ stub IsWow64Process2
+@ stdcall IsWow64Process2(ptr ptr ptr)
@ stdcall K32EmptyWorkingSet(long)
@ stdcall K32EnumDeviceDrivers(ptr long ptr)
@ stdcall K32EnumPageFilesA(ptr ptr)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c
index a3b168543f..1076e2ea82 100644
--- a/dlls/kernelbase/process.c
+++ b/dlls/kernelbase/process.c
@@ -24,6 +24,7 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
@@ -882,6 +883,97 @@ BOOL WINAPI DECLSPEC_HOTPATCH IsProcessorFeaturePresent ( DWORD feature )
}
+/**********************************************************************
+ * IsWow64Process2 (kernelbase.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process2( HANDLE process, USHORT *machine, USHORT *native_machine )
+{
+ BOOL wow64;
+ SYSTEM_INFO si;
+
+ TRACE( "(%p,%p,%p)\n", process, machine, native_machine );
+
+ if (!IsWow64Process( process, &wow64 ))
+ return FALSE;
+
+ if (wow64)
+ {
+ GetNativeSystemInfo( &si );
+
+ if (process != GetCurrentProcess())
+ {
+#if defined(__i386__) || defined(__x86_64__)
+ *machine = IMAGE_FILE_MACHINE_I386;
+#else
+ FIXME("not implemented for other process\n");
+ *machine = IMAGE_FILE_MACHINE_UNKNOWN;
+#endif
+ }
+ else
+ {
+ IMAGE_NT_HEADERS *nt;
+ nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
+ *machine = nt->FileHeader.Machine;
+ }
+ }
+ else
+ {
+#ifdef _WIN64
+ GetSystemInfo( &si );
+#else
+ GetNativeSystemInfo( &si );
+#endif
+ *machine = IMAGE_FILE_MACHINE_UNKNOWN;
+ }
+
+ switch (si.u.s.wProcessorArchitecture)
+ {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ *native_machine = IMAGE_FILE_MACHINE_I386;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_ALPHA:
+ *native_machine = IMAGE_FILE_MACHINE_ALPHA;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_ARM:
+ *native_machine = IMAGE_FILE_MACHINE_ARM;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_IA64:
+ *native_machine = IMAGE_FILE_MACHINE_IA64;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_ALPHA64:
+ *native_machine = IMAGE_FILE_MACHINE_ALPHA64;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ *native_machine = IMAGE_FILE_MACHINE_AMD64;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ *native_machine = IMAGE_FILE_MACHINE_ARM64;
+ break;
+
+ case PROCESSOR_ARCHITECTURE_MIPS:
+ case PROCESSOR_ARCHITECTURE_PPC:
+ case PROCESSOR_ARCHITECTURE_SHX:
+ case PROCESSOR_ARCHITECTURE_MSIL:
+ case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
+ case PROCESSOR_ARCHITECTURE_NEUTRAL:
+ case PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64:
+ case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64:
+ default:
+ FIXME("unknown architecture %u\n", si.u.s.wProcessorArchitecture);
+ *native_machine = IMAGE_FILE_MACHINE_UNKNOWN;
+ break;
+ }
+
+ return TRUE;
+}
+
+
/**********************************************************************
* IsWow64Process (kernelbase.@)
*/
diff --git a/include/winbase.h b/include/winbase.h
index 39a4a9c9ac..981d4ea76a 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2406,6 +2406,7 @@ WINADVAPI BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
WINADVAPI BOOL WINAPI IsValidSid(PSID);
WINADVAPI BOOL WINAPI IsWellKnownSid(PSID,WELL_KNOWN_SID_TYPE);
WINBASEAPI BOOL WINAPI IsWow64Process(HANDLE,PBOOL);
+WINBASEAPI BOOL WINAPI IsWow64Process2(HANDLE,USHORT*,USHORT*);
WINADVAPI BOOL WINAPI ImpersonateLoggedOnUser(HANDLE);
WINADVAPI BOOL WINAPI ImpersonateNamedPipeClient(HANDLE);
WINADVAPI BOOL WINAPI ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL);
--
2.26.2