[PATCH 1/4] kernel32: Implement SetXStateFeaturesMask().

Paul Gofman pgofman at codeweavers.com
Tue Sep 1 04:21:43 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                   |  2 +-
 dlls/kernelbase/kernelbase.spec               |  2 +-
 dlls/kernelbase/memory.c                      | 41 +++++++++-
 dlls/ntdll/exception.c                        | 10 +++
 dlls/ntdll/ntdll.spec                         |  1 +
 dlls/ntdll/tests/exception.c                  | 77 ++++++++++++++++++-
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec           |  1 +
 include/ddk/wdm.h                             |  1 +
 include/winbase.h                             |  1 +
 11 files changed, 131 insertions(+), 9 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 b933eca226f..0a29d660112 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
@@ -5,4 +5,4 @@
 @ stdcall RtlInitializeExtendedContext(ptr long ptr) ntdll.RtlInitializeExtendedContext
 @ stdcall RtlLocateExtendedFeature(ptr long ptr) ntdll.RtlLocateExtendedFeature
 @ stdcall RtlLocateLegacyContext(ptr ptr) ntdll.RtlLocateLegacyContext
-@ stub RtlSetExtendedFeaturesMask
+@ stdcall RtlSetExtendedFeaturesMask(ptr int64) ntdll.RtlSetExtendedFeaturesMask
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 5ad2df2b405..74aafa4db1c 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
@@ -3,4 +3,4 @@
 @ stub GetXStateFeaturesMask
 @ stdcall -arch=i386,x86_64 InitializeContext(ptr long ptr ptr) kernel32.InitializeContext
 @ stdcall -arch=i386,x86_64 LocateXStateFeature(ptr long ptr) kernel32.LocateXStateFeature
-@ stub SetXStateFeaturesMask
+@ stdcall -arch=i386,x86_64 SetXStateFeaturesMask(ptr int64) kernel32.SetXStateFeaturesMask
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index c22f3000bf0..4bcda92bf7f 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -895,7 +895,7 @@
 @ stdcall -import GetWindowsDirectoryA(ptr long)
 @ stdcall -import GetWindowsDirectoryW(ptr long)
 @ stdcall -import GetWriteWatch(long ptr long ptr ptr ptr)
-# @ stub GetXStateFeaturesMask
+@ stdcall -import -arch=i386,x86_64 SetXStateFeaturesMask(ptr int64)
 @ stdcall GlobalAddAtomA(str)
 @ stdcall GlobalAddAtomW(wstr)
 @ stdcall -import GlobalAlloc(long long)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index ef862c57a4f..d2832600091 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1510,7 +1510,7 @@
 @ stdcall SetUserGeoID(long)
 @ stdcall SetWaitableTimer(long ptr long ptr ptr long)
 @ stdcall SetWaitableTimerEx(long ptr long ptr ptr ptr long)
-# @ stub SetXStateFeaturesMask
+@ stdcall -arch=i386,x86_64 SetXStateFeaturesMask(ptr int64)
 @ stdcall SetupComm(long long long)
 # @ stub SharedLocalIsEnabled
 @ stdcall SignalObjectAndWait(long long long long)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index ea958e1e232..f99b908494b 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -1236,10 +1236,10 @@ BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **cont
 #endif
 
 
+#if defined(__x86_64__)
 /***********************************************************************
  *           LocateXStateFeature   (kernelbase.@)
  */
-#if defined(__x86_64__)
 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
 {
     if (!(context->ContextFlags & CONTEXT_AMD64))
@@ -1262,7 +1262,28 @@ void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *le
 
     return &context->u.FltSave;
 }
+
+/***********************************************************************
+ *           SetXStateFeaturesMask (kernelbase.@)
+ */
+BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
+{
+    if (!(context->ContextFlags & CONTEXT_AMD64))
+        return FALSE;
+
+    if (feature_mask & 0x3)
+        context->ContextFlags |= CONTEXT_FLOATING_POINT;
+
+    if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
+        return !(feature_mask & ~(DWORD64)3);
+
+    RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
+    return TRUE;
+}
 #elif defined(__i386__)
+/***********************************************************************
+ *           LocateXStateFeature   (kernelbase.@)
+ */
 void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
 {
     if (!(context->ContextFlags & CONTEXT_X86))
@@ -1285,6 +1306,24 @@ void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *le
 
     return &context->ExtendedRegisters;
 }
