Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - no changes.
.../api-ms-win-core-xstate-l1-1-0.spec | 2 +- dlls/ntdll/exception.c | 71 +++++++++ dlls/ntdll/ntdll.spec | 2 + dlls/ntdll/tests/exception.c | 147 +++++++++++++++++- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 + include/ddk/wdm.h | 8 +- 6 files changed, 228 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 36a1c8812f0..15126e5ddfe 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,6 +1,6 @@ @ stub RtlCopyExtendedContext @ stdcall RtlGetEnabledExtendedFeatures(int64) ntdll.RtlGetEnabledExtendedFeatures -@ stub RtlGetExtendedContextLength +@ stdcall RtlGetExtendedContextLength(long ptr) ntdll.RtlGetExtendedContextLength @ stub RtlGetExtendedFeaturesMask @ stub RtlInitializeExtendedContext @ stub RtlLocateExtendedFeature diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 3f7443bb45b..1b212cdee7f 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -665,3 +665,74 @@ ULONG64 WINAPI RtlGetEnabledExtendedFeatures(ULONG64 feature_mask) { return user_shared_data->XState.EnabledFeatures & feature_mask; } + +static const struct context_parameters +{ + ULONG arch_flag; + ULONG supported_flags; + ULONG context_size; /* sizeof(CONTEXT) */ + ULONG context_ex_size; /* sizeof(CONTEXT_EX) */ + ULONG alignment; +} +arch_context_paramaters[] = +{ + {0x00100000, 0xd810005f, 0x4d0, 0x20, 7}, + {0x00010000, 0xd801007f, 0x2cc, 0x18, 3}, +}; + +static const struct context_parameters *context_get_parameters( ULONG context_flags ) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(arch_context_paramaters); ++i) + { + if (context_flags & arch_context_paramaters[i].arch_flag) + return context_flags & ~arch_context_paramaters[i].supported_flags ? NULL : &arch_context_paramaters[i]; + } + return NULL; +} + + +/********************************************************************** + * RtlGetExtendedContextLength2 (NTDLL.@) + */ +ULONG64 WINAPI RtlGetExtendedContextLength2( ULONG context_flags, ULONG *length, ULONG64 compaction_mask ) +{ + const struct context_parameters *p; + ULONG64 supported_mask; + ULONG64 size; + + TRACE( "context_flags %#x, length %p, compaction_mask %s.\n", context_flags, length, + wine_dbgstr_longlong(compaction_mask) ); + + if (!(p = context_get_parameters( context_flags ))) + return STATUS_INVALID_PARAMETER; + + if (!(context_flags & 0x40)) + { + *length = p->context_size + p->context_ex_size + p->alignment; + return STATUS_SUCCESS; + } + + if (!(supported_mask = RtlGetEnabledExtendedFeatures( ~(ULONG64)0) )) + return STATUS_NOT_SUPPORTED; + + compaction_mask &= supported_mask; + + size = p->context_size + p->context_ex_size + offsetof(XSTATE, YmmContext) + 63; + + if (compaction_mask & supported_mask & (1 << XSTATE_AVX)) + size += sizeof(YMMCONTEXT); + + *length = size; + return STATUS_SUCCESS; +} + + +/********************************************************************** + * RtlGetExtendedContextLength (NTDLL.@) + */ +ULONG64 WINAPI RtlGetExtendedContextLength( ULONG context_flags, ULONG *length ) +{ + return RtlGetExtendedContextLength2( context_flags, length, ~(ULONG64)0 ); +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c21e2bcf32a..08c6e1849a2 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -695,6 +695,8 @@ # @ stub RtlGetElementGenericTableAvl @ stdcall RtlGetEnabledExtendedFeatures(int64) @ stdcall RtlGetExePath(wstr ptr) +@ stdcall -ret64 RtlGetExtendedContextLength(long ptr) +@ stdcall -ret64 RtlGetExtendedContextLength2(long ptr int64) # @ 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 9f93212acf6..0e00e889d41 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -45,6 +45,8 @@ static PVOID (WINAPI *pRtlAddVectoredContinueHandler)(ULONG first, PVECTORED static ULONG (WINAPI *pRtlRemoveVectoredContinueHandler)(PVOID handler); static void (WINAPI *pRtlSetUnhandledExceptionFilter)(PRTL_EXCEPTION_FILTER filter); static ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64); +static ULONG64 (WINAPI *pRtlGetExtendedContextLength)(ULONG context_flags, ULONG *length); +static ULONG64 (WINAPI *pRtlGetExtendedContextLength2)(ULONG context_flags, ULONG *length, ULONG64 compaction_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); @@ -5544,6 +5546,8 @@ done: return ExceptionContinueExecution; }
+#define CONTEXT_NATIVE (CONTEXT_XSTATE & CONTEXT_CONTROL) + static void test_extended_context(void) { static BYTE except_code_set_ymm0[] = @@ -5580,19 +5584,156 @@ static void test_extended_context(void) 0xc5, 0xfc, 0x11, 0x00, /* vmovups %ymm0,(%ax) */ 0xc3, /* ret */ }; - unsigned int i, address_offset; + static const struct + { + ULONG flag; + ULONG supported_flags; + ULONG broken_flags; + ULONG context_length; + ULONG context_ex_length; + ULONG align; + } + context_arch[] = + { + { + 0x00100000, /* CONTEXT_AMD64 */ + 0xd800005f, + 0xd8000000, + 0x4d0, /* sizeof(CONTEXT) */ + 0x20, /* sizeof(CONTEXT_EX) */ + 7, + }, + { + 0x00010000, /* CONTEXT_X86 */ + 0xd800007f, + 0xd8000000, + 0x2cc, /* sizeof(CONTEXT) */ + 0x18, /* sizeof(CONTEXT_EX) */ + 3, + }, + }; + ULONG expected_length, expected_length_xstate; + unsigned int i, address_offset, test; + ULONG64 enabled_features; + ULONG ret, length; unsigned data[8]; + ULONG flags;
address_offset = sizeof(void *) == 8 ? 2 : 1; *(void **)(except_code_set_ymm0 + address_offset) = data; *(void **)(except_code_reset_ymm_state + address_offset) = data;
- if (!pRtlGetEnabledExtendedFeatures || !(pRtlGetEnabledExtendedFeatures(~(ULONG64)0) & (1 << XSTATE_AVX))) + if (!pRtlGetEnabledExtendedFeatures) + { + skip("RtlGetEnabledExtendedFeatures is not available.\n"); + return; + } + + enabled_features = pRtlGetEnabledExtendedFeatures(~(ULONG64)0); + + /* Test context manipulation functions. */ + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength(0, &length); + ok(ret == STATUS_INVALID_PARAMETER && length == 0xdeadbeef, "Got unexpected result ret %#x, length %#x.\n", + ret, length); + + for (test = 0; test < ARRAY_SIZE(context_arch); ++test) + { + expected_length = context_arch[test].context_length + context_arch[test].context_ex_length + + context_arch[test].align; + 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", + ret, length); + + for (i = 0; i < 32; ++i) + { + if (i == 6) /* CONTEXT_XSTATE */ + continue; + + flags = context_arch[test].flag | (1 << i); + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength(flags, &length); + + if ((context_arch[test].supported_flags & flags) || flags == context_arch[test].flag) + { + ok((!ret && length == expected_length) + || broken((context_arch[test].broken_flags & (1 << i)) + && ret == STATUS_INVALID_PARAMETER && length == 0xdeadbeef), + "Got unexpected result ret %#x, length %#x, flags 0x%08x.\n", + ret, length, flags); + } + else + { + ok(ret == STATUS_INVALID_PARAMETER && length == 0xdeadbeef, + "Got unexpected result ret %#x, length %#x, flags 0x%08x.\n", ret, length, flags); + } + } + + flags = context_arch[test].flag | 0x40; + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength(flags, &length); + + if (!enabled_features) + { + ok(ret == STATUS_NOT_SUPPORTED && length == 0xdeadbeef, + "Got unexpected result ret %#x, length %#x.\n", ret, length); + continue; + } + + ok(!ret && length >= expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + + if (!pRtlGetExtendedContextLength2) + { + win_skip("RtlGetExtendedContextLength2 is not available.\n"); + continue; + } + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 7); + ok(!ret && length == expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, ~0); + ok(!ret && length >= expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 0); + ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 3); + ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 4); + ok(!ret && length == expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + } + + if (0) + { + /* Crashes on Windows. */ + pRtlGetExtendedContextLength(CONTEXT_FULL, NULL); + } + + if (!(enabled_features & (1 << XSTATE_AVX))) { skip("AVX is not supported.\n"); return; }
+ /* Test fault exception context. */ memset(data, 0xff, sizeof(data)); test_extended_context_modified_state = FALSE; run_exception_test(test_extended_context_handler, NULL, except_code_reset_ymm_state, @@ -5657,6 +5798,8 @@ START_TEST(exception) X(RtlGetUnloadEventTrace); X(RtlGetUnloadEventTraceEx); X(RtlGetEnabledExtendedFeatures); + X(RtlGetExtendedContextLength); + X(RtlGetExtendedContextLength2); #undef X
pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0e8082fad26..45024a3a8da 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1096,6 +1096,8 @@ @ stub RtlGetDefaultCodePage @ stub RtlGetElementGenericTable @ stub RtlGetElementGenericTableAvl +@ stdcall RtlGetExtendedContextLength(long ptr) +@ stdcall RtlGetExtendedContextLength2(long ptr int64) @ stub RtlGetFirstRange @ stdcall RtlGetGroupSecurityDescriptor(ptr ptr ptr) @ stub RtlGetNextRange diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index cc841326979..fa0f42aadef 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1836,12 +1836,18 @@ HANDLE WINAPI PsGetProcessInheritedFromUniqueProcessId(PEPROCESS); BOOLEAN WINAPI PsGetVersion(ULONG*,ULONG*,ULONG*,UNICODE_STRING*); NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS);
+ULONG64 WINAPI RtlGetExtendedContextLength(ULONG,ULONG*); +ULONG64 WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,ULONG64); + +#if defined(__x86_64__) || defined(__i386__) +ULONG64 WINAPI RtlGetEnabledExtendedFeatures(ULONG64); +#endif + #ifdef __x86_64__ void WINAPI RtlCopyMemoryNonTemporal(void*,const void*,SIZE_T); #else #define RtlCopyMemoryNonTemporal RtlCopyMemory #endif -ULONG64 WINAPI RtlGetEnabledExtendedFeatures(ULONG64); BOOLEAN WINAPI RtlIsNtDdiVersionAvailable(ULONG);
NTSTATUS WINAPI ZwAddBootEntry(PUNICODE_STRING,PUNICODE_STRING);
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - fix legacy context length on x86.
.../api-ms-win-core-xstate-l1-1-0.spec | 2 +- .../api-ms-win-core-xstate-l2-1-0.spec | 2 +- dlls/kernel32/kernel32.spec | 3 +- dlls/kernelbase/kernelbase.spec | 3 +- dlls/kernelbase/thread.c | 47 +++ dlls/ntdll/exception.c | 74 +++- dlls/ntdll/ntdll.spec | 2 + dlls/ntdll/tests/exception.c | 349 ++++++++++++++++-- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 + include/ddk/wdm.h | 2 + include/winbase.h | 2 + 11 files changed, 446 insertions(+), 42 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 15126e5ddfe..2c72d52e452 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 @@ -2,7 +2,7 @@ @ stdcall RtlGetEnabledExtendedFeatures(int64) ntdll.RtlGetEnabledExtendedFeatures @ stdcall RtlGetExtendedContextLength(long ptr) ntdll.RtlGetExtendedContextLength @ stub RtlGetExtendedFeaturesMask -@ stub RtlInitializeExtendedContext +@ stdcall RtlInitializeExtendedContext(ptr long ptr) ntdll.RtlInitializeExtendedContext @ stub 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 f0510978198..2f79395bd28 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 -@ stub InitializeContext +@ stdcall InitializeContext(ptr long ptr ptr) kernel32.InitializeContext @ stub LocateXStateFeature @ stub SetXStateFeaturesMask diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 5671ae7e93d..bf51bcc8491 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -950,7 +950,8 @@ @ stdcall InitOnceExecuteOnce(ptr ptr ptr ptr) kernelbase.InitOnceExecuteOnce @ stdcall InitOnceInitialize(ptr) ntdll.RtlRunOnceInitialize @ stdcall InitializeConditionVariable(ptr) ntdll.RtlInitializeConditionVariable -# @ stub InitializeContext +@ stdcall -import InitializeContext(ptr long ptr ptr) +@ stdcall -import InitializeContext2(ptr long ptr ptr int64) @ stdcall InitializeCriticalSection(ptr) ntdll.RtlInitializeCriticalSection @ stdcall -import InitializeCriticalSectionAndSpinCount(ptr long) @ stdcall -import InitializeCriticalSectionEx(ptr long long) diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index e8989a0639d..3b4d20eea96 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -801,7 +801,8 @@ @ stdcall InitOnceInitialize(ptr) ntdll.RtlRunOnceInitialize @ stdcall InitializeAcl(ptr long long) @ stdcall InitializeConditionVariable(ptr) ntdll.RtlInitializeConditionVariable -# @ stub InitializeContext +@ stdcall InitializeContext(ptr long ptr ptr) +@ stdcall InitializeContext2(ptr long ptr ptr int64) @ stdcall InitializeCriticalSection(ptr) ntdll.RtlInitializeCriticalSection @ stdcall InitializeCriticalSectionAndSpinCount(ptr long) @ stdcall InitializeCriticalSectionEx(ptr long long) diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index c688b81e460..16954d4a385 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -29,6 +29,7 @@ #include "winbase.h" #include "winnls.h" #include "winternl.h" +#include "ddk/wdm.h"
#include "kernelbase.h" #include "wine/exception.h" @@ -1362,3 +1363,49 @@ BOOL WINAPI DECLSPEC_HOTPATCH QueryThreadpoolStackInformation( PTP_POOL pool, PT { return set_ntstatus( TpQueryPoolStackInformation( pool, stack_info )); } + + +/*********************************************************************** + * Context functions + + ***********************************************************************/ + + +/*********************************************************************** + * InitializeContext2 (kernelbase.@) + */ +BOOL WINAPI InitializeContext2( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length, + ULONG64 compaction_mask ) +{ + ULONG orig_length; + NTSTATUS status; + + TRACE( "buffer %p, context_flags %#x, context %p, ret_length %p, compaction_mask %s.\n", + buffer, context_flags, context, length, wine_dbgstr_longlong(compaction_mask) ); + + orig_length = *length; + + if ((status = RtlGetExtendedContextLength2( context_flags, length, compaction_mask ))) + return set_ntstatus( status ); + + if (!buffer || orig_length < *length) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + if ((status = RtlInitializeExtendedContext2( buffer, context_flags, (CONTEXT_EX **)context, compaction_mask ))) + return set_ntstatus( status ); + + *context = (CONTEXT *)((BYTE *)*context + (*(CONTEXT_EX **)context)->Legacy.Offset); + + return TRUE; +} + +/*********************************************************************** + * InitializeContext (kernelbase.@) + */ +BOOL WINAPI InitializeContext( void *buffer, DWORD context_flags, CONTEXT **context, DWORD *length ) +{ + return InitializeContext2( buffer, context_flags, context, length, ~(ULONG64)0 ); +} diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 1b212cdee7f..e875b560c6b 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -671,13 +671,16 @@ static const struct context_parameters ULONG arch_flag; ULONG supported_flags; ULONG context_size; /* sizeof(CONTEXT) */ + ULONG legacy_size; /* Legacy context size */ ULONG context_ex_size; /* sizeof(CONTEXT_EX) */ - ULONG alignment; + ULONG alignment; /* Used when computing size of context. */ + ULONG true_alignment; /* Used for actual alignment. */ + ULONG flags_offset; } arch_context_paramaters[] = { - {0x00100000, 0xd810005f, 0x4d0, 0x20, 7}, - {0x00010000, 0xd801007f, 0x2cc, 0x18, 3}, + {0x00100000, 0xd810005f, 0x4d0, 0x4d0, 0x20, 7, 0xf, 0x30}, + {0x00010000, 0xd801007f, 0x2cc, 0xcc, 0x18, 3, 0x3, 0}, };
static const struct context_parameters *context_get_parameters( ULONG context_flags ) @@ -736,3 +739,68 @@ ULONG64 WINAPI RtlGetExtendedContextLength( ULONG context_flags, ULONG *length ) { return RtlGetExtendedContextLength2( context_flags, length, ~(ULONG64)0 ); } + + +/********************************************************************** + * RtlInitializeExtendedContext2 (NTDLL.@) + */ +ULONG WINAPI RtlInitializeExtendedContext2( void *context, ULONG context_flags, CONTEXT_EX **context_ex, + ULONG64 compaction_mask ) +{ + const struct context_parameters *p; + ULONG64 supported_mask = 0; + CONTEXT_EX *c_ex; + + TRACE( "context %p, context_flags %#x, context_ex %p, compaction_mask %s.\n", + context, context_flags, context_ex, wine_dbgstr_longlong(compaction_mask)); + + if (!(p = context_get_parameters( context_flags ))) + return STATUS_INVALID_PARAMETER; + + if ((context_flags & 0x40) && !(supported_mask = RtlGetEnabledExtendedFeatures( ~(ULONG64)0 ))) + return STATUS_NOT_SUPPORTED; + + context = (void *)(((ULONG_PTR)context + p->true_alignment) & ~p->true_alignment); + *(ULONG *)((BYTE *)context + p->flags_offset) = context_flags; + + *context_ex = c_ex = (CONTEXT_EX *)((BYTE *)context + p->context_size); + c_ex->Legacy.Offset = c_ex->All.Offset = -(LONG)p->context_size; + c_ex->Legacy.Length = context_flags & 0x20 ? p->context_size : p->legacy_size; + + if (context_flags & 0x40) + { + XSTATE *xs; + + compaction_mask &= supported_mask; + + xs = (XSTATE *)(((ULONG_PTR)c_ex + p->context_ex_size + 63) & ~(ULONG_PTR)63); + c_ex->XState.Offset = (ULONG_PTR)xs - (ULONG_PTR)c_ex; + c_ex->XState.Length = offsetof(XSTATE, YmmContext); + memset( xs, 0, c_ex->XState.Length ); + compaction_mask &= supported_mask; + if (user_shared_data->XState.CompactionEnabled) + xs->CompactionMask = ((ULONG64)1 << 63) | compaction_mask; + + if (compaction_mask & (1 << XSTATE_AVX)) + c_ex->XState.Length += sizeof(YMMCONTEXT); + + c_ex->All.Length = p->context_size + c_ex->XState.Offset + c_ex->XState.Length; + } + else + { + c_ex->XState.Offset = 25; /* According to the tests, it is just 25 if CONTEXT_XSTATE is not specified. */ + c_ex->XState.Length = 0; + c_ex->All.Length = p->context_size + 24; /* sizeof(CONTEXT_EX) minus 8 alignment bytes on x64. */ + } + + return STATUS_SUCCESS; +} + + +/********************************************************************** + * RtlInitializeExtendedContext (NTDLL.@) + */ +ULONG WINAPI RtlInitializeExtendedContext( void *context, ULONG context_flags, CONTEXT_EX **context_ex ) +{ + return RtlInitializeExtendedContext2( context, context_flags, context_ex, ~(ULONG64)0 ); +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 08c6e1849a2..2a33368d7f8 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -757,6 +757,8 @@ @ stdcall RtlInitializeCriticalSection(ptr) @ stdcall RtlInitializeCriticalSectionAndSpinCount(ptr long) @ stdcall RtlInitializeCriticalSectionEx(ptr long long) +@ stdcall RtlInitializeExtendedContext(ptr long ptr) +@ stdcall RtlInitializeExtendedContext2(ptr long ptr int64) @ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr) @ stdcall RtlInitializeGenericTableAvl(ptr ptr ptr ptr ptr) @ stdcall RtlInitializeHandleTable(long long ptr) diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 0e00e889d41..c5a6b4e4d77 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -47,6 +47,9 @@ static void (WINAPI *pRtlSetUnhandledExceptionFilter)(PRTL_EXCEPTION_FILTER static ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64); static ULONG64 (WINAPI *pRtlGetExtendedContextLength)(ULONG context_flags, ULONG *length); static ULONG64 (WINAPI *pRtlGetExtendedContextLength2)(ULONG context_flags, ULONG *length, ULONG64 compaction_mask); +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 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); @@ -56,6 +59,10 @@ static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); static NTSTATUS (WINAPI *pNtClose)(HANDLE); static NTSTATUS (WINAPI *pNtSuspendProcess)(HANDLE process); static NTSTATUS (WINAPI *pNtResumeProcess)(HANDLE process); +static BOOL (WINAPI *pInitializeContext)(void *buffer, DWORD context_flags, CONTEXT **context, + DWORD *length); +static BOOL (WINAPI *pInitializeContext2)(void *buffer, DWORD context_flags, CONTEXT **context, + DWORD *length, ULONG64 compaction_mask);
#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
@@ -5469,6 +5476,7 @@ static const unsigned test_extended_context_spoil_data1[8] = {0x10, 0x20, 0x30, static const unsigned test_extended_context_spoil_data2[8] = {0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85};
static BOOL test_extended_context_modified_state; +static BOOL compaction_enabled;
static DWORD test_extended_context_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher) @@ -5477,14 +5485,8 @@ static DWORD test_extended_context_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGI CONTEXT_EX *xctx = (CONTEXT_EX *)(context + 1); unsigned int *context_ymm_data; DWORD expected_min_offset; - BOOL compaction; - int regs[4]; XSTATE *xs;
- /* Since we got xstates enabled by OS this cpuid level should be supported. */ - __cpuidex(regs, 0xd, 1); - compaction = regs[0] & 2; - ok((context->ContextFlags & (CONTEXT_FULL | CONTEXT_XSTATE)) == (CONTEXT_FULL | CONTEXT_XSTATE), "Got unexpected ContextFlags %#x.\n", context->ContextFlags);
@@ -5515,9 +5517,9 @@ static DWORD test_extended_context_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGI context_ymm_data = (unsigned int *)&xs->YmmContext; ok(!((ULONG_PTR)xs % 64), "Got unexpected xs %p.\n", xs);
- ok((compaction && (xs->CompactionMask & (expected_compaction_mask | 3)) == expected_compaction_mask) - || (!compaction && !xs->CompactionMask), "Got unexpected CompactionMask %s, compaction %#x.\n", - wine_dbgstr_longlong(xs->CompactionMask), compaction); + ok((compaction_enabled && (xs->CompactionMask & (expected_compaction_mask | 3)) == expected_compaction_mask) + || (!compaction_enabled && !xs->CompactionMask), "Got unexpected CompactionMask %s, compaction %#x.\n", + wine_dbgstr_longlong(xs->CompactionMask), compaction_enabled);
if (test_extended_context_modified_state) { @@ -5590,8 +5592,10 @@ static void test_extended_context(void) ULONG supported_flags; ULONG broken_flags; ULONG context_length; + ULONG legacy_length; ULONG context_ex_length; ULONG align; + ULONG flags_offset; } context_arch[] = { @@ -5600,24 +5604,34 @@ static void test_extended_context(void) 0xd800005f, 0xd8000000, 0x4d0, /* sizeof(CONTEXT) */ + 0x4d0, /* sizeof(CONTEXT) */ 0x20, /* sizeof(CONTEXT_EX) */ 7, + 0x30, }, { 0x00010000, /* CONTEXT_X86 */ 0xd800007f, 0xd8000000, 0x2cc, /* sizeof(CONTEXT) */ + 0xcc, /* offsetof(CONTEXT, ExtendedRegisters) */ 0x18, /* sizeof(CONTEXT_EX) */ 3, + 0, }, }; - ULONG expected_length, expected_length_xstate; - unsigned int i, address_offset, test; + ULONG expected_length, expected_length_xstate, context_flags, expected_offset; + 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; - ULONG ret, length; + CONTEXT_EX *context_ex; + CONTEXT *context; unsigned data[8]; ULONG flags; + XSTATE *xs; + BOOL bret;
address_offset = sizeof(void *) == 8 ? 2 : 1; *(void **)(except_code_set_ymm0 + address_offset) = data; @@ -5631,6 +5645,14 @@ static void test_extended_context(void)
enabled_features = pRtlGetEnabledExtendedFeatures(~(ULONG64)0);
+ if (enabled_features) + { + int regs[4]; + + __cpuidex(regs, 0xd, 1); + compaction_enabled = regs[0] & 2; + } + /* Test context manipulation functions. */ length = 0xdeadbeef; ret = pRtlGetExtendedContextLength(0, &length); @@ -5656,7 +5678,7 @@ static void test_extended_context(void) continue;
flags = context_arch[test].flag | (1 << i); - length = 0xdeadbeef; + length = length2 = 0xdeadbeef; ret = pRtlGetExtendedContextLength(flags, &length);
if ((context_arch[test].supported_flags & flags) || flags == context_arch[test].flag) @@ -5672,6 +5694,134 @@ static void test_extended_context(void) ok(ret == STATUS_INVALID_PARAMETER && length == 0xdeadbeef, "Got unexpected result ret %#x, length %#x, flags 0x%08x.\n", ret, length, flags); } + + SetLastError(0xdeadbeef); + bret = pInitializeContext(NULL, flags, NULL, &length2); + ok(!bret && length2 == length && GetLastError() + == (!ret ? ERROR_INSUFFICIENT_BUFFER : ERROR_INVALID_PARAMETER), + "Got unexpected bret %#x, length2 %#x, GetLastError() %u, flags %#x.\n", + bret, length2, GetLastError(), flags); + + if (GetLastError() == ERROR_INVALID_PARAMETER) + continue; + + SetLastError(0xdeadbeef); + context = (void *)0xdeadbeef; + length2 = expected_length - 1; + bret = pInitializeContext(context_buffer, flags, &context, &length2); + ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Got unexpected bret %#x, GetLastError() %u, flags %#x.\n", bret, GetLastError(), flags); + ok(context == (void *)0xdeadbeef, "Got unexpected context %p.\n", context); + + SetLastError(0xdeadbeef); + memset(context_buffer, 0xcc, sizeof(context_buffer)); + length2 = expected_length; + bret = pInitializeContext(context_buffer, flags, &context, &length2); + 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((BYTE *)context == context_buffer, "Got unexpected context %p, flags %#x.\n", context, 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); + + context_ex = (CONTEXT_EX *)(context_buffer + context_arch[test].context_length); + ok(context_ex->Legacy.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->Legacy.Offset, flags); + ok(context_ex->Legacy.Length == ((flags & 0x20) ? context_arch[test].context_length + : context_arch[test].legacy_length), + "Got unexpected Length %#x, flags %#x.\n", context_ex->Legacy.Length, flags); + ok(context_ex->All.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->All.Offset, flags); + + /* No extra 8 bytes in x64 CONTEXT_EX here. */ + ok(context_ex->All.Length == context_arch[test].context_length + context_arch[1].context_ex_length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->All.Length, flags); + + /* No idea why is it so. */ + ok(context_ex->XState.Offset == 25, + "Got unexpected Offset %d, flags %#x.\n", context_ex->XState.Offset, flags); + ok(!context_ex->XState.Length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->XState.Length, flags); + + + for (j = 0; j < context_arch[test].flags_offset; ++j) + { + if (context_buffer[j] != 0xcc) + { + ok(0, "Buffer data changed at offset %#x.\n", j); + break; + } + } + for (j = context_arch[test].flags_offset + sizeof(context_flags); + j < context_arch[test].context_length; ++j) + { + if (context_buffer[j] != 0xcc) + { + ok(0, "Buffer data changed at offset %#x.\n", j); + break; + } + } + for (j = context_arch[test].context_length + context_arch[test].context_ex_length; + j < sizeof(context_buffer); ++j) + { + if (context_buffer[j] != 0xcc) + { + ok(0, "Buffer data changed at offset %#x.\n", j); + break; + } + } + + memset(context_buffer2, 0xcc, sizeof(context_buffer2)); + ret2 = pRtlInitializeExtendedContext(context_buffer2, flags, &context_ex); + ok(!ret2, "Got unexpected ret2 %#x, flags %#x.\n", ret2, flags); + ok(!memcmp(context_buffer2, context_buffer, sizeof(context_buffer2)), + "Context data do not match, flags %#x.\n", flags); + + memset(context_buffer2, 0xcc, sizeof(context_buffer2)); + ret2 = pRtlInitializeExtendedContext(context_buffer2 + 2, flags, &context_ex); + ok(!ret2, "Got unexpected ret2 %#x, flags %#x.\n", ret2, flags); + + /* Buffer gets aligned to 16 bytes on x64, while returned context length suggests it should be 8. */ + align = test ? 4 : 16; + ok(!memcmp(context_buffer2 + align, context_buffer, + sizeof(context_buffer2) - align), + "Context data do not match, flags %#x.\n", flags); + + SetLastError(0xdeadbeef); + memset(context_buffer2, 0xcc, sizeof(context_buffer2)); + bret = pInitializeContext(context_buffer2 + 2, flags, &context, &length2); + 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); + + if (!pRtlInitializeExtendedContext2 || !pInitializeContext2) + { + static int once; + + if (!once++) + win_skip("InitializeContext2 is not available.\n"); + continue; + } + + 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); + ok(!memcmp(context_buffer2 + align, context_buffer, + sizeof(context_buffer2) - align), + "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); + 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); }
flags = context_arch[test].flag | 0x40; @@ -5683,6 +5833,10 @@ static void test_extended_context(void) { ok(ret == STATUS_NOT_SUPPORTED && length == 0xdeadbeef, "Got unexpected result ret %#x, length %#x.\n", ret, length); + + context_ex = (void *)0xdeadbeef; + ret2 = pRtlInitializeExtendedContext(context_buffer, flags, &context_ex); + ok(ret2 == STATUS_NOT_SUPPORTED, "Got unexpected result ret %#x, test %u.\n", ret2, test); continue; }
@@ -5692,39 +5846,156 @@ static void test_extended_context(void) if (!pRtlGetExtendedContextLength2) { win_skip("RtlGetExtendedContextLength2 is not available.\n"); - continue; } + else + { + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 7); + ok(!ret && length == expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
- length = 0xdeadbeef; - ret = pRtlGetExtendedContextLength2(flags, &length, 7); - ok(!ret && length == expected_length_xstate, - "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, ~0); + ok(!ret && length >= expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
- length = 0xdeadbeef; - ret = pRtlGetExtendedContextLength2(flags, &length, ~0); - ok(!ret && length >= expected_length_xstate, - "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 0); + ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
- length = 0xdeadbeef; - ret = pRtlGetExtendedContextLength2(flags, &length, 0); - ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), - "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 3); + ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
- length = 0xdeadbeef; - ret = pRtlGetExtendedContextLength2(flags, &length, 3); - ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT), - "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength2(flags, &length, 4); + ok(!ret && length == expected_length_xstate, + "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + }
- length = 0xdeadbeef; - ret = pRtlGetExtendedContextLength2(flags, &length, 4); - ok(!ret && length == expected_length_xstate, - "Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test); + pRtlGetExtendedContextLength(flags, &length); + SetLastError(0xdeadbeef); + bret = pInitializeContext(NULL, flags, NULL, &length2); + ok(!bret && length2 == length && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Got unexpected bret %#x, length2 %#x, GetLastError() %u, flags %#x.\n", + bret, length2, GetLastError(), flags); + + SetLastError(0xdeadbeef); + context = (void *)0xdeadbeef; + length2 = length - 1; + bret = pInitializeContext(context_buffer, flags, &context, &length2); + ok(!bret && GetLastError() == ERROR_INSUFFICIENT_BUFFER && length2 == length && context == (void *)0xdeadbeef, + "Got unexpected bret %#x, GetLastError() %u, length2 %#x, flags %#x.\n", + bret, GetLastError(), length2, flags); + + SetLastError(0xdeadbeef); + memset(context_buffer, 0xcc, sizeof(context_buffer)); + length2 = length + 1; + bret = pInitializeContext(context_buffer, flags, &context, &length2); + ok(bret && GetLastError() == 0xdeadbeef, + "Got unexpected bret %#x, GetLastError() %u, flags %#x.\n", bret, GetLastError(), flags); + ok(length2 == length, "Got unexpexted length %#x.\n", length); + ok((BYTE *)context == context_buffer, "Got unexpected context %p.\n", context); + + context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset); + ok(context_flags == flags, "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags); + + context_ex = (CONTEXT_EX *)(context_buffer + context_arch[test].context_length); + ok(context_ex->Legacy.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->Legacy.Offset, flags); + + if (!test) + { + /* Contains garbage on x86. */ + ok(context_ex->Legacy.Length == context_arch[test].context_length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->Legacy.Length, flags); + } + + expected_offset = (((ULONG_PTR)context + context_arch[test].context_length + + context_arch[test].context_ex_length + 63) & ~(ULONG64)63) - (ULONG_PTR)context + - context_arch[test].context_length; + ok(context_ex->XState.Offset == expected_offset, + "Got unexpected Offset %d, flags %#x.\n", context_ex->XState.Offset, flags); + ok(context_ex->XState.Length >= sizeof(XSTATE), + "Got unexpected Length %#x, flags %#x.\n", context_ex->XState.Length, flags); + + ok(context_ex->All.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->All.Offset, flags); + /* No extra 8 bytes in x64 CONTEXT_EX here. */ + ok(context_ex->All.Length == context_arch[test].context_length + + context_ex->XState.Offset + context_ex->XState.Length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->All.Length, flags); + + 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) | enabled_features : 0), + "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])); + + if (pRtlGetExtendedContextLength2) + { + memset(context_buffer, 0xcc, sizeof(context_buffer)); + pRtlGetExtendedContextLength2(flags, &length, 0); + SetLastError(0xdeadbeef); + memset(context_buffer, 0xcc, sizeof(context_buffer)); + length2 = length; + bret = pInitializeContext2(context_buffer, flags, &context, &length2, 0); + ok(bret && GetLastError() == 0xdeadbeef, + "Got unexpected bret %#x, GetLastError() %u, flags %#x.\n", bret, GetLastError(), flags); + ok(length2 == length, "Got unexpexted length %#x.\n", length); + ok((BYTE *)context == context_buffer, "Got unexpected context %p.\n", context); + + context_flags = *(DWORD *)(context_buffer + context_arch[test].flags_offset); + ok(context_flags == flags, "Got unexpected ContextFlags %#x, flags %#x.\n", context_flags, flags); + + context_ex = (CONTEXT_EX *)(context_buffer + context_arch[test].context_length); + ok(context_ex->Legacy.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->Legacy.Offset, flags); + + if (!test) + { + /* Contains garbage on x86. */ + ok(context_ex->Legacy.Length == context_arch[test].context_length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->Legacy.Length, flags); + } + + expected_offset = (((ULONG_PTR)context + context_arch[test].context_length + + context_arch[test].context_ex_length + 63) & ~(ULONG64)63) - (ULONG_PTR)context + - context_arch[test].context_length; + ok(context_ex->XState.Offset == expected_offset, + "Got unexpected Offset %d, flags %#x.\n", context_ex->XState.Offset, flags); + ok(context_ex->XState.Length == sizeof(XSTATE) - sizeof(YMMCONTEXT), + "Got unexpected Length %#x, flags %#x.\n", context_ex->XState.Length, flags); + + ok(context_ex->All.Offset == -(int)context_arch[test].context_length, + "Got unexpected Offset %d, flags %#x.\n", context_ex->All.Offset, flags); + /* No extra 8 bytes in x64 CONTEXT_EX here. */ + ok(context_ex->All.Length == context_arch[test].context_length + + context_ex->XState.Offset + context_ex->XState.Length, + "Got unexpected Length %#x, flags %#x.\n", context_ex->All.Length, flags); + + 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), + "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])); + } }
+ length = 0xdeadbeef; + ret = pRtlGetExtendedContextLength(context_arch[0].flag | context_arch[1].flag, &length); + ok(ret == STATUS_INVALID_PARAMETER && length == 0xdeadbeef, "Got unexpected result ret %#x, length %#x.\n", + ret, length); + if (0) { /* Crashes on Windows. */ pRtlGetExtendedContextLength(CONTEXT_FULL, NULL); + length = sizeof(context_buffer); + pInitializeContext(context_buffer, CONTEXT_FULL, NULL, &length); + pInitializeContext(context_buffer, CONTEXT_FULL, &context, NULL); }
if (!(enabled_features & (1 << XSTATE_AVX))) @@ -5758,6 +6029,7 @@ static void test_extended_context(void) START_TEST(exception) { HMODULE hntdll = GetModuleHandleA("ntdll.dll"); + HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); #if defined(__x86_64__) HMODULE hmsvcrt = LoadLibraryA("msvcrt.dll"); #endif @@ -5800,11 +6072,18 @@ START_TEST(exception) X(RtlGetEnabledExtendedFeatures); X(RtlGetExtendedContextLength); X(RtlGetExtendedContextLength2); + X(RtlInitializeExtendedContext); + X(RtlInitializeExtendedContext2); #undef X
- pIsWow64Process = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process"); +#define X(f) p##f = (void*)GetProcAddress(hkernel32, #f) + X(IsWow64Process); if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
+ X(InitializeContext); + X(InitializeContext2); +#undef X + if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler) have_vectored_api = TRUE; else diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 45024a3a8da..163e041065f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1122,6 +1122,8 @@ @ stdcall RtlInitUnicodeString(ptr wstr) @ stdcall RtlInitUnicodeStringEx(ptr wstr) @ stdcall RtlInitializeBitMap(ptr ptr long) +@ stdcall RtlInitializeExtendedContext(ptr long ptr) +@ stdcall RtlInitializeExtendedContext2(ptr long ptr int64) @ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr) @ stdcall RtlInitializeGenericTableAvl(ptr ptr ptr ptr ptr) @ stub RtlInitializeRangeList diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index fa0f42aadef..b8a51fd7e61 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1836,6 +1836,8 @@ HANDLE WINAPI PsGetProcessInheritedFromUniqueProcessId(PEPROCESS); BOOLEAN WINAPI PsGetVersion(ULONG*,ULONG*,ULONG*,UNICODE_STRING*); NTSTATUS WINAPI PsTerminateSystemThread(NTSTATUS);
+ULONG WINAPI RtlInitializeExtendedContext(void*,ULONG,CONTEXT_EX**); +ULONG WINAPI RtlInitializeExtendedContext2(void*,ULONG,CONTEXT_EX**,ULONG64); ULONG64 WINAPI RtlGetExtendedContextLength(ULONG,ULONG*); ULONG64 WINAPI RtlGetExtendedContextLength2(ULONG,ULONG*,ULONG64);
diff --git a/include/winbase.h b/include/winbase.h index f2177ada1e4..9957cd43bb6 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2379,6 +2379,8 @@ WINBASEAPI BOOL WINAPI HeapWalk(HANDLE,LPPROCESS_HEAP_ENTRY); WINBASEAPI BOOL WINAPI InitAtomTable(DWORD); WINADVAPI BOOL WINAPI InitializeAcl(PACL,DWORD,DWORD); WINBASEAPI VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE); +WINBASEAPI BOOL WINAPI InitializeContext(void *,DWORD,CONTEXT **,DWORD *); +WINBASEAPI BOOL WINAPI InitializeContext2(void *,DWORD,CONTEXT **,DWORD *,ULONG64); WINBASEAPI void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit); WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *,DWORD); WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(CRITICAL_SECTION *,DWORD,DWORD);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=77505
Your paranoid android.
=== debiant (32 bit report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f870 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 75000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13591 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 89000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b28 / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
=== debiant (32 bit Chinese:China report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f870 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 75000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13591 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 89000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b28 / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15 process.c:1608: Test failed: Console:winRight expected 79, but got 80
=== debiant (32 bit WoW report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f870 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 75000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13591 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 89000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b28 / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
=== debiant (64 bit WoW report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f870 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 75000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13591 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 89000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b28 / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
Signed-off-by: Paul Gofman pgofman@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);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=77506
Your paranoid android.
=== debiant (32 bit report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f9f0 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 76000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13620 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8c000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b3c / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 1 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
=== debiant (32 bit Chinese:China report) ===
kernel32: change.c:350: Test failed: should be ready loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f9f0 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 76000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13620 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8c000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b3c / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 1 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
=== debiant (32 bit WoW report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f9f0 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 76000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13620 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8c000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b3c / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 1 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15
=== debiant (64 bit WoW report) ===
kernel32: loader.c:3932: Test failed: ntdll.dll:0: wrong OptionalHeader.AddressOfEntryPoint 5f9f0 / 5f3d0 loader.c:3941: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].VirtualAddress 76000 / 74000 loader.c:3946: Test failed: ntdll.dll:0: wrong OptionalHeader.DataDirectory[i].Size 13620 / 13459 loader.c:3941: Test failed: ntdll.dll:1: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8a000 / 88000 loader.c:3941: Test failed: ntdll.dll:2: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8b000 / 89000 loader.c:3941: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].VirtualAddress 8c000 / 8a000 loader.c:3946: Test failed: ntdll.dll:5: wrong OptionalHeader.DataDirectory[i].Size 3b3c / 3af4 loader.c:3952: Test failed: ntdll.dll: wrong section 0 loader.c:3952: Test failed: ntdll.dll: wrong section 1 loader.c:3952: Test failed: ntdll.dll: wrong section 2 loader.c:3952: Test failed: ntdll.dll: wrong section 3 loader.c:3952: Test failed: ntdll.dll: wrong section 4 loader.c:3952: Test failed: ntdll.dll: wrong section 5 loader.c:3952: Test failed: ntdll.dll: wrong section 6 loader.c:3952: Test failed: ntdll.dll: wrong section 7 loader.c:3952: Test failed: ntdll.dll: wrong section 8 loader.c:3952: Test failed: ntdll.dll: wrong section 9 loader.c:3952: Test failed: ntdll.dll: wrong section 10 loader.c:3952: Test failed: ntdll.dll: wrong section 11 loader.c:3952: Test failed: ntdll.dll: wrong section 12 loader.c:3952: Test failed: ntdll.dll: wrong section 13 loader.c:3952: Test failed: ntdll.dll: wrong section 14 loader.c:3952: Test failed: ntdll.dll: wrong section 15