Module: wine Branch: master Commit: e97a2c4c0f330ac1a523ca42573ba93bcc295710 URL: https://source.winehq.org/git/wine.git/?a=commit;h=e97a2c4c0f330ac1a523ca425...
Author: Alexandre Julliard julliard@winehq.org Date: Wed May 12 15:30:41 2021 +0200
ntdll: Implement RtlWow64GetCpuAreaInfo().
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/process.c | 36 +++++++++++++++++++++++++++++++++ dlls/ntdll/tests/info.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- include/winternl.h | 29 +++++++++++++++++++++++---- 4 files changed, 114 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 05712d842c4..06ca3d3957c 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1070,6 +1070,7 @@ @ stdcall RtlWalkHeap(long ptr) @ stdcall RtlWow64EnableFsRedirection(long) @ stdcall RtlWow64EnableFsRedirectionEx(long ptr) +@ stdcall -arch=win64 RtlWow64GetCpuAreaInfo(ptr long ptr) @ stdcall RtlWow64GetCurrentMachine() @ stdcall RtlWow64GetProcessMachines(long ptr ptr) @ stdcall -arch=x86_64 RtlWow64GetThreadContext(long ptr) diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index dbb94cfb8b7..82b1b69c4ea 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -108,6 +108,42 @@ NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported( USHORT machine, BOOLEAN *sup }
+#ifdef _WIN64 + +/********************************************************************** + * RtlWow64GetCpuAreaInfo (NTDLL.@) + */ +NTSTATUS WINAPI RtlWow64GetCpuAreaInfo( WOW64_CPURESERVED *cpu, ULONG reserved, WOW64_CPU_AREA_INFO *info ) +{ + static const struct { ULONG machine, align, size, offset, flag; } data[] = + { +#define ENTRY(machine,type,flag) { machine, TYPE_ALIGNMENT(type), sizeof(type), offsetof(type,ContextFlags), flag }, + ENTRY( IMAGE_FILE_MACHINE_I386, I386_CONTEXT, CONTEXT_i386 ) + ENTRY( IMAGE_FILE_MACHINE_AMD64, AMD64_CONTEXT, CONTEXT_AMD64 ) + ENTRY( IMAGE_FILE_MACHINE_ARMNT, ARM_CONTEXT, CONTEXT_ARM ) + ENTRY( IMAGE_FILE_MACHINE_ARM64, ARM64_NT_CONTEXT, CONTEXT_ARM64 ) +#undef ENTRY + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(data); i++) + { +#define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((align) - 1))) + if (data[i].machine != cpu->Machine) continue; + info->Context = ALIGN( cpu + 1, data[i].align ); + info->ContextEx = ALIGN( (char *)info->Context + data[i].size, sizeof(void *) ); + info->ContextFlagsLocation = (char *)info->Context + data[i].offset; + info->ContextFlag = data[i].flag; + info->CpuReserved = cpu; + info->Machine = data[i].machine; + return STATUS_SUCCESS; +#undef ALIGN + } + return STATUS_INVALID_PARAMETER; +} + +#endif + /********************************************************************** * RtlCreateUserProcess (NTDLL.@) */ diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 1c1722ee392..bca2086fee9 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -25,6 +25,7 @@ static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG); static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); +static NTSTATUS (WINAPI * pRtlWow64GetCpuAreaInfo)( WOW64_CPURESERVED *cpu, ULONG reserved, WOW64_CPU_AREA_INFO *info ); static USHORT (WINAPI * pRtlWow64GetCurrentMachine)(void); static NTSTATUS (WINAPI * pRtlWow64GetProcessMachines)(HANDLE,WORD*,WORD*); static NTSTATUS (WINAPI * pRtlWow64IsWowGuestMachineSupported)(USHORT,BOOLEAN*); @@ -85,6 +86,7 @@ static BOOL InitFunctionPtrs(void) NTDLL_GET_PROC(NtQuerySystemInformation); NTDLL_GET_PROC(NtSetSystemInformation); NTDLL_GET_PROC(RtlGetNativeSystemInformation); + NTDLL_GET_PROC(RtlWow64GetCpuAreaInfo); NTDLL_GET_PROC(RtlWow64GetCurrentMachine); NTDLL_GET_PROC(RtlWow64GetProcessMachines); NTDLL_GET_PROC(RtlWow64IsWowGuestMachineSupported); @@ -3133,7 +3135,56 @@ static void test_thread_info(void)
static void test_wow64(void) { -#ifndef _WIN64 +#ifdef _WIN64 + if (pRtlWow64GetCpuAreaInfo) + { + static const struct + { + USHORT machine; + NTSTATUS expect; + ULONG align, size, offset, flag; + } tests[] = + { + { IMAGE_FILE_MACHINE_I386, 0, 4, 0x2cc, 0x00, 0x00010000 }, + { IMAGE_FILE_MACHINE_AMD64, 0, 16, 0x4d0, 0x30, 0x00100000 }, + { IMAGE_FILE_MACHINE_ARMNT, 0, 8, 0x1a0, 0x00, 0x00200000 }, + { IMAGE_FILE_MACHINE_ARM64, 0, 16, 0x390, 0x00, 0x00400000 }, + { IMAGE_FILE_MACHINE_ARM, STATUS_INVALID_PARAMETER }, + { IMAGE_FILE_MACHINE_THUMB, STATUS_INVALID_PARAMETER }, + }; + USHORT buffer[2048]; + WOW64_CPURESERVED *cpu; + WOW64_CPU_AREA_INFO info; + ULONG i, j; + NTSTATUS status; +#define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((align) - 1))) + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + for (j = 0; j < 8; j++) + { + cpu = (WOW64_CPURESERVED *)(buffer + j); + cpu->Flags = 0; + cpu->Machine = tests[i].machine; + status = pRtlWow64GetCpuAreaInfo( cpu, 0, &info ); + ok( status == tests[i].expect, "%u:%u: failed %x\n", i, j, status ); + if (status) continue; + ok( info.Context == ALIGN( cpu + 1, tests[i].align ), "%u:%u: wrong offset %u\n", + i, j, (ULONG)((char *)info.Context - (char *)cpu) ); + ok( info.ContextEx == ALIGN( (char *)info.Context + tests[i].size, sizeof(void*) ), + "%u:%u: wrong ex offset %u\n", i, j, (ULONG)((char *)info.ContextEx - (char *)cpu) ); + ok( info.ContextFlagsLocation == (char *)info.Context + tests[i].offset, + "%u:%u: wrong flags offset %u\n", + i, j, (ULONG)((char *)info.ContextFlagsLocation - (char *)info.Context) ); + ok( info.CpuReserved == cpu, "%u:%u: wrong cpu %p / %p\n", info.CpuReserved, cpu ); + ok( info.ContextFlag == tests[i].flag, "%u:%u: wrong flag %08x\n", i, j, info.ContextFlag ); + ok( info.Machine == tests[i].machine, "%u:%u: wrong machine %x\n", i, j, info.Machine ); + } + } +#undef ALIGN + } + else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" ); +#else if (is_wow64) { PEB64 *peb64; diff --git a/include/winternl.h b/include/winternl.h index 1839f4a0151..c9868fb5e39 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3588,6 +3588,25 @@ typedef enum _DEBUGOBJECTINFOCLASS MaxDebugObjectInfoClass } DEBUGOBJECTINFOCLASS, *PDEBUGOBJECTINFOCLASS;
+ +typedef struct _WOW64_CPURESERVED +{ + USHORT Flags; + USHORT Machine; + /* CONTEXT context */ + /* CONTEXT_EX *context_ex */ +} WOW64_CPURESERVED, *PWOW64_CPURESERVED; + +typedef struct _WOW64_CPU_AREA_INFO +{ + void *Context; + void *ContextEx; + void *ContextFlagsLocation; + WOW64_CPURESERVED *CpuReserved; + ULONG ContextFlag; + USHORT Machine; +} WOW64_CPU_AREA_INFO, *PWOW64_CPU_AREA_INFO; + /*********************************************************************** * Function declarations */ @@ -4249,10 +4268,6 @@ NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*); NTSYSAPI USHORT WINAPI RtlWow64GetCurrentMachine(void); NTSYSAPI NTSTATUS WINAPI RtlWow64GetProcessMachines(HANDLE,USHORT*,USHORT*); -#ifdef __x86_64__ -NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE, WOW64_CONTEXT *); -NTSYSAPI NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE, const WOW64_CONTEXT *); -#endif NTSYSAPI NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported(USHORT,BOOLEAN*); NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE); @@ -4263,6 +4278,12 @@ NTSYSAPI NTSTATUS WINAPI RtlpUnWaitCriticalSection(RTL_CRITICAL_SECTION *); NTSYSAPI NTSTATUS WINAPI vDbgPrintEx(ULONG,ULONG,LPCSTR,__ms_va_list); NTSYSAPI NTSTATUS WINAPI vDbgPrintExWithPrefix(LPCSTR,ULONG,ULONG,LPCSTR,__ms_va_list);
+#ifdef _WIN64 +NTSYSAPI NTSTATUS WINAPI RtlWow64GetCpuAreaInfo(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*); +NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE,WOW64_CONTEXT*); +NTSYSAPI NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE,const WOW64_CONTEXT*); +#endif + #if defined(__x86_64__) || defined(__i386__) NTSYSAPI NTSTATUS WINAPI RtlCopyExtendedContext(CONTEXT_EX*,ULONG,CONTEXT_EX*); NTSYSAPI NTSTATUS WINAPI RtlInitializeExtendedContext(void*,ULONG,CONTEXT_EX**);