+
+/***********************************************************************
+ *           SetXStateFeaturesMask (kernelbase.@)
+ */
+BOOL WINAPI SetXStateFeaturesMask( CONTEXT *context, DWORD64 feature_mask )
+{
+    if (!(context->ContextFlags & CONTEXT_X86))
+        return FALSE;
+
+    if (feature_mask & 0x3)
+        context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
+
+    if ((context->ContextFlags & CONTEXT_XSTATE) != CONTEXT_XSTATE)
+        return !(feature_mask & ~(DWORD64)3);
+
+    RtlSetExtendedFeaturesMask( (CONTEXT_EX *)(context + 1), feature_mask );
+    return TRUE;
+}
 #endif
 
 /***********************************************************************
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 0e7e3b959e4..6ca22d6660f 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -861,3 +861,13 @@ void * WINAPI RtlLocateLegacyContext( CONTEXT_EX *context_ex, ULONG *length )
 
     return (BYTE *)context_ex + context_ex->Legacy.Offset;
 }
+
+/**********************************************************************
+ *              RtlSetExtendedFeaturesMask  (NTDLL.@)
+ */
+void WINAPI RtlSetExtendedFeaturesMask( CONTEXT_EX *context_ex, ULONG64 feature_mask )
+{
+    XSTATE *xs = (XSTATE *)((BYTE *)context_ex + context_ex->XState.Offset);
+
+    xs->Mask = RtlGetEnabledExtendedFeatures( feature_mask ) & ~(ULONG64)3;
+}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index cc75aad06d1..0e17d29ed1b 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -946,6 +946,7 @@
 @ stdcall RtlSetCurrentTransaction(ptr)
 @ stdcall RtlSetDaclSecurityDescriptor(ptr long ptr long)
 @ stdcall RtlSetEnvironmentVariable(ptr ptr ptr)
+@ stdcall RtlSetExtendedFeaturesMask(ptr int64)
 @ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long)
 @ stdcall RtlSetHeapInformation(long long ptr long)
 @ stub RtlSetInformationAcl
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 4b714e4739e..7b6c65f8572 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -53,6 +53,7 @@ static NTSTATUS  (WINAPI *pRtlInitializeExtendedContext2)(void *context, ULONG c
         ULONG64 compaction_mask);
 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 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);
@@ -67,6 +68,7 @@ static BOOL      (WINAPI *pInitializeContext)(void *buffer, DWORD context_flags,
 static BOOL      (WINAPI *pInitializeContext2)(void *buffer, DWORD context_flags, CONTEXT **context,
         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);
 
 #define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
 
@@ -6224,15 +6226,15 @@ static void test_extended_context(void)
         },
     };
     ULONG expected_length, expected_length_xstate, context_flags, expected_offset;
+    ULONG64 enabled_features, expected_compaction;
     DECLSPEC_ALIGN(64) BYTE context_buffer2[2048];
     DECLSPEC_ALIGN(64) BYTE context_buffer[2048];
     unsigned int i, j, address_offset, test;
     ULONG ret, ret2, length, length2, align;
-    ULONG64 enabled_features;
     CONTEXT_EX *context_ex;
+    ULONG flags, flags_fpx;
     CONTEXT *context;
     unsigned data[8];
-    ULONG flags;
     XSTATE *xs;
     BOOL bret;
     void *p;
@@ -6359,6 +6361,36 @@ static void test_extended_context(void)
                     "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
             length2 = expected_length;
 
+            if (0)
+            {
+                /* Crashes on Windows. */
+                pRtlSetExtendedFeaturesMask(context_ex, 0);
+            }
+            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);
+            ok(context_flags == (bret ? flags_fpx : flags),
+                    "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags);
+
+            bret = pSetXStateFeaturesMask(context, 2);
+            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 == (bret ? flags_fpx : flags),
+                    "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags);
+
+            bret = pSetXStateFeaturesMask(context, 4);
+            ok(!bret, "Got unexpected bret %#x.\n", bret);
+            context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
+            ok(context_flags == (flags & CONTEXT_NATIVE ? flags_fpx : flags),
+                    "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags);
+            *(DWORD *)(context_buffer + context_arch[test].flags_offset) = flags;
+
             for (j = 0; j < context_arch[test].flags_offset; ++j)
             {
                 if (context_buffer[j] != 0xcc)
@@ -6469,6 +6501,7 @@ static void test_extended_context(void)
         }
 
         flags = context_arch[test].flag | 0x40;
+        flags_fpx = flags & 0x10000 ? flags | 0x20 : flags | 0x8;
 
         length = 0xdeadbeef;
         ret = pRtlGetExtendedContextLength(flags, &length);
@@ -6629,11 +6662,40 @@ static void test_extended_context(void)
         else
             ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
 
+        expected_compaction = compaction_enabled ? ((ULONG64)1 << 63) | enabled_features : 0;
         ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
-        ok(xs->CompactionMask == (compaction_enabled ? ((ULONG64)1 << 63) | enabled_features : 0),
+        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]));
 
