ntdll: Implement RtlWow64GetCpuAreaInfo().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-05-12 15:30:41 +02:00
parent 7a25671c38
commit e97a2c4c0f
4 changed files with 114 additions and 5 deletions

View File

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

View File

@ -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.@)
*/

View File

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

View File

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