@@ -79,6 +79,7 @@ static BOOL (WINAPI *pSetXStateFeaturesMask)(CONTEXT *context, DWORD64 feat
79
79
static BOOL (WINAPI *pGetXStateFeaturesMask)(CONTEXT *context, DWORD64 *feature_mask);
80
80
static BOOL (WINAPI *pWaitForDebugEventEx)(DEBUG_EVENT *, DWORD);
81
81
82
+ static void *pKiUserApcDispatcher;
82
83
static void *pKiUserExceptionDispatcher;
83
84
84
85
#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
@@ -4930,6 +4931,94 @@ static void test_KiUserExceptionDispatcher(void)
4930
4931
ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError());
4931
4932
}
4932
4933
4934
+
4935
+ static BYTE saved_KiUserApcDispatcher[12];
4936
+ static BOOL apc_called;
4937
+
4938
+ static void CALLBACK apc_func( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
4939
+ {
4940
+ ok( arg1 == 0x1234, "wrong arg1 %Ix\n", arg1 );
4941
+ ok( arg2 == 0x5678, "wrong arg2 %Ix\n", arg2 );
4942
+ ok( arg3 == 0xdeadbeef, "wrong arg3 %Ix\n", arg3 );
4943
+ apc_called = TRUE;
4944
+ }
4945
+
4946
+ static void * WINAPI hook_KiUserApcDispatcher(CONTEXT *context)
4947
+ {
4948
+ struct machine_frame *frame = (struct machine_frame *)(context + 1);
4949
+ UINT i;
4950
+
4951
+ trace( "context %p, context->Rip %#Ix, context->Rsp %#Ix (%#Ix), ContextFlags %#lx.\n",
4952
+ context, context->Rip, context->Rsp,
4953
+ (char *)context->Rsp - (char *)context, context->ContextFlags );
4954
+
4955
+ ok( context->P1Home == 0x1234, "wrong p1 %#Ix\n", context->P1Home );
4956
+ ok( context->P2Home == 0x5678, "wrong p2 %#Ix\n", context->P2Home );
4957
+ ok( context->P3Home == 0xdeadbeef, "wrong p3 %#Ix\n", context->P3Home );
4958
+ ok( context->P4Home == (ULONG_PTR)apc_func, "wrong p4 %#Ix / %p\n", context->P4Home, apc_func );
4959
+
4960
+ /* machine frame offset varies between Windows versions */
4961
+ for (i = 0; i < 16; i++)
4962
+ {
4963
+ if (frame->rip == context->Rip) break;
4964
+ frame = (struct machine_frame *)((ULONG64 *)frame + 2);
4965
+ }
4966
+ trace( "machine frame %p (%#Ix): rip=%#Ix cs=%#Ix eflags=%#Ix rsp=%#Ix ss=%#Ix\n",
4967
+ frame, (char *)frame - (char *)context,
4968
+ frame->rip, frame->cs, frame->eflags, frame->rsp, frame->ss );
4969
+ ok( frame->rip == context->Rip, "wrong rip %#Ix / %#Ix\n", frame->rip, context->Rip );
4970
+ ok( frame->rsp == context->Rsp, "wrong rsp %#Ix / %#Ix\n", frame->rsp, context->Rsp );
4971
+
4972
+ hook_called = TRUE;
4973
+ memcpy( pKiUserApcDispatcher, saved_KiUserApcDispatcher, sizeof(saved_KiUserApcDispatcher));
4974
+ return pKiUserApcDispatcher;
4975
+ }
4976
+
4977
+ static void test_KiUserApcDispatcher(void)
4978
+ {
4979
+ BYTE hook_trampoline[] =
4980
+ {
4981
+ 0x48, 0x89, 0xe1, /* mov %rsp,%rcx */
4982
+ 0x48, 0xb8, /* movabs hook_KiUserApcDispatcher,%rax */
4983
+ 0,0,0,0,0,0,0,0, /* offset 5 */
4984
+ 0xff, 0xd0, /* callq *rax */
4985
+ 0xff, 0xe0, /* jmpq *rax */
4986
+ };
4987
+
4988
+ BYTE patched_KiUserApcDispatcher[12];
4989
+ DWORD old_protect;
4990
+ BYTE *ptr;
4991
+ BOOL ret;
4992
+
4993
+ *(ULONG_PTR *)(hook_trampoline + 5) = (ULONG_PTR)hook_KiUserApcDispatcher;
4994
+ memcpy(code_mem, hook_trampoline, sizeof(hook_trampoline));
4995
+
4996
+ ret = VirtualProtect( pKiUserApcDispatcher, sizeof(saved_KiUserApcDispatcher),
4997
+ PAGE_EXECUTE_READWRITE, &old_protect );
4998
+ ok( ret, "Got unexpected ret %#x, GetLastError() %lu.\n", ret, GetLastError() );
4999
+
5000
+ memcpy( saved_KiUserApcDispatcher, pKiUserApcDispatcher, sizeof(saved_KiUserApcDispatcher) );
5001
+ ptr = patched_KiUserApcDispatcher;
5002
+ /* mov $code_mem, %rax */
5003
+ *ptr++ = 0x48;
5004
+ *ptr++ = 0xb8;
5005
+ *(void **)ptr = code_mem;
5006
+ ptr += sizeof(ULONG64);
5007
+ /* jmp *rax */
5008
+ *ptr++ = 0xff;
5009
+ *ptr++ = 0xe0;
5010
+ memcpy( pKiUserApcDispatcher, patched_KiUserApcDispatcher, sizeof(patched_KiUserApcDispatcher) );
5011
+
5012
+ hook_called = FALSE;
5013
+ apc_called = FALSE;
5014
+ pNtQueueApcThread( GetCurrentThread(), apc_func, 0x1234, 0x5678, 0xdeadbeef );
5015
+ SleepEx( 0, TRUE );
5016
+ ok( apc_called, "APC was not called\n" );
5017
+ ok( hook_called, "hook was not called\n" );
5018
+
5019
+ VirtualProtect( pKiUserApcDispatcher, sizeof(saved_KiUserApcDispatcher), old_protect, &old_protect );
5020
+ }
5021
+
4933
5022
static BOOL got_nested_exception, got_prev_frame_exception;
4934
5023
static void *nested_exception_initial_frame;
4935
5024
@@ -11476,6 +11565,7 @@ START_TEST(exception)
11476
11565
X(RtlGetExtendedFeaturesMask);
11477
11566
X(RtlCopyContext);
11478
11567
X(RtlCopyExtendedContext);
11568
+ X(KiUserApcDispatcher);
11479
11569
X(KiUserExceptionDispatcher);
11480
11570
#undef X
11481
11571
@@ -11637,6 +11727,7 @@ START_TEST(exception)
11637
11727
test_dpe_exceptions();
11638
11728
test_wow64_context();
11639
11729
test_KiUserExceptionDispatcher();
11730
+ test_KiUserApcDispatcher();
11640
11731
test_nested_exception();
11641
11732
test_collided_unwind();
11642
11733
0 commit comments