+        xs->Mask = 0xdeadbeef;
+        xs->CompactionMask = 0xdeadbeef;
+        pRtlSetExtendedFeaturesMask(context_ex, 0);
+        ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->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);
+
+        xs->Mask = 0xdeadbeef;
+        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));
+        ok(!xs->CompactionMask, "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);
+
+        xs->Mask = 0xdeadbeef;
+        xs->CompactionMask = 0xdeadbeef;
+        bret = pSetXStateFeaturesMask(context, 7);
+        ok(bret == !!(flags & CONTEXT_NATIVE), "Got unexpected bret %#x.\n", bret);
+        context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset);
+        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));
+        ok(xs->CompactionMask == bret ? expected_compaction : 0xdeadbeef, "Got unexpected CompactionMask %s.\n",
+                wine_dbgstr_longlong(xs->CompactionMask));
+
         if (pRtlGetExtendedContextLength2)
         {
             memset(context_buffer, 0xcc, sizeof(context_buffer));
@@ -6690,11 +6752,16 @@ static void test_extended_context(void)
                     + context_ex->XState.Offset + context_ex->XState.Length,
                     "Got unexpected Length %#x, flags %#x.\n", context_ex->All.Length, flags);
 
+            expected_compaction = compaction_enabled ? (ULONG64)1 << 63 : 0;
             xs = (XSTATE *)((BYTE *)context_ex + context_ex->XState.Offset);
             ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
-            ok(xs->CompactionMask == (compaction_enabled ? (ULONG64)1 << 63 : 0),
+            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]));
+
+            pRtlSetExtendedFeaturesMask(context_ex, ~(ULONG64)0);
+            ok(xs->Mask == (enabled_features & ~(ULONG64)3), "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+            ok(xs->CompactionMask == expected_compaction, "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask));
         }
     }
 
@@ -6790,6 +6857,7 @@ START_TEST(exception)
     X(RtlInitializeExtendedContext2);
     X(RtlLocateExtendedFeature);
     X(RtlLocateLegacyContext);
+    X(RtlSetExtendedFeaturesMask);
 #undef X
 
 #define X(f) p##f = (void*)GetProcAddress(hkernel32, #f)
@@ -6799,6 +6867,7 @@ START_TEST(exception)
     X(InitializeContext);
     X(InitializeContext2);
     X(LocateXStateFeature);
+    X(SetXStateFeaturesMask);
 #undef X
 
     if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index a900796359c..ffd8f7dcd4c 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 RtlSetExtendedFeaturesMask(ptr int64)
 @ stdcall RtlSetGroupSecurityDescriptor(ptr ptr long)
 @ stdcall RtlSetOwnerSecurityDescriptor(ptr ptr long)
 @ stdcall RtlSetSaclSecurityDescriptor(ptr long ptr long)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 2115627d3a6..3938645da94 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*);
+void      WINAPI RtlSetExtendedFeaturesMask(CONTEXT_EX*,ULONG64);
 #endif
 
 #ifdef __x86_64__
diff --git a/include/winbase.h b/include/winbase.h
index d5ed5db8d7b..f741f0a09dc 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2700,6 +2700,7 @@ WINBASEAPI BOOL        WINAPI SetVolumeMountPointW(LPCWSTR,LPCWSTR);
 WINBASEAPI BOOL        WINAPI SetWaitableTimer(HANDLE,const LARGE_INTEGER*,LONG,PTIMERAPCROUTINE,LPVOID,BOOL);
 WINBASEAPI BOOL        WINAPI SetWaitableTimerEx(HANDLE,const LARGE_INTEGER*,LONG,PTIMERAPCROUTINE,LPVOID,REASON_CONTEXT*,ULONG);
 WINBASEAPI BOOL        WINAPI SetUmsThreadInformation(PUMS_CONTEXT,UMS_THREAD_INFO_CLASS,void *,ULONG);
+WINBASEAPI BOOL        WINAPI SetXStateFeaturesMask(CONTEXT*, DWORD64);
 WINBASEAPI BOOL        WINAPI SetupComm(HANDLE,DWORD,DWORD);
 WINBASEAPI DWORD       WINAPI SignalObjectAndWait(HANDLE,HANDLE,DWORD,BOOL);
 WINBASEAPI DWORD       WINAPI SizeofResource(HMODULE,HRSRC);
-- 
2.26.2




More information about the wine-devel mailing list