Alexandre Julliard : ntdll: Implement RtlWow64GetCpuAreaInfo().

Alexandre Julliard julliard at winehq.org
Wed May 12 15:44:28 CDT 2021


Module: wine
Branch: master
Commit: e97a2c4c0f330ac1a523ca42573ba93bcc295710
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e97a2c4c0f330ac1a523ca42573ba93bcc295710

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed May 12 15:30:41 2021 +0200

ntdll: Implement RtlWow64GetCpuAreaInfo().

Signed-off-by: Alexandre Julliard <julliard at 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**);




More information about the wine-cvs mailing list