[PATCH 2/4] kernel32: Implement GetXStateFeaturesMask().

Paul Gofman pgofman at codeweavers.com
Tue Sep 1 04:21:44 CDT 2020


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 .../api-ms-win-core-xstate-l1-1-0.spec        |  2 +-
 .../api-ms-win-core-xstate-l2-1-0.spec        |  2 +-
 dlls/kernel32/kernel32.spec                   |  1 +
 dlls/kernelbase/kernelbase.spec               |  2 +-
 dlls/kernelbase/memory.c                      | 34 +++++++++++++
 dlls/ntdll/exception.c                        | 11 +++++
 dlls/ntdll/ntdll.spec                         |  1 +
 dlls/ntdll/tests/exception.c                  | 48 ++++++++++++++++++-
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec           |  1 +
 include/ddk/wdm.h                             |  1 +
 include/winbase.h                             |  1 +
 11 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/dlls/api-ms-win-core-xstate-l1-1-0/api-ms-win-core-xstate-l1-1-0.spec b/dlls/api-ms-win-core-xstate-l1-1-0/api-ms-win-core-xstate-l1-1-0.spec
index 0a29d660112..4abed7d3252 100644
--- a/dlls/api-ms-win-core-xstate-l1-1-0/api-ms-win-core-xstate-l1-1-0.spec
+++ b/dlls/api-ms-win-core-xstate-l1-1-0/api-ms-win-core-xstate-l1-1-0.spec
@@ -1,7 +1,7 @@
 @ stub RtlCopyExtendedContext
 @ stdcall RtlGetEnabledExtendedFeatures(int64) ntdll.RtlGetEnabledExtendedFeatures
 @ stdcall RtlGetExtendedContextLength(long ptr) ntdll.RtlGetExtendedContextLength
-@ stub RtlGetExtendedFeaturesMask
+@ stdcall RtlGetExtendedFeaturesMask(ptr) ntdll.RtlGetExtendedFeaturesMask
 @ stdcall RtlInitializeExtendedContext(ptr long ptr) ntdll.RtlInitializeExtendedContext
 @ stdcall RtlLocateExtendedFeature(ptr long ptr) ntdll.RtlLocateExtendedFeature
 @ stdcall RtlLocateLegacyContext(ptr ptr) ntdll.RtlLocateLegacyContext
diff --git a/dlls/api-ms-win-core-xstate-l2-1-0/api-ms-win-core-xstate-l2-1-0.spec b/dlls/api-ms-win-core-xstate-l2-1-0/api-ms-win-core-xstate-l2-1-0.spec
index 74aafa4db1c..9c804b28864 100644
--- a/dlls/api-ms-win-core-xstate-l2-1-0/api-ms-win-core-xstate-l2-1-0.spec
+++ b/dlls/api-ms-win-core-xstate-l2-1-0/api-ms-win-core-xstate-l2-1-0.spec
@@ -1,6 +1,6 @@
 @ stub CopyContext
 @ stdcall -ret64 -arch=i386,x86_64 GetEnabledXStateFeatures() kernel32.GetEnabledXStateFeatures
-@ stub GetXStateFeaturesMask
+@ stdcall -arch=i386,x86_64 GetXStateFeaturesMask(ptr ptr) kernel32.GetXStateFeaturesMask
 @ stdcall -arch=i386,x86_64 InitializeContext(ptr long ptr ptr) kernel32.InitializeContext
 @ stdcall -arch=i386,x86_64 LocateXStateFeature(ptr long ptr) kernel32.LocateXStateFeature
 @ stdcall -arch=i386,x86_64 SetXStateFeaturesMask(ptr int64) kernel32.SetXStateFeaturesMask
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 4bcda92bf7f..d357d32c23e 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -895,6 +895,7 @@
 @ stdcall -import GetWindowsDirectoryA(ptr long)
 @ stdcall -import GetWindowsDirectoryW(ptr long)
 @ stdcall -import GetWriteWatch(long ptr long ptr ptr ptr)
+@ stdcall -import -arch=i386,x86_64 GetXStateFeaturesMask(ptr ptr)
 @ stdcall -import -arch=i386,x86_64 SetXStateFeaturesMask(ptr int64)
 @ stdcall GlobalAddAtomA(str)
 @ stdcall GlobalAddAtomW(wstr)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index d2832600091..e8e974d9c15 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -766,7 +766,7 @@
 @ stdcall GetWriteWatch(long ptr long ptr ptr ptr)
 # @ stub GetWsChanges
 # @ stub GetWsChangesEx
