From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/kernel32/tests/actctx.c | 115 +++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+)
diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index 8bd459dccca..66360284d42 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -33,7 +33,12 @@ static BOOL (WINAPI *pQueryActCtxSettingsW)(DWORD,HANDLE,LPCWSTR,LPCWSTR,LPWST
static NTSTATUS (NTAPI *pRtlActivateActivationContext)(ULONG,HANDLE,ULONG_PTR *); static NTSTATUS (NTAPI *pRtlActivateActivationContextEx)(ULONG,TEB *,HANDLE,ULONG_PTR *); +static PRTL_ACTIVATION_CONTEXT_STACK_FRAME (FASTCALL *pRtlActivateActivationContextUnsafeFast)(PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, + PVOID); +static VOID (FASTCALL *pRtlDeactivateActivationContextUnsafeFast)(PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED); +static NTSTATUS (WINAPI *pRtlGetVersion)(RTL_OSVERSIONINFOEXW *); 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 *); @@ -604,6 +609,16 @@ static const WCHAR wndClass3W[] = static WCHAR app_dir[MAX_PATH], exe_path[MAX_PATH], work_dir[MAX_PATH], work_dir_subdir[MAX_PATH]; static WCHAR app_manifest_path[MAX_PATH], manifest_path[MAX_PATH], depmanifest_path[MAX_PATH];
+#define is_win8_plus() check_win_version(6, 2) +static BOOL check_win_version(int min_major, int min_minor) +{ + RTL_OSVERSIONINFOEXW ver; + + ver.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); + pRtlGetVersion(&ver); + return ver.dwMajorVersion > min_major || (ver.dwMajorVersion == min_major && ver.dwMinorVersion >= min_minor); +} + static BOOL create_manifest_file(const char *filename, const char *manifest, int manifest_len, const char *depfile, const char *depmanifest) { @@ -3167,7 +3182,11 @@ static BOOL init_funcs(void) hLibrary = GetModuleHandleA("ntdll.dll"); X(RtlActivateActivationContext); X(RtlActivateActivationContextEx); + X(RtlActivateActivationContextUnsafeFast); + X(RtlDeactivateActivationContextUnsafeFast); + X(RtlGetVersion); X(RtlFindActivationContextSectionString); + X(RtlFreeThreadActivationContextStack); X(RtlCreateUnicodeStringFromAsciiz); X(RtlFreeUnicodeString); X(RtlQueryInformationActiveActivationContext); @@ -4597,6 +4616,101 @@ 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; + + /* RtlActivateActivationContextUnsafeFast() has a different prototype on <= Win7 */ + if (!is_win8_plus()) + { + skip("Test requires Win8+.\n"); + return; + } + + 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"); + + frame_extended1.Size = sizeof(frame_extended1); + frame_extended1.Format = 0xdeadbeef; + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended1, context1); + ok(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 == 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 == 0x20, "Got unexpected Flags %#lx.\n", frame_extended1.Frame.Flags); + + ret = GetCurrentActCtx(¤t_context); + ok(current_context == context1, "Got unexpected handle.\n"); + ReleaseActCtx(current_context); + + frame_extended2.Size = sizeof(frame_extended2); + frame_extended2.Format = 0xdeadbeef; + frame = pRtlActivateActivationContextUnsafeFast(&frame_extended2, context2); + ok(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 == 0xdeadbeef, "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 == 0x20, "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, "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; @@ -4637,5 +4751,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); }