19 #include <winpr/wtypes.h>
20 #include <winpr/thread.h>
21 #include <winpr/synch.h>
29 static void CALLBACK userApc(ULONG_PTR arg)
31 UserApcArg* userArg = (UserApcArg*)arg;
32 userArg->called = TRUE;
35 static DWORD WINAPI uncleanThread(LPVOID lpThreadParameter)
38 UserApcArg* userArg = (UserApcArg*)lpThreadParameter;
39 if (!QueueUserAPC((PAPCFUNC)userApc, _GetCurrentThread(), (ULONG_PTR)lpThreadParameter))
41 userArg->error = TRUE;
48 static DWORD WINAPI cleanThread(LPVOID lpThreadParameter)
65 static VOID CALLBACK Timer1APCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
67 UncleanCloseData* data = (UncleanCloseData*)lpArg;
69 (void)CloseHandle(data->timer2);
73 static VOID CALLBACK Timer2APCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
75 UncleanCloseData* data = (UncleanCloseData*)lpArg;
79 static DWORD closeHandleTest(LPVOID lpThreadParameter)
81 LARGE_INTEGER dueTime = { 0 };
82 UncleanCloseData* data = (UncleanCloseData*)lpThreadParameter;
83 data->endTest = FALSE;
85 dueTime.QuadPart = -500;
86 if (!SetWaitableTimer(data->timer1, &dueTime, 0, Timer1APCProc, lpThreadParameter, FALSE))
89 dueTime.QuadPart = -900;
90 if (!SetWaitableTimer(data->timer2, &dueTime, 0, Timer2APCProc, lpThreadParameter, FALSE))
93 while (!data->endTest)
100 int TestSynchAPC(
int argc,
char* argv[])
102 HANDLE thread = NULL;
103 UserApcArg userApcArg;
105 userApcArg.error = FALSE;
106 userApcArg.called = FALSE;
112 if (!QueueUserAPC((PAPCFUNC)userApc, _GetCurrentThread(), (ULONG_PTR)&userApcArg))
115 if (SleepEx(100, FALSE) != 0)
118 if (SleepEx(100, TRUE) != WAIT_IO_COMPLETION)
121 if (!userApcArg.called)
124 userApcArg.called = FALSE;
127 thread = CreateThread(NULL, 0, uncleanThread, &userApcArg, 0, NULL);
130 (void)WaitForSingleObject(thread, INFINITE);
131 (void)CloseHandle(thread);
133 if (userApcArg.called || userApcArg.error)
137 thread = CreateThread(NULL, 0, cleanThread, &userApcArg, 0, NULL);
141 if (!QueueUserAPC((PAPCFUNC)userApc, thread, (ULONG_PTR)&userApcArg))
144 (void)WaitForSingleObject(thread, INFINITE);
145 (void)CloseHandle(thread);
147 if (!userApcArg.called)
152 memset(&uncleanCloseData, 0,
sizeof(uncleanCloseData));
153 uncleanCloseData.timer1 = CreateWaitableTimerA(NULL, FALSE, NULL);
154 if (!uncleanCloseData.timer1)
157 uncleanCloseData.timer2 = CreateWaitableTimerA(NULL, FALSE, NULL);
158 if (!uncleanCloseData.timer2)
161 thread = CreateThread(NULL, 0, closeHandleTest, &uncleanCloseData, 0, NULL);
165 (void)WaitForSingleObject(thread, INFINITE);
166 (void)CloseHandle(thread);
168 if (uncleanCloseData.timer1Calls != 1 || uncleanCloseData.timer2Calls != 0)
170 (void)CloseHandle(uncleanCloseData.timer1);