From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/tests/sync.c | 30 ++++++++++++++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 1 + dlls/kernelbase/thread.c | 9 +++++++++ include/winbase.h | 1 + 5 files changed, 42 insertions(+)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 83c374d2254..3bb49206c6b 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1213,6 +1213,7 @@ @ stdcall -import QueryUnbiasedInterruptTime(ptr) @ stub QueryWin31IniFilesMappedToRegistry @ stdcall -import QueueUserAPC(ptr long long) +@ stdcall -import QueueUserAPC2(ptr long long long) @ stdcall -import QueueUserWorkItem(ptr ptr long) @ stdcall -import RaiseException(long long long ptr) @ stdcall -import RaiseFailFastException(ptr ptr long) diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 25ed4aec6a0..49f5002f651 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -56,6 +56,8 @@ static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
+static DWORD (WINAPI *pQueueUserAPC2)(PAPCFUNC,HANDLE,ULONG_PTR,QUEUE_USER_APC_FLAGS); + static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG); static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); @@ -2959,6 +2961,33 @@ static void test_QueueUserAPC(void) status = pNtTestAlert(); ok(!status, "got %lx\n", status); ok(apc_count == 1, "APC count %u\n", apc_count); + + if (!pQueueUserAPC2) + { + win_skip("QueueUserAPC2 is not available.\n"); + return; + } + + apc_count = 0; + ret = pQueueUserAPC2(user_apc, GetCurrentThread(), 0, QUEUE_USER_APC_FLAGS_NONE); + ok(ret, "QueueUserAPC failed err %lu\n", GetLastError()); + ok(!apc_count, "got %d.\n", apc_count); + SleepEx( 0, TRUE ); + ok(apc_count == 1, "got %d.\n", apc_count); + + apc_count = 0; + ret = pQueueUserAPC2(user_apc, GetCurrentThread(), 0, QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC); + if (sizeof(void *) == 4) + ok(!ret && GetLastError() == ERROR_NOT_SUPPORTED, "got ret %lu, error %lu.\n", ret, GetLastError()); + else + ok(ret, "got error %lu.\n", GetLastError()); + + if (ret) + { + todo_wine ok(apc_count == 1, "got %d.\n", apc_count); + SleepEx( 0, TRUE ); + ok(apc_count == 1, "got %d.\n", apc_count); + } }
START_TEST(sync) @@ -2985,6 +3014,7 @@ START_TEST(sync) pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared"); pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive"); pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); + pQueueUserAPC2 = (void *)GetProcAddress(hdll, "QueueUserAPC2"); pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 545c30a1eb8..7681815b7e7 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1264,6 +1264,7 @@ @ stdcall QueryWorkingSet(long ptr long) @ stdcall QueryWorkingSetEx(long ptr long) @ stdcall QueueUserAPC(ptr long long) +@ stdcall QueueUserAPC2(ptr long long long) @ stdcall QueueUserWorkItem(ptr ptr long) # @ stub QuirkGetData # @ stub QuirkGetData2 diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c index bc8210bd43a..dbde4dcfaf3 100644 --- a/dlls/kernelbase/thread.c +++ b/dlls/kernelbase/thread.c @@ -369,6 +369,15 @@ DWORD WINAPI DECLSPEC_HOTPATCH QueueUserAPC( PAPCFUNC func, HANDLE thread, ULONG }
+/*********************************************************************** + * QueueUserAPC2 (kernelbase.@) + */ +DWORD WINAPI DECLSPEC_HOTPATCH QueueUserAPC2( PAPCFUNC func, HANDLE thread, ULONG_PTR data, QUEUE_USER_APC_FLAGS flags ) +{ + return set_ntstatus( NtQueueApcThreadEx2( thread, NULL, flags, call_user_apc, (ULONG_PTR)func, data, 0 )); +} + + /*********************************************************************** * QueryThreadCycleTime (kernelbase.@) */ diff --git a/include/winbase.h b/include/winbase.h index 29a3ea8fbce..65499319704 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2293,6 +2293,7 @@ WINBASEAPI BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*); WINBASEAPI BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*); WINBASEAPI BOOL WINAPI QueryUmsThreadInformation(PUMS_CONTEXT,UMS_THREAD_INFO_CLASS,PVOID,ULONG,PULONG); WINBASEAPI DWORD WINAPI QueueUserAPC(PAPCFUNC,HANDLE,ULONG_PTR); +WINBASEAPI DWORD WINAPI QueueUserAPC2(PAPCFUNC,HANDLE,ULONG_PTR,QUEUE_USER_APC_FLAGS); WINBASEAPI BOOL WINAPI QueueUserWorkItem(LPTHREAD_START_ROUTINE,PVOID,ULONG); WINBASEAPI void WINAPI RaiseException(DWORD,DWORD,DWORD,const ULONG_PTR *); WINBASEAPI HANDLE WINAPI ReOpenFile(HANDLE,DWORD,DWORD,DWORD);