From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/kernel32/tests/actctx.c | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+)
diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 050b39516d9..947804a02d8 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -33,7 +33,11 @@ static BOOL (WINAPI *pQueryActCtxSettingsW)(DWORD,HANDLE,LPCWSTR,LPCWSTR,LPWST
static NTSTATUS (NTAPI *pRtlActivateActivationContext)(ULONG,struct _ACTIVATION_CONTEXT *,ULONG_PTR *); static NTSTATUS (NTAPI *pRtlActivateActivationContextEx)(ULONG,TEB *,struct _ACTIVATION_CONTEXT *,ULONG_PTR *); +static PRTL_ACTIVATION_CONTEXT_STACK_FRAME (FASTCALL *pRtlActivateActivationContextUnsafeFast)(PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, + struct _ACTIVATION_CONTEXT *); +static VOID (FASTCALL *pRtlDeactivateActivationContextUnsafeFast)(PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED); static NTSTATUS(NTAPI *pRtlFindActivationContextSectionString)(DWORD,const GUID *,ULONG,PUNICODE_STRING,PACTCTX_SECTION_KEYED_DATA); +static VOID (NTAPI *pRtlFreeThreadActivationContextStack)(VOID); static BOOLEAN (NTAPI *pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, PCSZ); static VOID (NTAPI *pRtlFreeUnicodeString)(PUNICODE_STRING); static NTSTATUS(NTAPI *pRtlQueryInformationActiveActivationContext)(ULONG,PVOID,SIZE_T,SIZE_T *); @@ -3160,7 +3164,10 @@ static BOOL init_funcs(void) hLibrary = GetModuleHandleA("ntdll.dll"); X(RtlActivateActivationContext); X(RtlActivateActivationContextEx); + X(RtlActivateActivationContextUnsafeFast); + X(RtlDeactivateActivationContextUnsafeFast); X(RtlFindActivationContextSectionString); + X(RtlFreeThreadActivationContextStack); X(RtlCreateUnicodeStringFromAsciiz); X(RtlFreeUnicodeString); X(RtlQueryInformationActiveActivationContext); @@ -4590,6 +4597,119 @@ static void test_RtlQueryInformationActiveActivationContext(void) ReleaseActCtx( context ); }
+static void test_RtlActivateActivationContextUnsafeFast(void) +{ + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED frame_extended1 = {0}, frame_extended2 = {0}; + HANDLE context1, context2, current_context; + RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; + BOOL ret; + + ret = GetCurrentActCtx(¤t_context); + ok(ret, "GetCurrentActCtx failed.\n"); + ok(!current_context, "Got unexpected handle.\n"); + + if (!create_manifest_file("test1.manifest", manifest1, -1, NULL, NULL)) + { + skip("Could not create manifest file 1.\n"); + return; + } + if (!create_manifest_file("test2.manifest", manifest1_1, -1, NULL, NULL)) + { + skip("Could not create manifest file 2.\n"); + DeleteFileA("test1.manifest"); + return; + } + context1 = test_create("test1.manifest"); + ok(context1 != INVALID_HANDLE_VALUE, "Failed to create context, error %lu.\n", GetLastError()); + DeleteFileA("test1.manifest"); + context2 = test_create("test2.manifest"); + ok(context2 != INVALID_HANDLE_VALUE, "Failed to create context, error %lu.\n", GetLastError()); + DeleteFileA("test2.manifest"); + + /* Size and Format don't seem to be checked */ + frame_extended1.Size = 0; + frame_extended1.Format = 0xdeadbeef; + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended1, context1); + /* RtlActivateActivationContextUnsafeFast() has a different prototype on <= Win7 */ + ok(frame == &frame_extended1.Frame || broken(frame != &frame_extended1.Frame), "Got unexpected frame.\n"); + ok(frame_extended1.Size == 0, "Got unexpected Size %#Ix.\n", frame_extended1.Size); + ok(frame_extended1.Format == 0xdeadbeef, "Got unexpected Format %#lx.\n", frame_extended1.Format); + ok(!frame_extended1.Frame.Previous, "Got unexpected Previous.\n"); + ok(frame_extended1.Frame.ActivationContext == context1, "Got unexpected ActivationContext.\n"); + ok(!(frame_extended1.Frame.Flags & NTDLL_ACTCTX_STACK_FRAME_HEAP_ALLOCATED), + "Got unexpected Flags %#lx.\n", frame_extended1.Frame.Flags); + + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context1, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + pRtlDeactivateActivationContextUnsafeFast(&frame_extended1); + ret = GetCurrentActCtx(¤t_context); + ok(ret, "GetCurrentActCtx failed.\n"); + ok(!current_context, "Got unexpected handle.\n"); + + /* Normal call */ + frame_extended1.Size = sizeof(frame_extended1); + frame_extended1.Format = 0; + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended1, context1); + /* RtlActivateActivationContextUnsafeFast() has a different prototype on <= Win7 */ + ok(frame == &frame_extended1.Frame || broken(frame != &frame_extended1.Frame), "Got unexpected frame.\n"); + ok(frame_extended1.Size == sizeof(frame_extended1), "Got unexpected Size %#Ix.\n", frame_extended1.Size); + ok(frame_extended1.Format == 0, "Got unexpected Format %#lx.\n", frame_extended1.Format); + ok(!frame_extended1.Frame.Previous, "Got unexpected Previous.\n"); + ok(frame_extended1.Frame.ActivationContext == context1, "Got unexpected ActivationContext.\n"); + ok(!(frame_extended1.Frame.Flags & NTDLL_ACTCTX_STACK_FRAME_HEAP_ALLOCATED), + "Got unexpected Flags %#lx.\n", frame_extended1.Frame.Flags); + + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context1, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + /* Activate another activation context */ + frame_extended2.Size = sizeof(frame_extended2); + frame_extended2.Format = 0; + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended2, context2); + ok(frame == &frame_extended2.Frame || broken(frame != &frame_extended2.Frame), "Got unexpected frame %p.\n", frame); + ok(frame_extended2.Size == sizeof(frame_extended2), "Got unexpected Size %#Ix.\n", frame_extended2.Size); + ok(frame_extended2.Format == 0, "Got unexpected Format %#lx.\n", frame_extended2.Format); + ok(frame_extended2.Frame.Previous == &frame_extended1.Frame, "Got unexpected Previous.\n"); + ok(frame_extended2.Frame.ActivationContext == context2, "Got unexpected ActivationContext.\n"); + ok(!(frame_extended2.Frame.Flags & NTDLL_ACTCTX_STACK_FRAME_HEAP_ALLOCATED), + "Got unexpected Flags %#lx.\n", frame_extended2.Frame.Flags); + + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context2, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + pRtlDeactivateActivationContextUnsafeFast(&frame_extended2); + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context1, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + pRtlDeactivateActivationContextUnsafeFast(&frame_extended1); + ret = GetCurrentActCtx(¤t_context); + ok(ret, "GetCurrentActCtx failed.\n"); + ok(!current_context, "Got unexpected handle.\n"); + + /* Test freeing an unsafe frame. Not crashing means RtlFreeThreadActivationContextStack() must + * be able to handle it, most likely by checking the frame flags */ + frame_extended1.Size = sizeof(frame_extended1); + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended1, context1); + ok(frame == &frame_extended1.Frame || broken(frame != &frame_extended1.Frame), "Got unexpected frame.\n"); + + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context1, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + pRtlFreeThreadActivationContextStack(); + ret = GetCurrentActCtx(¤t_context); + ok(ret, "GetCurrentActCtx failed.\n"); + ok(!current_context, "Got unexpected handle.\n"); + + ReleaseActCtx(context2); + ReleaseActCtx(context1); +} + START_TEST(actctx) { int argc; @@ -4630,5 +4750,6 @@ START_TEST(actctx) test_compatibility(); test_settings(); test_RtlQueryInformationActiveActivationContext(); + test_RtlActivateActivationContextUnsafeFast(); for (int i = 1; i <= 6; i++) run_child_process_two_dll(i); }