[PATCH v2 3/3] kernel32: Implement LocateXStateFeature().
Paul Gofman
pgofman at codeweavers.com
Mon Aug 24 07:17:22 CDT 2020
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
v2:
- no changes.
.../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 | 51 +++++++++
dlls/ntdll/exception.c | 44 ++++++++
dlls/ntdll/ntdll.spec | 2 +
dlls/ntdll/tests/exception.c | 102 +++++++++++++++++-
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +
include/ddk/wdm.h | 2 +
include/winbase.h | 1 +
11 files changed, 206 insertions(+), 6 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 2c72d52e452..4d8d5803871 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
@@ -3,6 +3,6 @@
@ stdcall RtlGetExtendedContextLength(long ptr) ntdll.RtlGetExtendedContextLength
@ stub RtlGetExtendedFeaturesMask
@ stdcall RtlInitializeExtendedContext(ptr long ptr) ntdll.RtlInitializeExtendedContext
-@ stub RtlLocateExtendedFeature
+@ stdcall RtlLocateExtendedFeature(ptr long ptr) ntdll.RtlLocateExtendedFeature
@ stub RtlLocateLegacyContext
@ stub 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 2f79395bd28..dc3b41de97e 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
@@ -2,5 +2,5 @@
@ stdcall -ret64 -arch=i386,x86_64 GetEnabledXStateFeatures() kernel32.GetEnabledXStateFeatures
@ stub GetXStateFeaturesMask
@ stdcall InitializeContext(ptr long ptr ptr) kernel32.InitializeContext
-@ stub LocateXStateFeature
+@ stdcall -arch=i386,x86_64 LocateXStateFeature(ptr long ptr) kernel32.LocateXStateFeature
@ stub SetXStateFeaturesMask
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index bf51bcc8491..bd28e3bf265 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1071,7 +1071,7 @@
@ stdcall LocalSize(long)
@ stdcall -import LocalUnlock(long)
@ stdcall -import LocaleNameToLCID(wstr long)
-# @ stub LocateXStateFeature
+@ stdcall -import -arch=i386,x86_64 LocateXStateFeature(ptr long ptr)
@ stdcall -import LockFile(long long long long long)
@ stdcall -import LockFileEx(long long long long long ptr)
@ stdcall -import LockResource(long)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 3b4d20eea96..23775afe784 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -942,7 +942,7 @@
@ stdcall LocalReAlloc(long long long)
@ stdcall LocalUnlock(long)
@ stdcall LocaleNameToLCID(wstr long)
-# @ stub LocateXStateFeature
+@ stdcall -arch=i386,x86_64 LocateXStateFeature(ptr long ptr)
@ stdcall LockFile(long long long long long)
@ stdcall LockFileEx(long long long long long ptr)
@ stdcall LockResource(long)
diff --git a/dlls/kernelbase/memory.c b/dlls/kernelbase/memory.c
index 9131b9de28f..8bfc1bfc861 100644
--- a/dlls/kernelbase/memory.c
+++ b/dlls/kernelbase/memory.c
@@ -1187,6 +1187,57 @@ DWORD64 WINAPI GetEnabledXStateFeatures(void)
#endif
+/***********************************************************************
+ * LocateXStateFeature (kernelbase.@)
+ */
+#if defined(__x86_64__)
+void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
+{
+ if (!(context->ContextFlags & CONTEXT_AMD64))
+ return NULL;
+
+ if (feature_id >= 2)
+ return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
+ ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
+
+ if (feature_id == 1)
+ {
+ if (length)
+ *length = sizeof(M128A) * 16;
+
+ return &context->u.FltSave.XmmRegisters;
+ }
+
+ if (length)
+ *length = offsetof(XSAVE_FORMAT, XmmRegisters);
+
+ return &context->u.FltSave;
+}
+#elif defined(__i386__)
+void * WINAPI LocateXStateFeature( CONTEXT *context, DWORD feature_id, DWORD *length )
+{
+ if (!(context->ContextFlags & CONTEXT_X86))
+ return NULL;
+
+ if (feature_id >= 2)
+ return ((context->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
+ ? RtlLocateExtendedFeature( (CONTEXT_EX *)(context + 1), feature_id, length ) : NULL;
+
+ if (feature_id == 1)
+ {
+ if (length)
+ *length = sizeof(M128A) * 8;
+
+ return (BYTE *)&context->ExtendedRegisters + offsetof(XSAVE_FORMAT, XmmRegisters);
+ }
+
+ if (length)
+ *length = offsetof(XSAVE_FORMAT, XmmRegisters);
+
+ return &context->ExtendedRegisters;
+}
+#endif
+
/***********************************************************************
* Firmware functions
***********************************************************************/
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index e875b560c6b..0018cb047e1 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -804,3 +804,47 @@ ULONG WINAPI RtlInitializeExtendedContext( void *context, ULONG context_flags, C
{
return RtlInitializeExtendedContext2( context, context_flags, context_ex, ~(ULONG64)0 );
}
+
+
+/**********************************************************************
+ * RtlLocateExtendedFeature2 (NTDLL.@)
+ */
+void * WINAPI RtlLocateExtendedFeature2( CONTEXT_EX *context_ex, ULONG feature_id,
+ XSTATE_CONFIGURATION *xstate_config, ULONG *length )
+{
+ TRACE( "context_ex %p, feature_id %u, xstate_config %p, length %p.\n",
+ context_ex, feature_id, xstate_config, length );
+
+ if (!xstate_config)
+ {
+ FIXME( "NULL xstate_config.\n" );
+ return NULL;
+ }
+
+ if (xstate_config != &user_shared_data->XState)
+ {
+ FIXME( "Custom xstate configuration is not supported.\n" );
+ return NULL;
+ }
+
+ if (feature_id != XSTATE_AVX)
+ return NULL;
+
+ if (length)
+ *length = sizeof(YMMCONTEXT);
+
+ if (context_ex->XState.Length < sizeof(XSTATE))
+ return NULL;
+
+ return (BYTE *)context_ex + context_ex->XState.Offset + offsetof(XSTATE, YmmContext);
+}
+
+
+/**********************************************************************
+ * RtlLocateExtendedFeature (NTDLL.@)
+ */
+void * WINAPI RtlLocateExtendedFeature( CONTEXT_EX *context_ex, ULONG feature_id,
+ ULONG *length )
+{
+ return RtlLocateExtendedFeature2( context_ex, feature_id, &user_shared_data->XState, length );
+}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 2a33368d7f8..02d0cc69aff 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -826,6 +826,8 @@
@ stdcall RtlLengthSid(ptr)
@ stdcall RtlLocalTimeToSystemTime(ptr ptr)
@ stdcall RtlLocaleNameToLcid(wstr ptr long)
+@ stdcall RtlLocateExtendedFeature(ptr long ptr)
+@ stdcall RtlLocateExtendedFeature2(ptr long ptr ptr)
# @ stub RtlLockBootStatusData
@ stdcall RtlLockHeap(long)
# @ stub RtlLockMemoryStreamRegion
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index c5a6b4e4d77..35bed600fa8 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -28,6 +28,7 @@
#include "winnt.h"
#include "winreg.h"
#include "winternl.h"
+#include "ddk/wdm.h"
#include "excpt.h"
#include "wine/test.h"
#include "intrin.h"
@@ -50,6 +51,7 @@ static ULONG64 (WINAPI *pRtlGetExtendedContextLength2)(ULONG context_flags, UL
static ULONG (WINAPI *pRtlInitializeExtendedContext)(void *context, ULONG context_flags, CONTEXT_EX **context_ex);
static ULONG (WINAPI *pRtlInitializeExtendedContext2)(void *context, ULONG context_flags, CONTEXT_EX **context_ex,
ULONG64 compaction_mask);
+static void * (WINAPI *pRtlLocateExtendedFeature)(CONTEXT_EX *context_ex, ULONG feature_id, ULONG *length);
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);
@@ -63,6 +65,7 @@ static BOOL (WINAPI *pInitializeContext)(void *buffer, DWORD context_flags,
DWORD *length);
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);
#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
@@ -5596,6 +5599,8 @@ static void test_extended_context(void)
ULONG context_ex_length;
ULONG align;
ULONG flags_offset;
+ ULONG xsavearea_offset;
+ ULONG vector_reg_count;
}
context_arch[] =
{
@@ -5608,6 +5613,8 @@ static void test_extended_context(void)
0x20, /* sizeof(CONTEXT_EX) */
7,
0x30,
+ 0x100, /* offsetof(CONTEXT, FltSave) */
+ 16,
},
{
0x00010000, /* CONTEXT_X86 */
@@ -5618,6 +5625,8 @@ static void test_extended_context(void)
0x18, /* sizeof(CONTEXT_EX) */
3,
0,
+ 0xcc, /* offsetof(CONTEXT, ExtendedRegisters) */
+ 8,
},
};
ULONG expected_length, expected_length_xstate, context_flags, expected_offset;
@@ -5632,6 +5641,7 @@ static void test_extended_context(void)
ULONG flags;
XSTATE *xs;
BOOL bret;
+ void *p;
address_offset = sizeof(void *) == 8 ? 2 : 1;
*(void **)(except_code_set_ymm0 + address_offset) = data;
@@ -5666,7 +5676,6 @@ static void test_extended_context(void)
expected_length_xstate = context_arch[test].context_length + context_arch[test].context_ex_length
+ sizeof(XSTATE) + 63;
-
length = 0xdeadbeef;
ret = pRtlGetExtendedContextLength(context_arch[test].flag, &length);
ok(!ret && length == expected_length, "Got unexpected result ret %#x, length %#x.\n",
@@ -5798,6 +5807,26 @@ static void test_extended_context(void)
sizeof(context_buffer2) - align),
"Context data do not match, flags %#x.\n", flags);
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 0, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset
+ && length2 == offsetof(XSAVE_FORMAT, XmmRegisters),
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 1, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset + offsetof(XSAVE_FORMAT, XmmRegisters)
+ && length2 == sizeof(M128A) * context_arch[test].vector_reg_count,
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 2, &length2);
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
if (!pRtlInitializeExtendedContext2 || !pInitializeContext2)
{
static int once;
@@ -5807,6 +5836,7 @@ static void test_extended_context(void)
continue;
}
+ length2 = expected_length;
memset(context_buffer2, 0xcc, sizeof(context_buffer2));
ret2 = pRtlInitializeExtendedContext2(context_buffer2 + 2, flags, &context_ex, ~(ULONG64)0);
ok(!ret2, "Got unexpected ret2 %#x, flags %#x.\n", ret2, flags);
@@ -5815,13 +5845,22 @@ static void test_extended_context(void)
"Context data do not match, flags %#x.\n", flags);
memset(context_buffer2, 0xcc, sizeof(context_buffer2));
- bret = pInitializeContext2(context_buffer2 + 2, flags, &context, &length2, ~(ULONG64)0);
+ bret = pInitializeContext2(context_buffer2 + 2, flags, &context, &length2, 0);
ok(bret && GetLastError() == 0xdeadbeef,
"Got unexpected bret %#x, GetLastError() %u, flags %#x.\n", bret, GetLastError(), flags);
ok(length2 == expected_length, "Got unexpexted length %#x.\n", length);
ok(!memcmp(context_buffer2 + align, context_buffer,
sizeof(context_buffer2) - align),
"Context data do not match, flags %#x.\n", flags);
+
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 0, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset
+ && length2 == offsetof(XSAVE_FORMAT, XmmRegisters),
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
}
flags = context_arch[test].flag | 0x40;
@@ -5929,6 +5968,45 @@ static void test_extended_context(void)
"Got unexpected Length %#x, flags %#x.\n", context_ex->All.Length, flags);
xs = (XSTATE *)((BYTE *)context_ex + context_ex->XState.Offset);
+ length2 = 0xdeadbeef;
+ for (i = 0; i < 2; ++i)
+ {
+ p = pRtlLocateExtendedFeature(context_ex, i, &length2);
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x.\n", p, length2);
+ }
+
+ p = pRtlLocateExtendedFeature(context_ex, XSTATE_AVX, &length2);
+ ok(length2 == sizeof(YMMCONTEXT), "Got unexpected length %#x.\n", length2);
+ ok(p == &xs->YmmContext, "Got unexpected p %p.\n", p);
+ p = pRtlLocateExtendedFeature(context_ex, XSTATE_AVX, NULL);
+ ok(p == &xs->YmmContext, "Got unexpected p %p.\n", p);
+
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 0, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset
+ && length2 == offsetof(XSAVE_FORMAT, XmmRegisters),
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 1, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset + offsetof(XSAVE_FORMAT, XmmRegisters)
+ && length2 == sizeof(M128A) * context_arch[test].vector_reg_count,
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 2, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == &xs->YmmContext && length2 == sizeof(YMMCONTEXT),
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
ok(xs->CompactionMask == (compaction_enabled ? ((ULONG64)1 << 63) | enabled_features : 0),
"Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(xs->CompactionMask));
@@ -5947,6 +6025,24 @@ static void test_extended_context(void)
ok(length2 == length, "Got unexpexted length %#x.\n", length);
ok((BYTE *)context == context_buffer, "Got unexpected context %p.\n", context);
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 0, &length2);
+ if (flags & CONTEXT_NATIVE)
+ ok(p == (BYTE *)context + context_arch[test].xsavearea_offset
+ && length2 == offsetof(XSAVE_FORMAT, XmmRegisters),
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ else
+ ok(!p && length2 == 0xdeadbeef, "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
+ length2 = 0xdeadbeef;
+ p = pRtlLocateExtendedFeature(context_ex, 2, &length2);
+ ok(!p && length2 == sizeof(YMMCONTEXT), "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+
+ length2 = 0xdeadbeef;
+ p = pLocateXStateFeature(context, 2, &length2);
+ ok(!p && length2 == (flags & CONTEXT_NATIVE) ? sizeof(YMMCONTEXT) : 0xdeadbeef,
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, 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);
@@ -6074,6 +6170,7 @@ START_TEST(exception)
X(RtlGetExtendedContextLength2);
X(RtlInitializeExtendedContext);
X(RtlInitializeExtendedContext2);
+ X(RtlLocateExtendedFeature);
#undef X
#define X(f) p##f = (void*)GetProcAddress(hkernel32, #f)
@@ -6082,6 +6179,7 @@ START_TEST(exception)
X(InitializeContext);
X(InitializeContext2);
+ X(LocateXStateFeature);
#undef X
if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 163e041065f..6666031cc6d 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1174,6 +1174,8 @@
@ stdcall RtlLengthSecurityDescriptor(ptr)
@ stdcall RtlLengthSid(ptr)
@ stdcall RtlLocalTimeToSystemTime(ptr ptr)
+@ stdcall RtlLocateExtendedFeature(ptr long ptr)
+@ stdcall RtlLocateExtendedFeature2(ptr long ptr ptr)
@ stub RtlLockBootStatusData
@ stdcall RtlLookupAtomInAtomTable(ptr wstr ptr)
@ stub RtlLookupElementGenericTable
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index b8a51fd7e61..59982f3b06b 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1843,6 +1843,8 @@ ULONG64 WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,ULONG64);
#if defined(__x86_64__) || defined(__i386__)
ULONG64 WINAPI RtlGetEnabledExtendedFeatures(ULONG64);
+void * WINAPI RtlLocateExtendedFeature(CONTEXT_EX*,ULONG,ULONG*);
+void * WINAPI RtlLocateExtendedFeature2(CONTEXT_EX*,ULONG,XSTATE_CONFIGURATION*,ULONG*);
#endif
#ifdef __x86_64__
diff --git a/include/winbase.h b/include/winbase.h
index 9957cd43bb6..d5ed5db8d7b 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -2439,6 +2439,7 @@ WINBASEAPI HLOCAL WINAPI LocalReAlloc(HLOCAL,SIZE_T,UINT) __WINE_ALLOC_SIZE
WINBASEAPI SIZE_T WINAPI LocalShrink(HGLOBAL,UINT);
WINBASEAPI SIZE_T WINAPI LocalSize(HLOCAL);
WINBASEAPI BOOL WINAPI LocalUnlock(HLOCAL);
+WINBASEAPI void * WINAPI LocateXStateFeature(CONTEXT *,DWORD,DWORD *);
WINBASEAPI LPVOID WINAPI LockResource(HGLOBAL);
#define LockSegment(handle) GlobalFix((HANDLE)(handle))
WINADVAPI BOOL WINAPI LookupAccountNameA(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE);
--
2.26.2
More information about the wine-devel
mailing list