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 3329be6cf08..5ad2df2b405 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 -arch=i386,x86_64 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 c2649809b33..c22f3000bf0 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 31be4761391..ef862c57a4f 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 6576e900d5f..ea958e1e232 100644 --- a/dlls/kernelbase/memory.c +++ b/dlls/kernelbase/memory.c @@ -1236,6 +1236,57 @@ BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **cont #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 7aa059775c7..cb9481322ba 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -806,3 +806,47 @@ NTSTATUS WINAPI RtlInitializeExtendedContext( void *context, ULONG context_flags { 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 2d6ddfef3c3..0829cc43a9f 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 29a68271cdd..242ca9c61a4 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 NTSTATUS (WINAPI *pRtlGetExtendedContextLength2)(ULONG context_flags, UL static NTSTATUS (WINAPI *pRtlInitializeExtendedContext)(void *context, ULONG context_flags, CONTEXT_EX **context_ex); static NTSTATUS (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 @@ -6151,6 +6154,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[] = { @@ -6163,6 +6168,8 @@ static void test_extended_context(void) 0x20, /* sizeof(CONTEXT_EX) */ 7, 0x30, + 0x100, /* offsetof(CONTEXT, FltSave) */ + 16, }, { 0x00010000, /* CONTEXT_X86 */ @@ -6173,6 +6180,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; @@ -6187,6 +6196,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; @@ -6221,7 +6231,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", @@ -6352,6 +6361,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; @@ -6361,6 +6390,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); @@ -6369,13 +6399,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; @@ -6500,6 +6539,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)); @@ -6518,6 +6596,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); @@ -6641,6 +6737,7 @@ START_TEST(exception) X(RtlGetExtendedContextLength2); X(RtlInitializeExtendedContext); X(RtlInitializeExtendedContext2); + X(RtlLocateExtendedFeature); #undef X #define X(f) p##f = (void*)GetProcAddress(hkernel32, #f) @@ -6649,6 +6746,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 703929074fc..893db4df20e 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1842,6 +1842,8 @@ NTSTATUS WINAPI RtlInitializeExtendedContext2(void*,ULONG,CONTEXT_EX**,ULONG64) ULONG64 WINAPI RtlGetEnabledExtendedFeatures(ULONG64); NTSTATUS WINAPI RtlGetExtendedContextLength(ULONG,ULONG*); NTSTATUS WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,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);