1 /*
2 * Synchronization tests
3 *
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winternl.h>
27
28 #include "wine/test.h"
29
30 #ifdef __REACTOS__
31 #define QueryDepthSList(x) RtlQueryDepthSList(x)
32 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y)
33 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x)
34 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x)
35 #endif
36
37 #undef __fastcall
38 #define __fastcall __stdcall
39
40 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
41 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
42 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
43 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
44 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
45 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
46
47 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
48 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
49 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG);
50 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
51 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
52
53 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK);
54 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK);
55 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK);
56 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
57 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
58 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
59 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
60
61 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
62 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
63 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *);
64 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
65 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first,
66 PSLIST_ENTRY last, ULONG count);
67 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first,
68 PSLIST_ENTRY last, ULONG count);
69
70 #ifdef __i386__
71
72 #include "pshpack1.h"
73 struct fastcall_thunk
74 {
75 BYTE pop_edx; /* popl %edx (ret addr) */
76 BYTE pop_eax; /* popl %eax (func) */
77 BYTE pop_ecx; /* popl %ecx (param 1) */
78 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */
79 WORD jmp_eax; /* jmp *%eax */
80 };
81 #include "poppack.h"
82
83 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d);
84
init_fastcall_thunk(void)85 static void init_fastcall_thunk(void)
86 {
87 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
88 thunk->pop_edx = 0x5a; /* popl %edx */
89 thunk->pop_eax = 0x58; /* popl %eax */
90 thunk->pop_ecx = 0x59; /* popl %ecx */
91 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */
92 thunk->xchg[1] = 0x14;
93 thunk->xchg[2] = 0x24;
94 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */
95 call_fastcall_func4 = (void *)thunk;
96 }
97
98 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
99 (const void *)(b), (const void *)(c), (const void *)(d))
100
101 #else /* __i386__ */
102
103 #define init_fastcall_thunk() do { } while(0)
104 #define call_func4(func, a, b, c, d) func(a, b, c, d)
105
106 #endif /* __i386__ */
107
test_signalandwait(void)108 static void test_signalandwait(void)
109 {
110 DWORD r;
111 HANDLE event[2], semaphore[2], file;
112 int i;
113
114 /* invalid parameters */
115 r = SignalObjectAndWait(NULL, NULL, 0, 0);
116 ok( r == WAIT_FAILED, "should fail\n");
117
118 event[0] = CreateEventW(NULL, 0, 0, NULL);
119 event[1] = CreateEventW(NULL, 1, 1, NULL);
120
121 ok( event[0] && event[1], "failed to create event flags\n");
122
123 r = SignalObjectAndWait(event[0], NULL, 0, FALSE);
124 ok( r == WAIT_FAILED, "should fail\n");
125
126 r = SignalObjectAndWait(NULL, event[0], 0, FALSE);
127 ok( r == WAIT_FAILED, "should fail\n");
128
129
130 /* valid parameters */
131 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
132 ok( r == WAIT_OBJECT_0, "should succeed\n");
133
134 /* event[0] is now signalled - we repeat this test multiple times
135 * to ensure that the wineserver handles this situation properly. */
136 for (i = 0; i < 10000; i++)
137 {
138 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
139 ok(r == WAIT_OBJECT_0, "should succeed\n");
140 }
141
142 /* event[0] is not signalled */
143 r = WaitForSingleObject(event[0], 0);
144 ok( r == WAIT_TIMEOUT, "event was signalled\n");
145
146 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
147 ok( r == WAIT_OBJECT_0, "should succeed\n");
148
149 /* clear event[1] and check for a timeout */
150 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
151 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
152 ok( r == WAIT_TIMEOUT, "should timeout\n");
153
154 CloseHandle(event[0]);
155 CloseHandle(event[1]);
156
157 /* semaphores */
158 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL );
159 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL );
160 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
161
162 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
163 ok( r == WAIT_OBJECT_0, "should succeed\n");
164
165 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
166 ok( r == WAIT_FAILED, "should fail\n");
167
168 r = ReleaseSemaphore(semaphore[0],1,NULL);
169 ok( r == FALSE, "should fail\n");
170
171 r = ReleaseSemaphore(semaphore[1],1,NULL);
172 ok( r == TRUE, "should succeed\n");
173
174 CloseHandle(semaphore[0]);
175 CloseHandle(semaphore[1]);
176
177 /* try a registry key */
178 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
179 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
180 r = SignalObjectAndWait(file, file, 0, FALSE);
181 ok( r == WAIT_FAILED, "should fail\n");
182 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
183 CloseHandle(file);
184 }
185
test_mutex(void)186 static void test_mutex(void)
187 {
188 DWORD wait_ret;
189 BOOL ret;
190 HANDLE hCreated;
191 HANDLE hOpened;
192 int i;
193 DWORD failed = 0;
194
195 SetLastError(0xdeadbeef);
196 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
197 ok(hOpened == NULL, "OpenMutex succeeded\n");
198 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
199
200 SetLastError(0xdeadbeef);
201 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex");
202 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
203
204 SetLastError(0xdeadbeef);
205 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
206 todo_wine
207 ok(hOpened == NULL, "OpenMutex succeeded\n");
208 todo_wine
209 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
210
211 SetLastError(0xdeadbeef);
212 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex");
213 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
214 wait_ret = WaitForSingleObject(hOpened, INFINITE);
215 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
216 CloseHandle(hOpened);
217
218 for(i=0; i < 31; i++)
219 {
220 wait_ret = WaitForSingleObject(hCreated, INFINITE);
221 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
222 }
223
224 SetLastError(0xdeadbeef);
225 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
226 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
227 wait_ret = WaitForSingleObject(hOpened, INFINITE);
228 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
229 CloseHandle(hOpened);
230
231 for (i = 0; i < 32; i++)
232 {
233 SetLastError(0xdeadbeef);
234 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex");
235 if(hOpened != NULL)
236 {
237 SetLastError(0xdeadbeef);
238 ret = ReleaseMutex(hOpened);
239 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
240 CloseHandle(hOpened);
241 }
242 else
243 {
244 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
245 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
246 else
247 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
248 ReleaseMutex(hCreated);
249 failed |=0x1 << i;
250 }
251 }
252
253 todo_wine
254 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
255
256 SetLastError(0xdeadbeef);
257 ret = ReleaseMutex(hCreated);
258 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
259 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
260
261 /* test case sensitivity */
262
263 SetLastError(0xdeadbeef);
264 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX");
265 ok(!hOpened, "OpenMutex succeeded\n");
266 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
267
268 SetLastError(0xdeadbeef);
269 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex");
270 ok(!hOpened, "OpenMutex succeeded\n");
271 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
272
273 SetLastError(0xdeadbeef);
274 hOpened = OpenMutexA(READ_CONTROL, FALSE, NULL);
275 ok(!hOpened, "OpenMutex succeeded\n");
276 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
277
278 SetLastError(0xdeadbeef);
279 hOpened = OpenMutexW(READ_CONTROL, FALSE, NULL);
280 ok(!hOpened, "OpenMutex succeeded\n");
281 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
282
283 SetLastError(0xdeadbeef);
284 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex");
285 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
286 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
287 CloseHandle(hOpened);
288
289 SetLastError(0xdeadbeef);
290 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX");
291 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
292 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
293 CloseHandle(hOpened);
294
295 CloseHandle(hCreated);
296 }
297
test_slist(void)298 static void test_slist(void)
299 {
300 struct item
301 {
302 SLIST_ENTRY entry;
303 int value;
304 } item1, item2, item3, *item;
305 SLIST_HEADER slist_header;
306 SLIST_ENTRY *entry;
307 USHORT size;
308 int i;
309
310 item1.value = 1;
311 item2.value = 2;
312 item3.value = 3;
313
314 memset(&slist_header, 0xff, sizeof(slist_header));
315 InitializeSListHead(&slist_header);
316 size = QueryDepthSList(&slist_header);
317 ok(size == 0, "Expected size == 0, got %u\n", size);
318
319 /* test PushEntry, PopEntry and Flush */
320 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
321 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
322 size = QueryDepthSList(&slist_header);
323 ok(size == 1, "Expected size == 1, got %u\n", size);
324
325 entry = InterlockedPushEntrySList(&slist_header, &item2.entry);
326 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
327 item = CONTAINING_RECORD(entry, struct item, entry);
328 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
329 size = QueryDepthSList(&slist_header);
330 ok(size == 2, "Expected size == 2, got %u\n", size);
331
332 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
333 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
334 item = CONTAINING_RECORD(entry, struct item, entry);
335 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
336 size = QueryDepthSList(&slist_header);
337 ok(size == 3, "Expected size == 3, got %u\n", size);
338
339 entry = InterlockedPopEntrySList(&slist_header);
340 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
341 item = CONTAINING_RECORD(entry, struct item, entry);
342 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
343 size = QueryDepthSList(&slist_header);
344 ok(size == 2, "Expected size == 2, got %u\n", size);
345
346 entry = InterlockedFlushSList(&slist_header);
347 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
348 item = CONTAINING_RECORD(entry, struct item, entry);
349 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
350 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
351 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
352 size = QueryDepthSList(&slist_header);
353 ok(size == 0, "Expected size == 0, got %u\n", size);
354 entry = InterlockedPopEntrySList(&slist_header);
355 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
356
357 /* test RtlInterlockedPushListSList */
358 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
359 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
360 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42);
361 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
362 item = CONTAINING_RECORD(entry, struct item, entry);
363 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
364 size = QueryDepthSList(&slist_header);
365 ok(size == 43, "Expected size == 43, got %u\n", size);
366
367 entry = InterlockedPopEntrySList(&slist_header);
368 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
369 item = CONTAINING_RECORD(entry, struct item, entry);
370 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
371 size = QueryDepthSList(&slist_header);
372 ok(size == 42, "Expected size == 42, got %u\n", size);
373
374 entry = InterlockedPopEntrySList(&slist_header);
375 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
376 item = CONTAINING_RECORD(entry, struct item, entry);
377 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
378 size = QueryDepthSList(&slist_header);
379 ok(size == 41, "Expected size == 41, got %u\n", size);
380
381 entry = InterlockedPopEntrySList(&slist_header);
382 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
383 item = CONTAINING_RECORD(entry, struct item, entry);
384 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
385 size = QueryDepthSList(&slist_header);
386 ok(size == 40, "Expected size == 40, got %u\n", size);
387
388 entry = InterlockedPopEntrySList(&slist_header);
389 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
390 size = QueryDepthSList(&slist_header);
391 ok(size == 40, "Expected size == 40, got %u\n", size);
392
393 entry = InterlockedFlushSList(&slist_header);
394 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
395 size = QueryDepthSList(&slist_header);
396 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size);
397
398 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
399 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
400 entry = InterlockedFlushSList(&slist_header);
401 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
402 item = CONTAINING_RECORD(entry, struct item, entry);
403 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
404 size = QueryDepthSList(&slist_header);
405 ok(size == 0, "Expected size == 0, got %u\n", size);
406
407 /* test RtlInterlockedPushListSListEx */
408 if (pRtlInterlockedPushListSListEx)
409 {
410 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
411 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
412 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42);
413 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
414 item = CONTAINING_RECORD(entry, struct item, entry);
415 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
416 size = QueryDepthSList(&slist_header);
417 ok(size == 43, "Expected size == 43, got %u\n", size);
418
419 entry = InterlockedFlushSList(&slist_header);
420 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
421 item = CONTAINING_RECORD(entry, struct item, entry);
422 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
423 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
424 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
425 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
426 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
427 size = QueryDepthSList(&slist_header);
428 ok(size == 0, "Expected size == 0, got %u\n", size);
429 }
430 else
431 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
432
433 /* test with a lot of items */
434 for (i = 0; i < 65536; i++)
435 {
436 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
437 item->value = i + 1;
438 entry = InterlockedPushEntrySList(&slist_header, &item->entry);
439 if (i)
440 {
441 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
442 item = CONTAINING_RECORD(entry, struct item, entry);
443 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
444 }
445 else
446 {
447 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
448 }
449 size = QueryDepthSList(&slist_header);
450 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size);
451 }
452
453 entry = InterlockedFlushSList(&slist_header);
454 for (i = 65536; i > 0; i--)
455 {
456 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
457 item = CONTAINING_RECORD(entry, struct item, entry);
458 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
459 entry = item->entry.Next;
460 HeapFree(GetProcessHeap(), 0, item);
461 }
462 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
463 size = QueryDepthSList(&slist_header);
464 ok(size == 0, "Expected size == 0, got %u\n", size);
465 entry = InterlockedPopEntrySList(&slist_header);
466 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
467 }
468
test_event(void)469 static void test_event(void)
470 {
471 HANDLE handle, handle2;
472 SECURITY_ATTRIBUTES sa;
473 SECURITY_DESCRIPTOR sd;
474 ACL acl;
475 DWORD ret;
476 BOOL val;
477
478 /* no sd */
479 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
480 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
481 CloseHandle(handle);
482
483 sa.nLength = sizeof(sa);
484 sa.lpSecurityDescriptor = &sd;
485 sa.bInheritHandle = FALSE;
486
487 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
488
489 /* blank sd */
490 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
491 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
492 CloseHandle(handle);
493
494 /* sd with NULL dacl */
495 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
496 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
497 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
498 CloseHandle(handle);
499
500 /* sd with empty dacl */
501 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
502 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
503 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
504 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
505 CloseHandle(handle);
506
507 /* test case sensitivity */
508
509 SetLastError(0xdeadbeef);
510 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
511 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
512 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
513
514 SetLastError(0xdeadbeef);
515 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
516 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
517 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
518 CloseHandle( handle2 );
519
520 SetLastError(0xdeadbeef);
521 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
522 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
523 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
524 CloseHandle( handle2 );
525
526 SetLastError(0xdeadbeef);
527 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
528 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
529 CloseHandle( handle2 );
530
531 SetLastError(0xdeadbeef);
532 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
533 ok( !handle2, "OpenEvent succeeded\n");
534 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
535
536 SetLastError(0xdeadbeef);
537 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, NULL );
538 ok( !handle2, "OpenEvent succeeded\n");
539 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
540
541 SetLastError(0xdeadbeef);
542 handle2 = OpenEventW( EVENT_ALL_ACCESS, FALSE, NULL );
543 ok( !handle2, "OpenEvent succeeded\n");
544 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
545
546 CloseHandle( handle );
547
548 /* resource notifications are events too */
549
550 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
551 {
552 trace( "memory resource notifications not supported\n" );
553 return;
554 }
555 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
556 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
557 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
558 ret = pQueryMemoryResourceNotification( handle, &val );
559 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
560 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
561
562 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
563 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
564 ret = WaitForSingleObject( handle, 10 );
565 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
566
567 val = ~0;
568 ret = pQueryMemoryResourceNotification( handle, &val );
569 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
570 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
571 ret = CloseHandle( handle );
572 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
573
574 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
575 val = ~0;
576 ret = pQueryMemoryResourceNotification( handle, &val );
577 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
578 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
579 CloseHandle( handle );
580 }
581
test_semaphore(void)582 static void test_semaphore(void)
583 {
584 HANDLE handle, handle2;
585
586 /* test case sensitivity */
587
588 SetLastError(0xdeadbeef);
589 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
590 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
591 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
592
593 SetLastError(0xdeadbeef);
594 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
595 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
596 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
597 CloseHandle( handle2 );
598
599 SetLastError(0xdeadbeef);
600 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
601 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
602 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
603 CloseHandle( handle2 );
604
605 SetLastError(0xdeadbeef);
606 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
607 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
608 CloseHandle( handle2 );
609
610 SetLastError(0xdeadbeef);
611 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
612 ok( !handle2, "OpenSemaphore succeeded\n");
613 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
614
615 SetLastError(0xdeadbeef);
616 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
617 ok( !handle2, "OpenSemaphore succeeded\n");
618 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
619
620 SetLastError(0xdeadbeef);
621 handle2 = OpenSemaphoreW( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
622 ok( !handle2, "OpenSemaphore succeeded\n");
623 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
624
625 CloseHandle( handle );
626 }
627
test_waitable_timer(void)628 static void test_waitable_timer(void)
629 {
630 HANDLE handle, handle2;
631
632 /* test case sensitivity */
633
634 SetLastError(0xdeadbeef);
635 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
636 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
637 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
638
639 SetLastError(0xdeadbeef);
640 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
641 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
642 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
643 CloseHandle( handle2 );
644
645 SetLastError(0xdeadbeef);
646 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
647 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
648 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
649 CloseHandle( handle2 );
650
651 SetLastError(0xdeadbeef);
652 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
653 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
654 CloseHandle( handle2 );
655
656 SetLastError(0xdeadbeef);
657 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
658 ok( !handle2, "OpenWaitableTimer succeeded\n");
659 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
660
661 SetLastError(0xdeadbeef);
662 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, NULL );
663 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError());
664 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
665
666 SetLastError(0xdeadbeef);
667 handle2 = OpenWaitableTimerW( TIMER_ALL_ACCESS, FALSE, NULL );
668 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError());
669 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
670
671 CloseHandle( handle );
672 }
673
674 static HANDLE sem = 0;
675
iocp_callback(DWORD dwErrorCode,DWORD dwNumberOfBytesTransferred,LPOVERLAPPED lpOverlapped)676 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
677 {
678 ReleaseSemaphore(sem, 1, NULL);
679 }
680
681 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
682
test_iocp_callback(void)683 static void test_iocp_callback(void)
684 {
685 char temp_path[MAX_PATH];
686 char filename[MAX_PATH];
687 DWORD ret;
688 BOOL retb;
689 static const char prefix[] = "pfx";
690 HANDLE hFile;
691 HMODULE hmod = GetModuleHandleA("kernel32.dll");
692 DWORD bytesWritten;
693 const char *buffer = "12345678123456781234567812345678";
694 OVERLAPPED overlapped;
695
696 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
697 if(!p_BindIoCompletionCallback) {
698 win_skip("BindIoCompletionCallback not found in this DLL\n");
699 return;
700 }
701
702 sem = CreateSemaphoreW(NULL, 0, 1, NULL);
703 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
704
705 ret = GetTempPathA(MAX_PATH, temp_path);
706 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
707 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
708
709 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
710 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
711
712 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
713 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
714 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
715
716 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
717 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
718 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
719
720 ret = CloseHandle(hFile);
721 ok( ret, "CloseHandle: error %d\n", GetLastError());
722 ret = DeleteFileA(filename);
723 ok( ret, "DeleteFileA: error %d\n", GetLastError());
724
725 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
726 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
727 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
728
729 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
730 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
731
732 memset(&overlapped, 0, sizeof(overlapped));
733 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
734 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
735
736 ret = WaitForSingleObject(sem, 5000);
737 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
738 CloseHandle(sem);
739
740 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
741 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
742 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
743 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
744 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
745 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
746
747 ret = CloseHandle(hFile);
748 ok( ret, "CloseHandle: error %d\n", GetLastError());
749 ret = DeleteFileA(filename);
750 ok( ret, "DeleteFileA: error %d\n", GetLastError());
751
752 /* win2k3 requires the Flags parameter to be zero */
753 SetLastError(0xdeadbeef);
754 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
755 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
756 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
757 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
758 if (!retb)
759 ok(GetLastError() == ERROR_INVALID_PARAMETER,
760 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
761 else
762 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
763 ret = CloseHandle(hFile);
764 ok( ret, "CloseHandle: error %d\n", GetLastError());
765 ret = DeleteFileA(filename);
766 ok( ret, "DeleteFileA: error %d\n", GetLastError());
767
768 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
769 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
770 ok(GetLastError() == ERROR_INVALID_HANDLE ||
771 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
772 "Last error is %d\n", GetLastError());
773 }
774
timer_queue_cb1(PVOID p,BOOLEAN timedOut)775 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
776 {
777 int *pn = p;
778 disable_success_count
779 ok(timedOut, "Timer callbacks should always time out\n");
780 ++*pn;
781 }
782
783 struct timer_queue_data1
784 {
785 int num_calls;
786 int max_calls;
787 HANDLE q, t;
788 };
789
timer_queue_cb2(PVOID p,BOOLEAN timedOut)790 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
791 {
792 struct timer_queue_data1 *d = p;
793 ok(timedOut, "Timer callbacks should always time out\n");
794 if (d->t && ++d->num_calls == d->max_calls)
795 {
796 BOOL ret;
797 SetLastError(0xdeadbeef);
798 /* Note, XP SP2 does *not* do any deadlock checking, so passing
799 INVALID_HANDLE_VALUE here will just hang. */
800 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
801 ok(!ret, "DeleteTimerQueueTimer\n");
802 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
803 }
804 }
805
timer_queue_cb3(PVOID p,BOOLEAN timedOut)806 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
807 {
808 struct timer_queue_data1 *d = p;
809 ok(timedOut, "Timer callbacks should always time out\n");
810 if (d->t && ++d->num_calls == d->max_calls)
811 {
812 /* Basically kill the timer since it won't have time to run
813 again. */
814 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0);
815 ok(ret, "ChangeTimerQueueTimer\n");
816 }
817 }
818
timer_queue_cb4(PVOID p,BOOLEAN timedOut)819 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
820 {
821 struct timer_queue_data1 *d = p;
822 ok(timedOut, "Timer callbacks should always time out\n");
823 if (d->t)
824 {
825 /* This tests whether a timer gets flagged for deletion before
826 or after the callback runs. If we start this timer with a
827 period of zero (run once), then ChangeTimerQueueTimer will
828 fail if the timer is already flagged. Hence we really run
829 only once. Otherwise we will run multiple times. */
830 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50);
831 ok(ret, "ChangeTimerQueueTimer\n");
832 ++d->num_calls;
833 }
834 }
835
timer_queue_cb5(PVOID p,BOOLEAN timedOut)836 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
837 {
838 DWORD_PTR delay = (DWORD_PTR) p;
839 ok(timedOut, "Timer callbacks should always time out\n");
840 if (delay)
841 Sleep(delay);
842 }
843
timer_queue_cb6(PVOID p,BOOLEAN timedOut)844 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
845 {
846 struct timer_queue_data1 *d = p;
847 ok(timedOut, "Timer callbacks should always time out\n");
848 /* This tests an original implementation bug where a deleted timer may get
849 to run, but it is tricky to set up. */
850 if (d->q && d->num_calls++ == 0)
851 {
852 /* First run: delete ourselves, then insert and remove a timer
853 that goes in front of us in the sorted timeout list. Once
854 removed, we will still timeout at the faster timer's due time,
855 but this should be a no-op if we are bug-free. There should
856 not be a second run. We can test the value of num_calls later. */
857 BOOL ret;
858 HANDLE t;
859
860 /* The delete will pend while we are in this callback. */
861 SetLastError(0xdeadbeef);
862 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
863 ok(!ret, "DeleteTimerQueueTimer\n");
864 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
865
866 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
867 ok(ret, "CreateTimerQueueTimer\n");
868 ok(t != NULL, "CreateTimerQueueTimer\n");
869
870 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
871 ok(ret, "DeleteTimerQueueTimer\n");
872
873 /* Now we stay alive by hanging around in the callback. */
874 Sleep(500);
875 }
876 }
877
test_timer_queue(void)878 static void test_timer_queue(void)
879 {
880 HANDLE q, t0, t1, t2, t3, t4, t5;
881 int n0, n1, n2, n3, n4, n5;
882 struct timer_queue_data1 d1, d2, d3, d4;
883 HANDLE e, et1, et2;
884 BOOL ret, ret0;
885
886 /* Test asynchronous deletion of the queue. */
887 q = CreateTimerQueue();
888 ok(q != NULL, "CreateTimerQueue\n");
889
890 SetLastError(0xdeadbeef);
891 ret = DeleteTimerQueueEx(q, NULL);
892 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
893 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
894 GetLastError());
895
896 /* Test synchronous deletion of the queue and running timers. */
897 q = CreateTimerQueue();
898 ok(q != NULL, "CreateTimerQueue\n");
899
900 /* Not called. */
901 t0 = NULL;
902 n0 = 0;
903 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0);
904 ok(ret, "CreateTimerQueueTimer\n");
905 ok(t0 != NULL, "CreateTimerQueueTimer\n");
906 ret0 = DeleteTimerQueueTimer(q, t0, NULL);
907 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
908 broken(ret0), /* Win 2000 & XP & 2003 */
909 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
910
911 /* Called once. */
912 t1 = NULL;
913 n1 = 0;
914 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0);
915 ok(ret, "CreateTimerQueueTimer\n");
916 ok(t1 != NULL, "CreateTimerQueueTimer\n");
917
918 /* A slow one. */
919 t2 = NULL;
920 n2 = 0;
921 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0);
922 ok(ret, "CreateTimerQueueTimer\n");
923 ok(t2 != NULL, "CreateTimerQueueTimer\n");
924
925 /* A fast one. */
926 t3 = NULL;
927 n3 = 0;
928 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0);
929 ok(ret, "CreateTimerQueueTimer\n");
930 ok(t3 != NULL, "CreateTimerQueueTimer\n");
931
932 /* Start really late (it won't start). */
933 t4 = NULL;
934 n4 = 0;
935 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0);
936 ok(ret, "CreateTimerQueueTimer\n");
937 ok(t4 != NULL, "CreateTimerQueueTimer\n");
938
939 /* Start soon, but delay so long it won't run again. */
940 t5 = NULL;
941 n5 = 0;
942 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0);
943 ok(ret, "CreateTimerQueueTimer\n");
944 ok(t5 != NULL, "CreateTimerQueueTimer\n");
945
946 /* Give them a chance to do some work. */
947 Sleep(500);
948
949 /* Test deleting a once-only timer. */
950 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
951 ok(ret, "DeleteTimerQueueTimer\n");
952
953 /* A periodic timer. */
954 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
955 ok(ret, "DeleteTimerQueueTimer\n");
956
957 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
958 ok(ret, "DeleteTimerQueueEx\n");
959 todo_wine
960 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
961 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
962 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
963 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
964 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
965
966 /* Test synchronous deletion of the timer/queue with event trigger. */
967 e = CreateEventW(NULL, TRUE, FALSE, NULL);
968 et1 = CreateEventW(NULL, TRUE, FALSE, NULL);
969 et2 = CreateEventW(NULL, TRUE, FALSE, NULL);
970 if (!e || !et1 || !et2)
971 {
972 skip("Failed to create timer queue descruction event\n");
973 return;
974 }
975
976 q = CreateTimerQueue();
977 ok(q != NULL, "CreateTimerQueue\n");
978
979 /* Run once and finish quickly (should be done when we delete it). */
980 t1 = NULL;
981 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
982 ok(ret, "CreateTimerQueueTimer\n");
983 ok(t1 != NULL, "CreateTimerQueueTimer\n");
984
985 /* Run once and finish slowly (shouldn't be done when we delete it). */
986 t2 = NULL;
987 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
988 ok(ret, "CreateTimerQueueTimer\n");
989 ok(t2 != NULL, "CreateTimerQueueTimer\n");
990
991 /* Run once and finish quickly (should be done when we delete it). */
992 t3 = NULL;
993 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
994 ok(ret, "CreateTimerQueueTimer\n");
995 ok(t3 != NULL, "CreateTimerQueueTimer\n");
996
997 /* Run once and finish slowly (shouldn't be done when we delete it). */
998 t4 = NULL;
999 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
1000 ok(ret, "CreateTimerQueueTimer\n");
1001 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1002
1003 /* Give them a chance to start. */
1004 Sleep(400);
1005
1006 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1007 even if the timer is finished. */
1008 SetLastError(0xdeadbeef);
1009 ret = DeleteTimerQueueTimer(q, t1, NULL);
1010 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1011 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1012 GetLastError());
1013
1014 SetLastError(0xdeadbeef);
1015 ret = DeleteTimerQueueTimer(q, t2, NULL);
1016 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1017 ok(GetLastError() == ERROR_IO_PENDING,
1018 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1019 GetLastError());
1020
1021 SetLastError(0xdeadbeef);
1022 ret = DeleteTimerQueueTimer(q, t3, et1);
1023 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
1024 ok(GetLastError() == 0xdeadbeef,
1025 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
1026 GetLastError());
1027 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
1028 "Timer destruction event not triggered\n");
1029
1030 SetLastError(0xdeadbeef);
1031 ret = DeleteTimerQueueTimer(q, t4, et2);
1032 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1033 ok(GetLastError() == ERROR_IO_PENDING,
1034 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1035 GetLastError());
1036 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
1037 "Timer destruction event not triggered\n");
1038
1039 SetLastError(0xdeadbeef);
1040 ret = DeleteTimerQueueEx(q, e);
1041 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1042 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1043 GetLastError());
1044 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
1045 "Queue destruction event not triggered\n");
1046 CloseHandle(e);
1047
1048 /* Test deleting/changing a timer in execution. */
1049 q = CreateTimerQueue();
1050 ok(q != NULL, "CreateTimerQueue\n");
1051
1052 /* Test changing a once-only timer before it fires (this is allowed,
1053 whereas after it fires you cannot). */
1054 n1 = 0;
1055 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0);
1056 ok(ret, "CreateTimerQueueTimer\n");
1057 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1058 ret = ChangeTimerQueueTimer(q, t1, 0, 0);
1059 ok(ret, "ChangeTimerQueueTimer\n");
1060
1061 d2.t = t2 = NULL;
1062 d2.num_calls = 0;
1063 d2.max_calls = 3;
1064 d2.q = q;
1065 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0);
1066 d2.t = t2;
1067 ok(ret, "CreateTimerQueueTimer\n");
1068 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1069
1070 d3.t = t3 = NULL;
1071 d3.num_calls = 0;
1072 d3.max_calls = 4;
1073 d3.q = q;
1074 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0);
1075 d3.t = t3;
1076 ok(ret, "CreateTimerQueueTimer\n");
1077 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1078
1079 d4.t = t4 = NULL;
1080 d4.num_calls = 0;
1081 d4.q = q;
1082 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0);
1083 d4.t = t4;
1084 ok(ret, "CreateTimerQueueTimer\n");
1085 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1086
1087 Sleep(500);
1088
1089 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1090 ok(ret, "DeleteTimerQueueEx\n");
1091 ok(n1 == 1, "ChangeTimerQueueTimer\n");
1092 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
1093 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
1094 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
1095
1096 /* Test an obscure bug that was in the original implementation. */
1097 q = CreateTimerQueue();
1098 ok(q != NULL, "CreateTimerQueue\n");
1099
1100 /* All the work is done in the callback. */
1101 d1.t = t1 = NULL;
1102 d1.num_calls = 0;
1103 d1.q = q;
1104 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION);
1105 d1.t = t1;
1106 ok(ret, "CreateTimerQueueTimer\n");
1107 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1108
1109 Sleep(750);
1110
1111 SetLastError(0xdeadbeef);
1112 ret = DeleteTimerQueueEx(q, NULL);
1113 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1114 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1115 GetLastError());
1116 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
1117
1118 /* Test functions on the default timer queue. */
1119 t1 = NULL;
1120 n1 = 0;
1121 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0);
1122 ok(ret, "CreateTimerQueueTimer, default queue\n");
1123 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
1124
1125 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1126 ok(ret, "ChangeTimerQueueTimer, default queue\n");
1127
1128 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1129 ok(ret, "DeleteTimerQueueTimer, default queue\n");
1130
1131 /* Try mixing default and non-default queues. Apparently this works. */
1132 q = CreateTimerQueue();
1133 ok(q != NULL, "CreateTimerQueue\n");
1134
1135 t1 = NULL;
1136 n1 = 0;
1137 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0);
1138 ok(ret, "CreateTimerQueueTimer\n");
1139 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1140
1141 t2 = NULL;
1142 n2 = 0;
1143 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0);
1144 ok(ret, "CreateTimerQueueTimer\n");
1145 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1146
1147 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1148 ok(ret, "ChangeTimerQueueTimer\n");
1149
1150 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000);
1151 ok(ret, "ChangeTimerQueueTimer\n");
1152
1153 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1154 ok(ret, "DeleteTimerQueueTimer\n");
1155
1156 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1157 ok(ret, "DeleteTimerQueueTimer\n");
1158
1159 /* Try to delete the default queue? In any case: not allowed. */
1160 SetLastError(0xdeadbeef);
1161 ret = DeleteTimerQueueEx(NULL, NULL);
1162 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1163 ok(GetLastError() == ERROR_INVALID_HANDLE,
1164 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1165 GetLastError());
1166
1167 SetLastError(0xdeadbeef);
1168 ret = DeleteTimerQueueEx(q, NULL);
1169 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1170 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1171 GetLastError());
1172 }
1173
modify_handle(HANDLE handle,DWORD modify)1174 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1175 {
1176 DWORD tmp = HandleToULong(handle);
1177 tmp |= modify;
1178 return ULongToHandle(tmp);
1179 }
1180
test_WaitForSingleObject(void)1181 static void test_WaitForSingleObject(void)
1182 {
1183 HANDLE signaled, nonsignaled, invalid;
1184 LARGE_INTEGER timeout;
1185 NTSTATUS status;
1186 DWORD ret;
1187
1188 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1189 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1190 invalid = (HANDLE) 0xdeadbee0;
1191
1192 /* invalid handle with different values for lower 2 bits */
1193 SetLastError(0xdeadbeef);
1194 ret = WaitForSingleObject(invalid, 0);
1195 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1196 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1197
1198 SetLastError(0xdeadbeef);
1199 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1200 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1201 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1202
1203 SetLastError(0xdeadbeef);
1204 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1205 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1206 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1207
1208 SetLastError(0xdeadbeef);
1209 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1210 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1211 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1212
1213 /* valid handle with different values for lower 2 bits */
1214 SetLastError(0xdeadbeef);
1215 ret = WaitForSingleObject(nonsignaled, 0);
1216 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1217 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1218
1219 SetLastError(0xdeadbeef);
1220 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1221 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1222 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1223
1224 SetLastError(0xdeadbeef);
1225 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1226 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1227 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1228
1229 SetLastError(0xdeadbeef);
1230 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1231 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1232 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1233
1234 /* valid handle with different values for lower 2 bits */
1235 SetLastError(0xdeadbeef);
1236 ret = WaitForSingleObject(signaled, 0);
1237 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1238 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1239
1240 SetLastError(0xdeadbeef);
1241 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1242 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1243 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1244
1245 SetLastError(0xdeadbeef);
1246 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1247 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1248 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1249
1250 SetLastError(0xdeadbeef);
1251 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1252 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1253 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1254
1255 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1256 ret = WaitForSingleObject(GetCurrentProcess(), 100);
1257 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret);
1258
1259 ret = WaitForSingleObject(GetCurrentThread(), 100);
1260 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret);
1261
1262 timeout.QuadPart = -1000000;
1263 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout);
1264 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status);
1265
1266 timeout.QuadPart = -1000000;
1267 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout);
1268 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status);
1269
1270 CloseHandle(signaled);
1271 CloseHandle(nonsignaled);
1272 }
1273
test_WaitForMultipleObjects(void)1274 static void test_WaitForMultipleObjects(void)
1275 {
1276 LARGE_INTEGER timeout;
1277 NTSTATUS status;
1278 DWORD r;
1279 int i;
1280 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1281
1282 /* create the maximum number of events and make sure
1283 * we can wait on that many */
1284 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1285 {
1286 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL);
1287 ok( maxevents[i] != 0, "should create enough events\n");
1288 }
1289
1290 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1291 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1292 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1293 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1294 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1295 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1296 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1297 {
1298 /* the lowest index is checked first and remaining events are untouched */
1299 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1300 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1301 }
1302
1303 /* run same test with Nt* call */
1304 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1305 SetEvent(maxevents[i]);
1306
1307 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1308 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1309 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08x\n", status);
1310 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1311 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08x\n", status);
1312 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1313 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1314 {
1315 /* the lowest index is checked first and remaining events are untouched */
1316 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1317 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08x\n", i, status);
1318 }
1319
1320 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1321 if (maxevents[i]) CloseHandle(maxevents[i]);
1322
1323 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1324 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1325 maxevents[0] = GetCurrentProcess();
1326 SetLastError(0xdeadbeef);
1327 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1328 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r);
1329 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1330 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1331
1332 maxevents[0] = GetCurrentThread();
1333 SetLastError(0xdeadbeef);
1334 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1335 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r);
1336 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1337 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1338
1339 timeout.QuadPart = -1000000;
1340 maxevents[0] = GetCurrentProcess();
1341 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1342 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status);
1343
1344 timeout.QuadPart = -1000000;
1345 maxevents[0] = GetCurrentThread();
1346 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1347 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status);
1348 }
1349
1350 static BOOL g_initcallback_ret, g_initcallback_called;
1351 static void *g_initctxt;
1352
initonce_callback(INIT_ONCE * initonce,void * parameter,void ** ctxt)1353 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1354 {
1355 g_initcallback_called = TRUE;
1356 /* zero bit set means here that initialization is taking place - initialization locked */
1357 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1358 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1359 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1360 return g_initcallback_ret;
1361 }
1362
test_initonce(void)1363 static void test_initonce(void)
1364 {
1365 INIT_ONCE initonce;
1366 BOOL ret, pending;
1367
1368 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1369 {
1370 win_skip("one-time initialization API not supported\n");
1371 return;
1372 }
1373
1374 /* blocking initialization with callback */
1375 initonce.Ptr = (void*)0xdeadbeef;
1376 pInitOnceInitialize(&initonce);
1377 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1378
1379 /* initialisation completed successfully */
1380 g_initcallback_ret = TRUE;
1381 g_initctxt = NULL;
1382 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1383 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1384 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1385 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1386 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1387
1388 /* so it's been called already so won't be called again */
1389 g_initctxt = NULL;
1390 g_initcallback_called = FALSE;
1391 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1392 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1393 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1394 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1395 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1396
1397 pInitOnceInitialize(&initonce);
1398 g_initcallback_called = FALSE;
1399 /* 2 lower order bits should never be used, you'll get a crash in result */
1400 g_initctxt = (void*)0xFFFFFFF0;
1401 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1402 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1403 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1404 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1405 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1406
1407 /* callback failed */
1408 g_initcallback_ret = FALSE;
1409 g_initcallback_called = FALSE;
1410 g_initctxt = NULL;
1411 pInitOnceInitialize(&initonce);
1412 SetLastError( 0xdeadbeef );
1413 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1414 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret, GetLastError());
1415 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1416 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1417 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1418
1419 /* blocking initialization without a callback */
1420 pInitOnceInitialize(&initonce);
1421 g_initctxt = NULL;
1422 pending = FALSE;
1423 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1424 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1425 ok(pending, "got %d\n", pending);
1426 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1427 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1428 /* another attempt to begin initialization with block a single thread */
1429
1430 g_initctxt = NULL;
1431 pending = 0xf;
1432 SetLastError( 0xdeadbeef );
1433 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1434 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1435 ok(pending == 0xf, "got %d\n", pending);
1436 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1437 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1438
1439 g_initctxt = (void*)0xdeadbee0;
1440 SetLastError( 0xdeadbeef );
1441 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1442 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1443 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1444
1445 /* once failed already */
1446 g_initctxt = (void*)0xdeadbee0;
1447 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1448 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1449 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1450
1451 pInitOnceInitialize(&initonce);
1452 SetLastError( 0xdeadbeef );
1453 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1454 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1455 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1456
1457 SetLastError( 0xdeadbeef );
1458 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1459 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1460 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1461
1462 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1463 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1464 ok(pending, "got %d\n", pending);
1465 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1466
1467 SetLastError( 0xdeadbeef );
1468 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1469 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1470
1471 SetLastError( 0xdeadbeef );
1472 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1473 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1474 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1475
1476 SetLastError( 0xdeadbeef );
1477 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef);
1478 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1479 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1480
1481 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1482 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1483 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1484
1485 pInitOnceInitialize(&initonce);
1486 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1487 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1488 ok(pending, "got %d\n", pending);
1489 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1490
1491 SetLastError( 0xdeadbeef );
1492 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1493 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1494
1495 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1496 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1497 ok(pending, "got %d\n", pending);
1498 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1499
1500 SetLastError( 0xdeadbeef );
1501 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1502 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1503 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1504
1505 SetLastError( 0xdeadbeef );
1506 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1507 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1508 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1509
1510 SetLastError( 0xdeadbeef );
1511 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef);
1512 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1513 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1514
1515 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1516 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1517 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1518
1519 SetLastError( 0xdeadbeef );
1520 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1521 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1522 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1523
1524 pInitOnceInitialize(&initonce);
1525 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1526 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1527 ok(pending, "got %d\n", pending);
1528 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1529
1530 /* test INIT_ONCE_CHECK_ONLY */
1531
1532 pInitOnceInitialize(&initonce);
1533 SetLastError( 0xdeadbeef );
1534 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1535 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1536 SetLastError( 0xdeadbeef );
1537 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1538 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1539
1540 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1541 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1542 ok(pending, "got %d\n", pending);
1543 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1544
1545 SetLastError( 0xdeadbeef );
1546 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1547 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1548 SetLastError( 0xdeadbeef );
1549 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1550 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1551
1552 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0);
1553 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1554 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1555
1556 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1557 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError());
1558 ok(!pending, "got %d\n", pending);
1559 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1560 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1561
1562 SetLastError( 0xdeadbeef );
1563 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1564 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1565
1566 pInitOnceInitialize(&initonce);
1567 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1568 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1569 ok(pending, "got %d\n", pending);
1570 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1571
1572 SetLastError( 0xdeadbeef );
1573 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1574 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1575 SetLastError( 0xdeadbeef );
1576 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1577 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1578
1579 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1580 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1581 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1582
1583 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1584 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError());
1585 ok(!pending, "got %d\n", pending);
1586 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1587 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1588
1589 SetLastError( 0xdeadbeef );
1590 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1591 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1592 }
1593
1594 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT;
1595 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT;
1596 static CRITICAL_SECTION buffercrit;
1597 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1598 static LONG bufferlen,totalproduced,totalconsumed;
1599 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1600
1601 #define BUFFER_SIZE 5
1602
condvar_producer(LPVOID x)1603 static DWORD WINAPI condvar_producer(LPVOID x) {
1604 DWORD sleepinterval = 5;
1605
1606 while (1) {
1607 Sleep(sleepinterval);
1608 if (sleepinterval > 1)
1609 sleepinterval -= 1;
1610
1611 EnterCriticalSection(&buffercrit);
1612 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1613 condvar_producer_sleepcnt++;
1614 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) {
1615 if (GetLastError() != ERROR_TIMEOUT)
1616 condvar_sleeperr = TRUE;
1617 }
1618 }
1619 if (condvar_stop) {
1620 LeaveCriticalSection(&buffercrit);
1621 break;
1622 }
1623 bufferlen++;
1624 totalproduced++;
1625 LeaveCriticalSection(&buffercrit);
1626 pWakeConditionVariable(&buffernotempty);
1627 }
1628 return 0;
1629 }
1630
condvar_consumer(LPVOID x)1631 static DWORD WINAPI condvar_consumer(LPVOID x) {
1632 DWORD *cnt = (DWORD*)x;
1633 DWORD sleepinterval = 1;
1634
1635 while (1) {
1636 EnterCriticalSection(&buffercrit);
1637 while ((bufferlen == 0) && !condvar_stop) {
1638 condvar_consumer_sleepcnt++;
1639 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) {
1640 if (GetLastError() != ERROR_TIMEOUT)
1641 condvar_sleeperr = TRUE;
1642 }
1643 }
1644 if (condvar_stop && (bufferlen == 0)) {
1645 LeaveCriticalSection(&buffercrit);
1646 break;
1647 }
1648 bufferlen--;
1649 totalconsumed++;
1650 (*cnt)++;
1651 LeaveCriticalSection(&buffercrit);
1652 pWakeConditionVariable(&buffernotfull);
1653 Sleep(sleepinterval);
1654 if (sleepinterval < 5) sleepinterval += 1;
1655 }
1656 return 0;
1657 }
1658
test_condvars_consumer_producer(void)1659 static void test_condvars_consumer_producer(void)
1660 {
1661 HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
1662 DWORD dummy;
1663 DWORD cnt1,cnt2,cnt3;
1664
1665 if (!pInitializeConditionVariable) {
1666 /* function is not yet in XP, only in newer Windows */
1667 win_skip("no condition variable support.\n");
1668 return;
1669 }
1670
1671 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1672
1673 /* If we have static initialized condition variables, InitializeConditionVariable
1674 * is not strictly necessary.
1675 * pInitializeConditionVariable(&buffernotfull);
1676 */
1677 pInitializeConditionVariable(&buffernotempty);
1678 InitializeCriticalSection(&buffercrit);
1679
1680 /* Larger Test: consumer/producer example */
1681
1682 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
1683
1684 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1685 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1686 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1687 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1688 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1689 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy);
1690
1691 /* Limit run to 0.5 seconds. */
1692 Sleep(500);
1693
1694 /* tear down start */
1695 condvar_stop = TRUE;
1696
1697 /* final wake up call */
1698 pWakeAllConditionVariable (&buffernotfull);
1699 pWakeAllConditionVariable (&buffernotempty);
1700
1701 /* (mostly an implementation detail)
1702 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1703 */
1704
1705 WaitForSingleObject(hp1, 1000);
1706 WaitForSingleObject(hp2, 1000);
1707 WaitForSingleObject(hp3, 1000);
1708 WaitForSingleObject(hc1, 1000);
1709 WaitForSingleObject(hc2, 1000);
1710 WaitForSingleObject(hc3, 1000);
1711
1712 ok(totalconsumed == totalproduced,
1713 "consumed %d != produced %d\n", totalconsumed, totalproduced);
1714 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1715
1716 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1717 * one consumer does not get anything to do is possible. */
1718 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced, cnt1, cnt2, cnt3);
1719 /* The sleeps of the producer or consumer should not go above 100* produced count,
1720 * otherwise the implementation does not sleep correctly. But yet again, this is
1721 * not hard defined. */
1722 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1723 }
1724
1725 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1726 static DWORD condvar_seq = 0;
1727 static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT;
1728 static CRITICAL_SECTION condvar_crit;
1729 static SRWLOCK condvar_srwlock;
1730
1731 /* Sequence of wake/sleep to check boundary conditions:
1732 * 0: init
1733 * 1: producer emits a WakeConditionVariable without consumer waiting.
1734 * 2: consumer sleeps without a wake expecting timeout
1735 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1736 * 4: consumer sleeps without a wake expecting timeout
1737 * 5: a wake is handed to a SleepConditionVariableCS
1738 * 6: a wakeall is handed to a SleepConditionVariableCS
1739 * 7: sleep after above should timeout
1740 * 8: wake with crit section locked into the sleep timeout
1741 *
1742 * the following tests will only be executed if InitializeSRWLock is available
1743 *
1744 * 9: producer (exclusive) wakes up consumer (exclusive)
1745 * 10: producer (exclusive) wakes up consumer (shared)
1746 * 11: producer (shared) wakes up consumer (exclusive)
1747 * 12: producer (shared) wakes up consumer (shared)
1748 * 13: end
1749 */
condvar_base_producer(LPVOID x)1750 static DWORD WINAPI condvar_base_producer(LPVOID x) {
1751 while (condvar_seq < 1) Sleep(1);
1752
1753 pWakeConditionVariable (&condvar_base);
1754 condvar_seq = 2;
1755
1756 while (condvar_seq < 3) Sleep(1);
1757 pWakeAllConditionVariable (&condvar_base);
1758 condvar_seq = 4;
1759
1760 while (condvar_seq < 5) Sleep(1);
1761 EnterCriticalSection (&condvar_crit);
1762 pWakeConditionVariable (&condvar_base);
1763 LeaveCriticalSection (&condvar_crit);
1764 while (condvar_seq < 6) Sleep(1);
1765 EnterCriticalSection (&condvar_crit);
1766 pWakeAllConditionVariable (&condvar_base);
1767 LeaveCriticalSection (&condvar_crit);
1768
1769 while (condvar_seq < 8) Sleep(1);
1770 EnterCriticalSection (&condvar_crit);
1771 pWakeConditionVariable (&condvar_base);
1772 Sleep(50);
1773 LeaveCriticalSection (&condvar_crit);
1774
1775 /* skip over remaining tests if InitializeSRWLock is not available */
1776 if (!pInitializeSRWLock)
1777 return 0;
1778
1779 while (condvar_seq < 9) Sleep(1);
1780 pAcquireSRWLockExclusive(&condvar_srwlock);
1781 pWakeConditionVariable(&condvar_base);
1782 pReleaseSRWLockExclusive(&condvar_srwlock);
1783
1784 while (condvar_seq < 10) Sleep(1);
1785 pAcquireSRWLockExclusive(&condvar_srwlock);
1786 pWakeConditionVariable(&condvar_base);
1787 pReleaseSRWLockExclusive(&condvar_srwlock);
1788
1789 while (condvar_seq < 11) Sleep(1);
1790 pAcquireSRWLockShared(&condvar_srwlock);
1791 pWakeConditionVariable(&condvar_base);
1792 pReleaseSRWLockShared(&condvar_srwlock);
1793
1794 while (condvar_seq < 12) Sleep(1);
1795 Sleep(50); /* ensure that consumer waits for cond variable */
1796 pAcquireSRWLockShared(&condvar_srwlock);
1797 pWakeConditionVariable(&condvar_base);
1798 pReleaseSRWLockShared(&condvar_srwlock);
1799
1800 return 0;
1801 }
1802
condvar_base_consumer(LPVOID x)1803 static DWORD WINAPI condvar_base_consumer(LPVOID x) {
1804 BOOL ret;
1805
1806 while (condvar_seq < 2) Sleep(1);
1807
1808 /* wake was emitted, but we were not sleeping */
1809 EnterCriticalSection (&condvar_crit);
1810 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1811 LeaveCriticalSection (&condvar_crit);
1812 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1813 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1814
1815 condvar_seq = 3;
1816 while (condvar_seq < 4) Sleep(1);
1817
1818 /* wake all was emitted, but we were not sleeping */
1819 EnterCriticalSection (&condvar_crit);
1820 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1821 LeaveCriticalSection (&condvar_crit);
1822 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1823 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1824
1825 EnterCriticalSection (&condvar_crit);
1826 condvar_seq = 5;
1827 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1828 LeaveCriticalSection (&condvar_crit);
1829 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
1830
1831 EnterCriticalSection (&condvar_crit);
1832 condvar_seq = 6;
1833 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1834 LeaveCriticalSection (&condvar_crit);
1835 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1836 condvar_seq = 7;
1837
1838 EnterCriticalSection (&condvar_crit);
1839 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1840 LeaveCriticalSection (&condvar_crit);
1841 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1842 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1843
1844 EnterCriticalSection (&condvar_crit);
1845 condvar_seq = 8;
1846 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20);
1847 LeaveCriticalSection (&condvar_crit);
1848 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1849
1850 /* skip over remaining tests if InitializeSRWLock is not available */
1851 if (!pInitializeSRWLock)
1852 {
1853 win_skip("no srw lock support.\n");
1854 condvar_seq = 13; /* end */
1855 return 0;
1856 }
1857
1858 pAcquireSRWLockExclusive(&condvar_srwlock);
1859 condvar_seq = 9;
1860 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0);
1861 pReleaseSRWLockExclusive(&condvar_srwlock);
1862 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1863
1864 pAcquireSRWLockShared(&condvar_srwlock);
1865 condvar_seq = 10;
1866 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1867 pReleaseSRWLockShared(&condvar_srwlock);
1868 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1869
1870 pAcquireSRWLockExclusive(&condvar_srwlock);
1871 condvar_seq = 11;
1872 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0);
1873 pReleaseSRWLockExclusive(&condvar_srwlock);
1874 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1875
1876 pAcquireSRWLockShared(&condvar_srwlock);
1877 condvar_seq = 12;
1878 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1879 pReleaseSRWLockShared(&condvar_srwlock);
1880 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1881
1882 condvar_seq = 13;
1883 return 0;
1884 }
1885
test_condvars_base(void)1886 static void test_condvars_base(void) {
1887 HANDLE hp, hc;
1888 DWORD dummy;
1889 BOOL ret;
1890
1891
1892 if (!pInitializeConditionVariable) {
1893 /* function is not yet in XP, only in newer Windows */
1894 win_skip("no condition variable support.\n");
1895 return;
1896 }
1897
1898 InitializeCriticalSection (&condvar_crit);
1899
1900 if (pInitializeSRWLock)
1901 pInitializeSRWLock(&condvar_srwlock);
1902
1903 EnterCriticalSection (&condvar_crit);
1904 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1905 LeaveCriticalSection (&condvar_crit);
1906
1907 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1908 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1909
1910 if (pInitializeSRWLock)
1911 {
1912 pAcquireSRWLockExclusive(&condvar_srwlock);
1913 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, 0);
1914 pReleaseSRWLockExclusive(&condvar_srwlock);
1915
1916 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1917 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1918
1919 pAcquireSRWLockShared(&condvar_srwlock);
1920 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED);
1921 pReleaseSRWLockShared(&condvar_srwlock);
1922
1923 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1924 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1925 }
1926
1927
1928 hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy);
1929 hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy);
1930
1931 condvar_seq = 1; /* go */
1932
1933 while (condvar_seq < 9)
1934 Sleep (5);
1935 WaitForSingleObject(hp, 100);
1936 WaitForSingleObject(hc, 100);
1937 }
1938
1939 static LONG srwlock_seq = 0;
1940 static SRWLOCK srwlock_base;
1941 static struct
1942 {
1943 LONG wrong_execution_order;
1944 LONG samethread_excl_excl;
1945 LONG samethread_excl_shared;
1946 LONG samethread_shared_excl;
1947 LONG multithread_excl_excl;
1948 LONG excl_not_preferred;
1949 LONG trylock_excl;
1950 LONG trylock_shared;
1951 } srwlock_base_errors;
1952
1953 /* Sequence of acquire/release to check boundary conditions:
1954 * 0: init
1955 *
1956 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1957 * 2: thread1 expects a deadlock and releases the waiting lock
1958 * thread2 releases the lock again
1959 *
1960 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1961 * 4: thread1 expects a deadlock and releases the waiting lock
1962 * thread2 releases the lock again
1963 *
1964 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1965 * 6: thread1 expects a deadlock and releases the waiting lock
1966 * thread2 releases the lock again
1967 *
1968 * 7: thread2 acquires and releases two nested shared locks
1969 *
1970 * 8: thread1 acquires an exclusive lock
1971 * 9: thread2 tries to acquire the exclusive lock, too
1972 * thread1 releases the exclusive lock again
1973 * 10: thread2 enters the exclusive lock and leaves it immediately again
1974 *
1975 * 11: thread1 acquires a shared lock
1976 * 12: thread2 acquires and releases a shared lock
1977 * thread1 releases the lock again
1978 *
1979 * 13: thread1 acquires a shared lock
1980 * 14: thread2 tries to acquire an exclusive lock
1981 * 15: thread3 tries to acquire a shared lock
1982 * 16: thread1 releases the shared lock
1983 * 17: thread2 wakes up and releases the exclusive lock
1984 * 18: thread3 wakes up and releases the shared lock
1985 *
1986 * the following tests will only be executed if TryAcquireSRWLock* is available
1987 *
1988 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1989 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1990 * thread1 releases the exclusive lock
1991 *
1992 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1993 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1994 * thread1 releases the shared lock
1995 *
1996 * thread1 acquires an exclusive lock
1997 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1998 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1999 * 21: thread1 releases the exclusive lock
2000 *
2001 * thread1 acquires an shared lock
2002 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2003 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2004 * 23: thread1 releases the shared lock
2005 *
2006 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2007 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2008 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2009 * 25: thread1 releases the exclusive lock
2010 *
2011 * thread1 acquires two shared locks
2012 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2013 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2014 * 27: thread1 releases one shared lock
2015 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2016 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2017 * 29: thread1 releases the second shared lock
2018 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2019 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2020 *
2021 * 31: end
2022 */
2023
srwlock_base_thread1(LPVOID x)2024 static DWORD WINAPI srwlock_base_thread1(LPVOID x)
2025 {
2026 /* seq 2 */
2027 while (srwlock_seq < 2) Sleep(1);
2028 Sleep(100);
2029 if (InterlockedIncrement(&srwlock_seq) != 3)
2030 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2031 pReleaseSRWLockExclusive(&srwlock_base);
2032
2033 /* seq 4 */
2034 while (srwlock_seq < 4) Sleep(1);
2035 Sleep(100);
2036 if (InterlockedIncrement(&srwlock_seq) != 5)
2037 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2038 pReleaseSRWLockExclusive(&srwlock_base);
2039
2040 /* seq 6 */
2041 while (srwlock_seq < 6) Sleep(1);
2042 Sleep(100);
2043 if (InterlockedIncrement(&srwlock_seq) != 7)
2044 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2045 pReleaseSRWLockShared(&srwlock_base);
2046
2047 /* seq 8 */
2048 while (srwlock_seq < 8) Sleep(1);
2049 pAcquireSRWLockExclusive(&srwlock_base);
2050 if (InterlockedIncrement(&srwlock_seq) != 9)
2051 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2052 Sleep(100);
2053 if (InterlockedIncrement(&srwlock_seq) != 10)
2054 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2055 pReleaseSRWLockExclusive(&srwlock_base);
2056
2057 /* seq 11 */
2058 while (srwlock_seq < 11) Sleep(1);
2059 pAcquireSRWLockShared(&srwlock_base);
2060 if (InterlockedIncrement(&srwlock_seq) != 12)
2061 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2062
2063 /* seq 13 */
2064 while (srwlock_seq < 13) Sleep(1);
2065 pReleaseSRWLockShared(&srwlock_base);
2066 pAcquireSRWLockShared(&srwlock_base);
2067 if (InterlockedIncrement(&srwlock_seq) != 14)
2068 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2069
2070 /* seq 16 */
2071 while (srwlock_seq < 16) Sleep(1);
2072 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2073 if (InterlockedIncrement(&srwlock_seq) != 17)
2074 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2075 pReleaseSRWLockShared(&srwlock_base);
2076
2077 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2078 if (!pTryAcquireSRWLockExclusive)
2079 return 0;
2080
2081 /* seq 19 */
2082 while (srwlock_seq < 19) Sleep(1);
2083 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2084 {
2085 if (pTryAcquireSRWLockShared(&srwlock_base))
2086 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2087 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2088 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2089 pReleaseSRWLockExclusive(&srwlock_base);
2090 }
2091 else
2092 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2093
2094 if (pTryAcquireSRWLockShared(&srwlock_base))
2095 {
2096 if (pTryAcquireSRWLockShared(&srwlock_base))
2097 pReleaseSRWLockShared(&srwlock_base);
2098 else
2099 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2100 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2101 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2102 pReleaseSRWLockShared(&srwlock_base);
2103 }
2104 else
2105 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2106
2107 pAcquireSRWLockExclusive(&srwlock_base);
2108 if (InterlockedIncrement(&srwlock_seq) != 20)
2109 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2110
2111 /* seq 21 */
2112 while (srwlock_seq < 21) Sleep(1);
2113 pReleaseSRWLockExclusive(&srwlock_base);
2114 pAcquireSRWLockShared(&srwlock_base);
2115 if (InterlockedIncrement(&srwlock_seq) != 22)
2116 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2117
2118 /* seq 23 */
2119 while (srwlock_seq < 23) Sleep(1);
2120 pReleaseSRWLockShared(&srwlock_base);
2121 pAcquireSRWLockShared(&srwlock_base);
2122 if (InterlockedIncrement(&srwlock_seq) != 24)
2123 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2124
2125 /* seq 25 */
2126 pAcquireSRWLockExclusive(&srwlock_base);
2127 if (srwlock_seq != 25)
2128 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2129 pReleaseSRWLockExclusive(&srwlock_base);
2130
2131 pAcquireSRWLockShared(&srwlock_base);
2132 pAcquireSRWLockShared(&srwlock_base);
2133 if (InterlockedIncrement(&srwlock_seq) != 26)
2134 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2135
2136 /* seq 27 */
2137 while (srwlock_seq < 27) Sleep(1);
2138 pReleaseSRWLockShared(&srwlock_base);
2139 if (InterlockedIncrement(&srwlock_seq) != 28)
2140 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2141
2142 /* seq 29 */
2143 while (srwlock_seq < 29) Sleep(1);
2144 pReleaseSRWLockShared(&srwlock_base);
2145 if (InterlockedIncrement(&srwlock_seq) != 30)
2146 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2147
2148 return 0;
2149 }
2150
srwlock_base_thread2(LPVOID x)2151 static DWORD WINAPI srwlock_base_thread2(LPVOID x)
2152 {
2153 /* seq 1 */
2154 while (srwlock_seq < 1) Sleep(1);
2155 pAcquireSRWLockExclusive(&srwlock_base);
2156 if (InterlockedIncrement(&srwlock_seq) != 2)
2157 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2158
2159 /* seq 3 */
2160 pAcquireSRWLockExclusive(&srwlock_base);
2161 if (srwlock_seq != 3)
2162 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2163 pReleaseSRWLockExclusive(&srwlock_base);
2164 pAcquireSRWLockExclusive(&srwlock_base);
2165 if (InterlockedIncrement(&srwlock_seq) != 4)
2166 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2167
2168 /* seq 5 */
2169 pAcquireSRWLockShared(&srwlock_base);
2170 if (srwlock_seq != 5)
2171 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2172 pReleaseSRWLockShared(&srwlock_base);
2173 pAcquireSRWLockShared(&srwlock_base);
2174 if (InterlockedIncrement(&srwlock_seq) != 6)
2175 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2176
2177 /* seq 7 */
2178 pAcquireSRWLockExclusive(&srwlock_base);
2179 if (srwlock_seq != 7)
2180 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2181 pReleaseSRWLockExclusive(&srwlock_base);
2182 pAcquireSRWLockShared(&srwlock_base);
2183 pAcquireSRWLockShared(&srwlock_base);
2184 pReleaseSRWLockShared(&srwlock_base);
2185 pReleaseSRWLockShared(&srwlock_base);
2186 if (InterlockedIncrement(&srwlock_seq) != 8)
2187 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2188
2189 /* seq 9, 10 */
2190 while (srwlock_seq < 9) Sleep(1);
2191 pAcquireSRWLockExclusive(&srwlock_base);
2192 if (srwlock_seq != 10)
2193 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2194 pReleaseSRWLockExclusive(&srwlock_base);
2195 if (InterlockedIncrement(&srwlock_seq) != 11)
2196 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2197
2198 /* seq 12 */
2199 while (srwlock_seq < 12) Sleep(1);
2200 pAcquireSRWLockShared(&srwlock_base);
2201 pReleaseSRWLockShared(&srwlock_base);
2202 if (InterlockedIncrement(&srwlock_seq) != 13)
2203 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2204
2205 /* seq 14 */
2206 while (srwlock_seq < 14) Sleep(1);
2207 if (InterlockedIncrement(&srwlock_seq) != 15)
2208 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2209
2210 /* seq 17 */
2211 pAcquireSRWLockExclusive(&srwlock_base);
2212 if (srwlock_seq != 17)
2213 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2214 if (InterlockedIncrement(&srwlock_seq) != 18)
2215 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2216 pReleaseSRWLockExclusive(&srwlock_base);
2217
2218 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2219 if (!pTryAcquireSRWLockExclusive)
2220 return 0;
2221
2222 /* seq 20 */
2223 while (srwlock_seq < 20) Sleep(1);
2224 if (pTryAcquireSRWLockShared(&srwlock_base))
2225 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2226 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2227 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2228 if (InterlockedIncrement(&srwlock_seq) != 21)
2229 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2230
2231 /* seq 22 */
2232 while (srwlock_seq < 22) Sleep(1);
2233 if (pTryAcquireSRWLockShared(&srwlock_base))
2234 pReleaseSRWLockShared(&srwlock_base);
2235 else
2236 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2237 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2238 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2239 if (InterlockedIncrement(&srwlock_seq) != 23)
2240 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2241
2242 /* seq 24 */
2243 while (srwlock_seq < 24) Sleep(1);
2244 Sleep(50); /* ensure that exclusive access request is queued */
2245 if (pTryAcquireSRWLockShared(&srwlock_base))
2246 {
2247 pReleaseSRWLockShared(&srwlock_base);
2248 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2249 }
2250 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2251 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2252 if (InterlockedIncrement(&srwlock_seq) != 25)
2253 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2254 pReleaseSRWLockShared(&srwlock_base);
2255
2256 /* seq 26 */
2257 while (srwlock_seq < 26) Sleep(1);
2258 if (pTryAcquireSRWLockShared(&srwlock_base))
2259 pReleaseSRWLockShared(&srwlock_base);
2260 else
2261 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2262 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2263 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2264 if (InterlockedIncrement(&srwlock_seq) != 27)
2265 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2266
2267 /* seq 28 */
2268 while (srwlock_seq < 28) Sleep(1);
2269 if (pTryAcquireSRWLockShared(&srwlock_base))
2270 pReleaseSRWLockShared(&srwlock_base);
2271 else
2272 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2273 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2274 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2275 if (InterlockedIncrement(&srwlock_seq) != 29)
2276 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2277
2278 /* seq 30 */
2279 while (srwlock_seq < 30) Sleep(1);
2280 if (pTryAcquireSRWLockShared(&srwlock_base))
2281 pReleaseSRWLockShared(&srwlock_base);
2282 else
2283 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2284 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2285 pReleaseSRWLockExclusive(&srwlock_base);
2286 else
2287 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2288 if (InterlockedIncrement(&srwlock_seq) != 31)
2289 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2290
2291 return 0;
2292 }
2293
srwlock_base_thread3(LPVOID x)2294 static DWORD WINAPI srwlock_base_thread3(LPVOID x)
2295 {
2296 /* seq 15 */
2297 while (srwlock_seq < 15) Sleep(1);
2298 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2299 if (InterlockedIncrement(&srwlock_seq) != 16)
2300 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2301
2302 /* seq 18 */
2303 pAcquireSRWLockShared(&srwlock_base);
2304 if (srwlock_seq != 18)
2305 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2306 pReleaseSRWLockShared(&srwlock_base);
2307 if (InterlockedIncrement(&srwlock_seq) != 19)
2308 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2309
2310 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2311 if (!pTryAcquireSRWLockExclusive)
2312 {
2313 /* function is only in Windows 7 and newer */
2314 win_skip("no srw trylock support.\n");
2315 srwlock_seq = 31; /* end */
2316 return 0;
2317 }
2318
2319 return 0;
2320 }
2321
test_srwlock_base(void)2322 static void test_srwlock_base(void)
2323 {
2324 HANDLE h1, h2, h3;
2325 DWORD dummy;
2326
2327 if (!pInitializeSRWLock)
2328 {
2329 /* function is not yet in XP, only in newer Windows */
2330 win_skip("no srw lock support.\n");
2331 return;
2332 }
2333
2334 pInitializeSRWLock(&srwlock_base);
2335 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors));
2336
2337 h1 = CreateThread(NULL, 0, srwlock_base_thread1, NULL, 0, &dummy);
2338 h2 = CreateThread(NULL, 0, srwlock_base_thread2, NULL, 0, &dummy);
2339 h3 = CreateThread(NULL, 0, srwlock_base_thread3, NULL, 0, &dummy);
2340
2341 srwlock_seq = 1; /* go */
2342 while (srwlock_seq < 31)
2343 Sleep(5);
2344
2345 WaitForSingleObject(h1, 100);
2346 WaitForSingleObject(h2, 100);
2347 WaitForSingleObject(h3, 100);
2348
2349 ok(!srwlock_base_errors.wrong_execution_order,
2350 "thread commands were executed in the wrong order (occurred %d times).\n",
2351 srwlock_base_errors.wrong_execution_order);
2352
2353 ok(!srwlock_base_errors.samethread_excl_excl,
2354 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2355 srwlock_base_errors.samethread_excl_excl);
2356
2357 ok(!srwlock_base_errors.samethread_excl_shared,
2358 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2359 srwlock_base_errors.samethread_excl_shared);
2360
2361 ok(!srwlock_base_errors.samethread_shared_excl,
2362 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2363 srwlock_base_errors.samethread_shared_excl);
2364
2365 ok(!srwlock_base_errors.multithread_excl_excl,
2366 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2367 srwlock_base_errors.multithread_excl_excl);
2368
2369 ok(!srwlock_base_errors.excl_not_preferred,
2370 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2371 srwlock_base_errors.excl_not_preferred);
2372
2373 ok(!srwlock_base_errors.trylock_excl,
2374 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2375 srwlock_base_errors.trylock_excl);
2376
2377 ok(!srwlock_base_errors.trylock_shared,
2378 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2379 srwlock_base_errors.trylock_shared);
2380
2381 }
2382
2383 static SRWLOCK srwlock_example;
2384 static LONG srwlock_protected_value = 0;
2385 static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0;
2386 static BOOL srwlock_stop = FALSE;
2387
srwlock_example_thread(LPVOID x)2388 static DWORD WINAPI srwlock_example_thread(LPVOID x) {
2389 DWORD *cnt = x;
2390 LONG old;
2391
2392 while (!srwlock_stop)
2393 {
2394
2395 /* periodically request exclusive access */
2396 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0)
2397 {
2398 pAcquireSRWLockExclusive(&srwlock_example);
2399 if (InterlockedIncrement(&srwlock_inside) != 1)
2400 InterlockedIncrement(&srwlock_example_errors);
2401
2402 InterlockedIncrement(&srwlock_protected_value);
2403 Sleep(1);
2404
2405 if (InterlockedDecrement(&srwlock_inside) != 0)
2406 InterlockedIncrement(&srwlock_example_errors);
2407 pReleaseSRWLockExclusive(&srwlock_example);
2408 }
2409
2410 /* request shared access */
2411 pAcquireSRWLockShared(&srwlock_example);
2412 InterlockedIncrement(&srwlock_inside);
2413 old = srwlock_protected_value;
2414
2415 (*cnt)++;
2416 Sleep(1);
2417
2418 if (old != srwlock_protected_value)
2419 InterlockedIncrement(&srwlock_example_errors);
2420 InterlockedDecrement(&srwlock_inside);
2421 pReleaseSRWLockShared(&srwlock_example);
2422 }
2423
2424 return 0;
2425 }
2426
test_srwlock_example(void)2427 static void test_srwlock_example(void)
2428 {
2429 HANDLE h1, h2, h3;
2430 DWORD dummy;
2431 DWORD cnt1, cnt2, cnt3;
2432
2433 if (!pInitializeSRWLock) {
2434 /* function is not yet in XP, only in newer Windows */
2435 win_skip("no srw lock support.\n");
2436 return;
2437 }
2438
2439 pInitializeSRWLock(&srwlock_example);
2440
2441 cnt1 = cnt2 = cnt3 = 0;
2442
2443 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy);
2444 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy);
2445 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy);
2446
2447 /* limit run to 1 second. */
2448 Sleep(1000);
2449
2450 /* tear down start */
2451 srwlock_stop = TRUE;
2452
2453 WaitForSingleObject(h1, 1000);
2454 WaitForSingleObject(h2, 1000);
2455 WaitForSingleObject(h3, 1000);
2456
2457 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside);
2458 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2459 srwlock_example_errors);
2460
2461 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1, cnt2, cnt3);
2462 trace("number of total exclusive accesses is %d\n", srwlock_protected_value);
2463 }
2464
alertable_wait_thread(void * param)2465 static DWORD WINAPI alertable_wait_thread(void *param)
2466 {
2467 HANDLE *semaphores = param;
2468 LARGE_INTEGER timeout;
2469 NTSTATUS status;
2470 DWORD result;
2471
2472 ReleaseSemaphore(semaphores[0], 1, NULL);
2473 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE);
2474 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %u\n", result);
2475 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE);
2476 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2477
2478 ReleaseSemaphore(semaphores[0], 1, NULL);
2479 timeout.QuadPart = -10000000;
2480 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2481 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
2482 timeout.QuadPart = -2000000;
2483 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2484 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08x\n", status);
2485
2486 ReleaseSemaphore(semaphores[0], 1, NULL);
2487 timeout.QuadPart = -10000000;
2488 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2489 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
2490 result = WaitForSingleObject(semaphores[0], 0);
2491 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", result);
2492
2493 return 0;
2494 }
2495
alertable_wait_apc(ULONG_PTR userdata)2496 static void CALLBACK alertable_wait_apc(ULONG_PTR userdata)
2497 {
2498 HANDLE *semaphores = (void *)userdata;
2499 ReleaseSemaphore(semaphores[1], 1, NULL);
2500 }
2501
alertable_wait_apc2(ULONG_PTR userdata)2502 static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata)
2503 {
2504 HANDLE *semaphores = (void *)userdata;
2505 DWORD result;
2506
2507 result = WaitForSingleObject(semaphores[0], 1000);
2508 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2509 }
2510
test_alertable_wait(void)2511 static void test_alertable_wait(void)
2512 {
2513 HANDLE thread, semaphores[2];
2514 DWORD result;
2515
2516 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
2517 ok(semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
2518 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
2519 ok(semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
2520 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL);
2521 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
2522
2523 result = WaitForSingleObject(semaphores[0], 1000);
2524 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2525 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2526 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2527 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2528
2529 result = WaitForSingleObject(semaphores[0], 1000);
2530 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2531 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2532 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2533 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2534
2535 result = WaitForSingleObject(semaphores[0], 1000);
2536 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2537 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2538 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2539 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2540 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2541 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2542 ReleaseSemaphore(semaphores[0], 2, NULL);
2543
2544 result = WaitForSingleObject(thread, 1000);
2545 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2546 CloseHandle(thread);
2547 CloseHandle(semaphores[0]);
2548 CloseHandle(semaphores[1]);
2549 }
2550
2551 struct apc_deadlock_info
2552 {
2553 PROCESS_INFORMATION *pi;
2554 HANDLE event;
2555 BOOL running;
2556 };
2557
apc_deadlock_thread(void * param)2558 static DWORD WINAPI apc_deadlock_thread(void *param)
2559 {
2560 struct apc_deadlock_info *info = param;
2561 PROCESS_INFORMATION *pi = info->pi;
2562 NTSTATUS status;
2563 SIZE_T size;
2564 void *base;
2565
2566 while (info->running)
2567 {
2568 base = NULL;
2569 size = 0x1000;
2570 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
2571 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
2572 disable_success_count
2573 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
2574 ok(base != NULL, "expected base != NULL, got %p\n", base);
2575 SetEvent(info->event);
2576
2577 size = 0;
2578 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
2579 disable_success_count
2580 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
2581 SetEvent(info->event);
2582 }
2583
2584 return 0;
2585 }
2586
test_apc_deadlock(void)2587 static void test_apc_deadlock(void)
2588 {
2589 struct apc_deadlock_info info;
2590 PROCESS_INFORMATION pi;
2591 STARTUPINFOA si = { sizeof(si) };
2592 char cmdline[MAX_PATH];
2593 HANDLE event, thread;
2594 DWORD result;
2595 BOOL success;
2596 char **argv;
2597 int i;
2598
2599 #if defined(__REACTOS__) && defined(_M_AMD64)
2600 if (!winetest_interactive)
2601 {
2602 skip("ROSTESTS-371: Skipping kernel32_winetest:sync test_apc_deadlock because it fails on Windows Server 2003 x64-Testbot. Set winetest_interactive to run it anyway.\n");
2603 return;
2604 }
2605 #endif
2606
2607 winetest_get_mainargs(&argv);
2608 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
2609 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2610 ok(success, "CreateProcess failed with %u\n", GetLastError());
2611
2612 event = CreateEventA(NULL, FALSE, FALSE, NULL);
2613 ok(event != NULL, "CreateEvent failed with %u\n", GetLastError());
2614
2615 info.pi = π
2616 info.event = event;
2617 info.running = TRUE;
2618
2619 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
2620 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
2621 result = WaitForSingleObject(event, 1000);
2622 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2623
2624 disable_success_count
2625 for (i = 0; i < 1000; i++)
2626 {
2627 result = SuspendThread(pi.hThread);
2628 ok(result == 0, "expected 0, got %u\n", result);
2629
2630 WaitForSingleObject(event, 0); /* reset event */
2631 result = WaitForSingleObject(event, 1000);
2632 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2633
2634 result = ResumeThread(pi.hThread);
2635 ok(result == 1, "expected 1, got %u\n", result);
2636 Sleep(1);
2637 }
2638
2639 info.running = FALSE;
2640 result = WaitForSingleObject(thread, 1000);
2641 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2642 CloseHandle(thread);
2643 CloseHandle(event);
2644
2645 TerminateProcess(pi.hProcess, 0);
2646 CloseHandle(pi.hThread);
2647 CloseHandle(pi.hProcess);
2648 }
2649
START_TEST(sync)2650 START_TEST(sync)
2651 {
2652 char **argv;
2653 int argc;
2654 HMODULE hdll = GetModuleHandleA("kernel32.dll");
2655 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
2656 #ifdef __REACTOS__
2657 HMODULE hdll_vista = GetModuleHandleA("kernel32_vista.dll");
2658 #endif
2659
2660 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
2661 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
2662 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
2663 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
2664 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
2665 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
2666 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW");
2667 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
2668 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
2669 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock");
2670 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive");
2671 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared");
2672 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive");
2673 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
2674 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
2675 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
2676 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
2677 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
2678 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
2679 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
2680 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList");
2681 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx");
2682
2683 #ifdef __REACTOS__
2684 if (!pInitializeConditionVariable)
2685 {
2686 pInitializeConditionVariable = (void *)GetProcAddress(hdll_vista, "InitializeConditionVariable");
2687 pSleepConditionVariableCS = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableCS");
2688 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableSRW");
2689 pWakeAllConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeAllConditionVariable");
2690 pWakeConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeConditionVariable");
2691 }
2692
2693 if (!pInitializeSRWLock)
2694 {
2695 pInitializeSRWLock = (void *)GetProcAddress(hdll_vista, "InitializeSRWLock");
2696 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockExclusive");
2697 pAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockShared");
2698 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockExclusive");
2699 pReleaseSRWLockShared = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockShared");
2700 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockExclusive");
2701 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockShared");
2702 }
2703 #endif
2704
2705 argc = winetest_get_mainargs( &argv );
2706 if (argc >= 3)
2707 {
2708 if (!strcmp(argv[2], "apc_deadlock"))
2709 {
2710 for (;;) SleepEx(INFINITE, TRUE);
2711 }
2712 return;
2713 }
2714
2715 init_fastcall_thunk();
2716 test_signalandwait();
2717 test_mutex();
2718 test_slist();
2719 test_event();
2720 test_semaphore();
2721 test_waitable_timer();
2722 test_iocp_callback();
2723 test_timer_queue();
2724 test_WaitForSingleObject();
2725 test_WaitForMultipleObjects();
2726 test_initonce();
2727 test_condvars_base();
2728 test_condvars_consumer_producer();
2729 test_srwlock_base();
2730 test_srwlock_example();
2731 test_alertable_wait();
2732 test_apc_deadlock();
2733 }
2734