FreeRDP
TestSynchWaitableTimerAPC.c
1 
2 #include <winpr/crt.h>
3 #include <winpr/synch.h>
4 #include <winpr/sysinfo.h>
5 
6 static int g_Count = 0;
7 static HANDLE g_Event = NULL;
8 
9 struct apc_data
10 {
11  UINT32 StartTime;
12 };
13 typedef struct apc_data APC_DATA;
14 
15 static VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
16 {
17  APC_DATA* apcData = NULL;
18  UINT32 CurrentTime = GetTickCount();
19  WINPR_UNUSED(dwTimerLowValue);
20  WINPR_UNUSED(dwTimerHighValue);
21 
22  if (!lpArg)
23  return;
24 
25  apcData = (APC_DATA*)lpArg;
26  printf("TimerAPCProc: time: %" PRIu32 "\n", CurrentTime - apcData->StartTime);
27  g_Count++;
28 
29  if (g_Count >= 5)
30  {
31  (void)SetEvent(g_Event);
32  }
33 }
34 
35 int TestSynchWaitableTimerAPC(int argc, char* argv[])
36 {
37  int status = -1;
38  DWORD rc = 0;
39  HANDLE hTimer = NULL;
40  BOOL bSuccess = 0;
41  LARGE_INTEGER due = { 0 };
42  APC_DATA apcData = { 0 };
43  WINPR_UNUSED(argc);
44  WINPR_UNUSED(argv);
45  g_Event = CreateEvent(NULL, TRUE, FALSE, NULL);
46 
47  if (!g_Event)
48  {
49  printf("Failed to create event\n");
50  goto cleanup;
51  }
52 
53  hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
54  if (!hTimer)
55  goto cleanup;
56 
57  due.QuadPart = -1000 * 100LL; /* 0.1 seconds */
58  apcData.StartTime = GetTickCount();
59  bSuccess = SetWaitableTimer(hTimer, &due, 10, TimerAPCProc, &apcData, FALSE);
60 
61  if (!bSuccess)
62  goto cleanup;
63 
64  /* nothing shall happen after 0.12 second, because thread is not in alertable state */
65  rc = WaitForSingleObject(g_Event, 120);
66  if (rc != WAIT_TIMEOUT)
67  goto cleanup;
68 
69  for (;;)
70  {
71  rc = WaitForSingleObjectEx(g_Event, INFINITE, TRUE);
72  if (rc == WAIT_OBJECT_0)
73  break;
74 
75  if (rc == WAIT_IO_COMPLETION)
76  continue;
77 
78  printf("Failed to wait for completion event (%" PRIu32 ")\n", GetLastError());
79  goto cleanup;
80  }
81 
82  status = 0;
83 cleanup:
84 
85  if (hTimer)
86  (void)CloseHandle(hTimer);
87 
88  if (g_Event)
89  (void)CloseHandle(g_Event);
90 
91  return status;
92 }