Signed-off-by: Paul Gofman pgofman@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)