-# @ stub GetXStateFeaturesMask
+@ stdcall -arch=i386,x86_64 GetXStateFeaturesMask(ptr ptr)
 @ stdcall GlobalAlloc(long long)
 @ stdcall GlobalFree(long)
 @ stdcall GlobalMemoryStatusEx(ptr)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index f99b908494b..38aa2c78410 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -1280,6 +1280,23 @@ BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
     RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
     return TRUE;
 }
+
+/***********************************************************************
+ *           GetXStateFeaturesMask (kernelbase.@)
+ */
+BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
+{
+    if (!(context->ContextFlags & CONTEXT_AMD64))
+        return FALSE;
+
+    *feature_mask = (context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT
+            ? 3 : 0;
+
+    if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
+        *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
+
+    return TRUE;
+}
 #elif defined(__i386__)
 /***********************************************************************
  *           LocateXStateFeature   (kernelbase.@)
@@ -1324,6 +1341,23 @@ BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
     RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
     return TRUE;
 }
+
+/***********************************************************************
+ *           GetXStateFeaturesMask (kernelbase.@)
+ */
+BOOL WINAPI GetXStateFeaturesMask( CONTEXT *context, DWORD64 *feature_mask )
+{
+    if (!(context->ContextFlags & CONTEXT_X86))
+        return FALSE;
+
+    *feature_mask = (context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS
+            ? 3 : 0;
+
+    if ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
+        *feature_mask |= RtlGetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1) );
+
+    return TRUE;
+}
 #endif
 
 /***********************************************************************
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 6ca22d6660f..e022e2c2cd1 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -871,3 +871,14 @@ void WINAPI RtlSetExtendedFeaturesMask( CONTEXT_EX *context_ex, ULONG64 feature_
 
     xs->Mask = RtlGetEnabledExtendedFeatures( feature_mask ) & ~(ULONG64)3;
 }
+
+
+/**********************************************************************
+ *              RtlGetExtendedFeaturesMask  (NTDLL.@)
+ */
+ULONG64 WINAPI RtlGetExtendedFeaturesMask( CONTEXT_EX *context_ex )
+{
+    XSTATE *xs = (XSTATE *)((BYTE *)context_ex + context_ex->XState.Offset);
+
+    return xs->Mask & ~(ULONG64)3;
+}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 0e17d29ed1b..c7083e0299c 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -697,6 +697,7 @@
 @ stdcall RtlGetExePath(wstr ptr)
 @ stdcall RtlGetExtendedContextLength(long ptr)
 @ stdcall RtlGetExtendedContextLength2(long ptr int64)
