From 541b06747ae4a64d0e39ed010b256b9326490701 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 1 Sep 2020 12:21:43 +0300 Subject: [PATCH] kernel32: Implement SetXStateFeaturesMask(). Signed-off-by: Paul Gofman Signed-off-by: Alexandre Julliard --- .../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 042ec1f99ba..ae1b44920bf 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 a1600a60c8f..38feffd3d17 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 @@ -6186,15 +6188,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; @@ -6321,6 +6323,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) @@ -6431,6 +6463,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); @@ -6591,11 +6624,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)); @@ -6652,11 +6714,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)); } } @@ -6752,6 +6819,7 @@ START_TEST(exception) X(RtlInitializeExtendedContext2); X(RtlLocateExtendedFeature); X(RtlLocateLegacyContext); + X(RtlSetExtendedFeaturesMask); #undef X #define X(f) p##f = (void*)GetProcAddress(hkernel32, #f) @@ -6761,6 +6829,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);