+@ stdcall -ret64 RtlGetExtendedFeaturesMask(ptr)
 # @ stub RtlGetFirstRange
 @ stdcall RtlGetFrame()
 @ stdcall RtlGetFullPathName_U(wstr long ptr ptr)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 7b6c65f8572..5d0857476ea 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -54,6 +54,7 @@ static NTSTATUS  (WINAPI *pRtlInitializeExtendedContext2)(void *context, ULONG c
 static void *    (WINAPI *pRtlLocateExtendedFeature)(CONTEXT_EX *context_ex, ULONG feature_id, ULONG *length);
 static void *    (WINAPI *pRtlLocateLegacyContext)(CONTEXT_EX *context_ex, ULONG *length);
 static void      (WINAPI *pRtlSetExtendedFeaturesMask)(CONTEXT_EX *context_ex, ULONG64 feature_mask);
+static ULONG64   (WINAPI *pRtlGetExtendedFeaturesMask)(CONTEXT_EX *context_ex);
 static NTSTATUS  (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
 static NTSTATUS  (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code);
 static NTSTATUS  (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
@@ -69,6 +70,7 @@ static BOOL      (WINAPI *pInitializeContext2)(void *buffer, DWORD context_flags
         DWORD *length, ULONG64 compaction_mask);
 static void *    (WINAPI *pLocateXStateFeature)(CONTEXT *context, DWORD feature_id, DWORD *length);
 static BOOL      (WINAPI *pSetXStateFeaturesMask)(CONTEXT *context, DWORD64 feature_mask);
+static BOOL      (WINAPI *pGetXStateFeaturesMask)(CONTEXT *context, DWORD64 *feature_mask);
 
 #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
 
@@ -6235,6 +6237,7 @@ static void test_extended_context(void)
     ULONG flags, flags_fpx;
     CONTEXT *context;
     unsigned data[8];
+    ULONG64 mask;
     XSTATE *xs;
     BOOL bret;
     void *p;
@@ -6364,14 +6367,29 @@ static void test_extended_context(void)
             if (0)
             {
                 /* Crashes on Windows. */
+                pGetXStateFeaturesMask(context, NULL);
+                pRtlGetExtendedFeaturesMask(context_ex);
                 pRtlSetExtendedFeaturesMask(context_ex, 0);
             }
+
+            flags_fpx = flags & 0x10000 ? flags | 0x20 : flags | 0x8;
+
+            mask = 0xdeadbeef;
+            bret = pGetXStateFeaturesMask(context, &mask);
+            SetLastError(0xdeadbeef);
+            if (flags & CONTEXT_NATIVE)
+                ok(bret && mask == ((flags & flags_fpx) == flags_fpx ? 0x3 : 0),
+                        "Got unexpected bret %#x, mask %s, flags %#x.\n", bret, wine_dbgstr_longlong(mask), flags);
+            else
+                ok(!bret && mask == 0xdeadbeef && GetLastError() == 0xdeadbeef,
+                        "Got unexpected bret %#x, mask %s, GetLastError() %#x, flags %#x.\n",
+                        bret, wine_dbgstr_longlong(mask), GetLastError(), flags);
+
             bret = pSetXStateFeaturesMask(context, 0);
             ok(bret == !!(flags & CONTEXT_NATIVE), "Got unexpected bret %#x, flags %#x.\n", bret, flags);
             context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
             ok(context_flags == flags, "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags);
 
-            flags_fpx = flags & 0x10000 ? flags | 0x20 : flags | 0x8;
             bret = pSetXStateFeaturesMask(context, 1);
             ok(bret == !!(flags & CONTEXT_NATIVE), "Got unexpected bret %#x, flags %#x.\n", bret, flags);
             context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
@@ -6662,8 +6680,19 @@ static void test_extended_context(void)
         else
             ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
 
+        mask = 0xdeadbeef;
+        bret = pGetXStateFeaturesMask(context, &mask);
+        if (flags & CONTEXT_NATIVE)
+            ok(bret && !mask,
+                    "Got unexpected bret %#x, mask %s, flags %#x.\n", bret, wine_dbgstr_longlong(mask), flags);
+        else
+            ok(!bret && mask == 0xdeadbeef,
+                    "Got unexpected bret %#x, mask %s, flags %#x.\n", bret, wine_dbgstr_longlong(mask), flags);
+
         expected_compaction = compaction_enabled ? ((ULONG64)1 << 63) | enabled_features : 0;
         ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+        mask = pRtlGetExtendedFeaturesMask(context_ex);
+        ok(mask == (xs->Mask & ~(ULONG64)3), "Got unexpected mask %s.\n", wine_dbgstr_longlong(mask));
         ok(xs->CompactionMask == expected_compaction,
                 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask));
         ok(!xs->Reserved[0], "Got unexpected Reserved[0]  %s.\n", wine_dbgstr_longlong(xs->Reserved[0]));
@@ -6672,6 +6701,8 @@ static void test_extended_context(void)
         xs->CompactionMask = 0xdeadbeef;
         pRtlSetExtendedFeaturesMask(context_ex, 0);
         ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+        mask = pRtlGetExtendedFeaturesMask(context_ex);
+        ok(mask == (xs->Mask & ~(ULONG64)3), "Got unexpected mask %s.\n", wine_dbgstr_longlong(mask));
         ok(xs->CompactionMask == 0xdeadbeef, "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask));
         context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
         ok(context_flags == flags, "Got unexpected ContextFlags %#x, flags %#x.\n", context->ContextFlags, flags);
@@ -6680,6 +6711,8 @@ static void test_extended_context(void)
         xs->CompactionMask = 0;
         pRtlSetExtendedFeaturesMask(context_ex, ~(ULONG64)0);
         ok(xs->Mask == (enabled_features & ~(ULONG64)3), "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+        mask = pRtlGetExtendedFeaturesMask(context_ex);
+        ok(mask == (xs->Mask & ~(ULONG64)3), "Got unexpected mask %s.\n", wine_dbgstr_longlong(mask));
         ok(!xs->CompactionMask, "Got unexpected CompactionMask %s.\n",
                 wine_dbgstr_longlong(xs->CompactionMask));
         context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
@@ -6693,9 +6726,20 @@ static void test_extended_context(void)
         ok(context_flags == (bret ? flags_fpx : flags),
                 "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags);
         ok(xs->Mask == bret ? 4 : 0xdeadbeef, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+        mask = pRtlGetExtendedFeaturesMask(context_ex);
+        ok(mask == (xs->Mask & ~(ULONG64)3), "Got unexpected mask %s.\n", wine_dbgstr_longlong(mask));
         ok(xs->CompactionMask == bret ? expected_compaction : 0xdeadbeef, "Got unexpected CompactionMask %s.\n",
                 wine_dbgstr_longlong(xs->CompactionMask));
 
+        mask = 0xdeadbeef;
+        bret = pGetXStateFeaturesMask(context, &mask);
+        if (flags & CONTEXT_NATIVE)
+            ok(bret && mask == enabled_features,
+                    "Got unexpected bret %#x, mask %s, flags %#x.\n", bret, wine_dbgstr_longlong(mask), flags);
+        else
+            ok(!bret && mask == 0xdeadbeef,
+                    "Got unexpected bret %#x, mask %s, flags %#x.\n", bret, wine_dbgstr_longlong(mask), flags);
+
         if (pRtlGetExtendedContextLength2)
         {
             memset(context_buffer, 0xcc, sizeof(context_buffer));
@@ -6858,6 +6902,7 @@ START_TEST(exception)
     X(RtlLocateExtendedFeature);
     X(RtlLocateLegacyContext);
     X(RtlSetExtendedFeaturesMask);
+    X(RtlGetExtendedFeaturesMask);
 #undef X
 
 #define X(f) p##f = (void*)GetProcAddress(hkernel32, #f)
@@ -6868,6 +6913,7 @@ START_TEST(exception)
     X(InitializeContext2);
     X(LocateXStateFeature);
     X(SetXStateFeaturesMask);
+    X(GetXStateFeaturesMask);
 #undef X
 
     if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index ffd8f7dcd4c..ed09ffcd924 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1235,6 +1235,7 @@
 @ stdcall RtlSetBits(ptr long long)
 @ stdcall RtlSetControlSecurityDescriptor(ptr long long)
 @ stdcall RtlSetDaclSecurityDescriptor(ptr long ptr long)
+@ stdcall -ret64 RtlGetExtendedFeaturesMask(ptr)
 @ stdcall RtlSetExtendedFeaturesMask(ptr int64)
 @ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long)
 @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 3938645da94..60f926d7c5a 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1845,6 +1845,7 @@ NTSTATUS  WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,ULONG64);
 void *    WINAPI RtlLocateLegacyContext(CONTEXT_EX*,ULONG*);
 void *    WINAPI RtlLocateExtendedFeature(CONTEXT_EX*,ULONG,ULONG*);
 void *    WINAPI RtlLocateExtendedFeature2(CONTEXT_EX*,ULONG,XSTATE_CONFIGURATION*,ULONG*);
+ULONG64   WINAPI RtlGetExtendedFeaturesMask(CONTEXT_EX*);
 void      WINAPI RtlSetExtendedFeaturesMask(CONTEXT_EX*,ULONG64);
 #endif
 
diff --git a/include/winbase.h b/include/winbase.h
index f741f0a09dc..1c29db367c2 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2337,6 +2337,7 @@ WINBASEAPI UINT        WINAPI GetWindowsDirectoryA(LPSTR,UINT);
 WINBASEAPI UINT        WINAPI GetWindowsDirectoryW(LPWSTR,UINT);
 #define                       GetWindowsDirectory WINELIB_NAME_AW(GetWindowsDirectory)
 WINBASEAPI UINT        WINAPI GetWriteWatch(DWORD,LPVOID,SIZE_T,LPVOID*,ULONG_PTR*,ULONG*);
+WINBASEAPI BOOL        WINAPI GetXStateFeaturesMask(CONTEXT*,DWORD64*);
 WINBASEAPI ATOM        WINAPI GlobalAddAtomA(LPCSTR);
 WINBASEAPI ATOM        WINAPI GlobalAddAtomW(LPCWSTR);
 #define                       GlobalAddAtom WINELIB_NAME_AW(GlobalAddAtom)
-- 
2.26.2




More information about the wine-devel mailing list