ddraw: Set dwMaxVertexCount to 2048.
[wine.git] / dlls / kernel32 / tests / sync.c
blobc06ced4729829a74c1c663916a6d13abe0f4edc3
1 /*
2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
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.
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.
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
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winternl.h>
31 #include "wine/test.h"
33 #undef __fastcall
34 #define __fastcall __stdcall
36 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
37 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
38 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
39 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
40 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
41 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
43 static BOOL (WINAPI *pInitializeCriticalSectionEx)(CRITICAL_SECTION*,DWORD,DWORD);
44 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
45 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
46 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG);
47 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
48 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
50 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK);
51 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK);
52 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK);
53 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
54 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
55 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
56 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
58 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG);
59 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
60 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *);
61 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
62 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first,
63 PSLIST_ENTRY last, ULONG count);
64 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first,
65 PSLIST_ENTRY last, ULONG count);
66 static NTSTATUS (WINAPI *pNtQueueApcThread)(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
67 static NTSTATUS (WINAPI *pNtTestAlert)(void);
69 #ifdef __i386__
71 #include "pshpack1.h"
72 struct fastcall_thunk
74 BYTE pop_edx; /* popl %edx (ret addr) */
75 BYTE pop_eax; /* popl %eax (func) */
76 BYTE pop_ecx; /* popl %ecx (param 1) */
77 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */
78 WORD jmp_eax; /* jmp *%eax */
80 #include "poppack.h"
82 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d);
84 static void init_fastcall_thunk(void)
86 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
87 thunk->pop_edx = 0x5a; /* popl %edx */
88 thunk->pop_eax = 0x58; /* popl %eax */
89 thunk->pop_ecx = 0x59; /* popl %ecx */
90 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */
91 thunk->xchg[1] = 0x14;
92 thunk->xchg[2] = 0x24;
93 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */
94 call_fastcall_func4 = (void *)thunk;
97 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
98 (const void *)(b), (const void *)(c), (const void *)(d))
100 #else /* __i386__ */
102 #define init_fastcall_thunk() do { } while(0)
103 #define call_func4(func, a, b, c, d) func(a, b, c, d)
105 #endif /* __i386__ */
107 static void test_signalandwait(void)
109 DWORD r;
110 HANDLE event[2], semaphore[2], file;
111 int i;
113 /* invalid parameters */
114 r = SignalObjectAndWait(NULL, NULL, 0, 0);
115 ok( r == WAIT_FAILED, "should fail\n");
117 event[0] = CreateEventW(NULL, 0, 0, NULL);
118 event[1] = CreateEventW(NULL, 1, 1, NULL);
120 ok( event[0] && event[1], "failed to create event flags\n");
122 r = SignalObjectAndWait(event[0], NULL, 0, FALSE);
123 ok( r == WAIT_FAILED, "should fail\n");
125 r = SignalObjectAndWait(NULL, event[0], 0, FALSE);
126 ok( r == WAIT_FAILED, "should fail\n");
129 /* valid parameters */
130 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
131 ok( r == WAIT_OBJECT_0, "should succeed\n");
133 /* event[0] is now signalled - we repeat this test multiple times
134 * to ensure that the wineserver handles this situation properly. */
135 for (i = 0; i < 10000; i++)
137 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
138 ok(r == WAIT_OBJECT_0, "should succeed\n");
141 /* event[0] is not signalled */
142 r = WaitForSingleObject(event[0], 0);
143 ok( r == WAIT_TIMEOUT, "event was signalled\n");
145 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
146 ok( r == WAIT_OBJECT_0, "should succeed\n");
148 /* clear event[1] and check for a timeout */
149 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
150 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
151 ok( r == WAIT_TIMEOUT, "should timeout\n");
153 CloseHandle(event[0]);
154 CloseHandle(event[1]);
156 /* semaphores */
157 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL );
158 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL );
159 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
161 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
162 ok( r == WAIT_OBJECT_0, "should succeed\n");
164 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
165 ok( r == WAIT_FAILED, "should fail\n");
167 r = ReleaseSemaphore(semaphore[0],1,NULL);
168 ok( r == FALSE, "should fail\n");
170 r = ReleaseSemaphore(semaphore[1],1,NULL);
171 ok( r == TRUE, "should succeed\n");
173 CloseHandle(semaphore[0]);
174 CloseHandle(semaphore[1]);
176 /* try a registry key */
177 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
178 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
179 r = SignalObjectAndWait(file, file, 0, FALSE);
180 ok( r == WAIT_FAILED, "should fail\n");
181 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
182 CloseHandle(file);
185 static void test_temporary_objects(void)
187 HANDLE handle;
189 SetLastError(0xdeadbeef);
190 handle = CreateMutexA(NULL, FALSE, "WineTestMutex2");
191 ok(handle != NULL, "CreateMutex failed with error %ld\n", GetLastError());
192 CloseHandle(handle);
194 SetLastError(0xdeadbeef);
195 handle = OpenMutexA(READ_CONTROL, FALSE, "WineTestMutex2");
196 ok(!handle, "OpenMutex succeeded\n");
197 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
199 SetLastError(0xdeadbeef);
200 handle = CreateSemaphoreA(NULL, 0, 1, "WineTestSemaphore2");
201 ok(handle != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
202 CloseHandle(handle);
204 SetLastError(0xdeadbeef);
205 handle = OpenSemaphoreA(READ_CONTROL, FALSE, "WineTestSemaphore2");
206 ok(!handle, "OpenSemaphore succeeded\n");
207 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
209 SetLastError(0xdeadbeef);
210 handle = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent2");
211 ok(handle != NULL, "CreateEvent failed with error %ld\n", GetLastError());
212 CloseHandle(handle);
214 SetLastError(0xdeadbeef);
215 handle = OpenEventA(READ_CONTROL, FALSE, "WineTestEvent2");
216 ok(!handle, "OpenEvent succeeded\n");
217 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
219 SetLastError(0xdeadbeef);
220 handle = CreateWaitableTimerA(NULL, FALSE, "WineTestWaitableTimer2");
221 ok(handle != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
222 CloseHandle(handle);
224 SetLastError(0xdeadbeef);
225 handle = OpenWaitableTimerA(READ_CONTROL, FALSE, "WineTestWaitableTimer2");
226 ok(!handle, "OpenWaitableTimer succeeded\n");
227 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
230 static void test_mutex(void)
232 DWORD wait_ret;
233 BOOL ret;
234 HANDLE hCreated;
235 HANDLE hOpened;
236 int i;
237 DWORD failed = 0;
239 SetLastError(0xdeadbeef);
240 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
241 ok(hOpened == NULL, "OpenMutex succeeded\n");
242 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
244 SetLastError(0xdeadbeef);
245 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex");
246 ok(hCreated != NULL, "CreateMutex failed with error %ld\n", GetLastError());
248 SetLastError(0xdeadbeef);
249 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
250 todo_wine
251 ok(hOpened == NULL, "OpenMutex succeeded\n");
252 todo_wine
253 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError());
255 SetLastError(0xdeadbeef);
256 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex");
257 ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError());
258 wait_ret = WaitForSingleObject(hOpened, INFINITE);
259 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %ld\n", GetLastError());
260 CloseHandle(hOpened);
262 for(i=0; i < 31; i++)
264 wait_ret = WaitForSingleObject(hCreated, INFINITE);
265 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08lx\n", wait_ret);
268 SetLastError(0xdeadbeef);
269 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
270 ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError());
271 wait_ret = WaitForSingleObject(hOpened, INFINITE);
272 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
273 CloseHandle(hOpened);
275 for (i = 0; i < 32; i++)
277 SetLastError(0xdeadbeef);
278 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex");
279 if(hOpened != NULL)
281 SetLastError(0xdeadbeef);
282 ret = ReleaseMutex(hOpened);
283 ok(ret, "ReleaseMutex failed with error %ld, access %x\n", GetLastError(), 1 << i);
284 CloseHandle(hOpened);
286 else
288 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
289 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %lu, access %x\n", GetLastError(), 1 << i);
290 else
291 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu, , access %x\n", GetLastError(), 1 << i);
292 ReleaseMutex(hCreated);
293 failed |=0x1 << i;
297 todo_wine
298 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %lx\n", failed);
300 SetLastError(0xdeadbeef);
301 ret = ReleaseMutex(hCreated);
302 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
303 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %ld\n", GetLastError());
305 /* test case sensitivity */
307 SetLastError(0xdeadbeef);
308 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX");
309 ok(!hOpened, "OpenMutex succeeded\n");
310 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
312 SetLastError(0xdeadbeef);
313 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex");
314 ok(!hOpened, "OpenMutex succeeded\n");
315 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
317 SetLastError(0xdeadbeef);
318 hOpened = OpenMutexA(READ_CONTROL, FALSE, NULL);
319 ok(!hOpened, "OpenMutex succeeded\n");
320 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
322 SetLastError(0xdeadbeef);
323 hOpened = OpenMutexW(READ_CONTROL, FALSE, NULL);
324 ok(!hOpened, "OpenMutex succeeded\n");
325 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
327 SetLastError(0xdeadbeef);
328 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex");
329 ok(hOpened != NULL, "CreateMutex failed with error %ld\n", GetLastError());
330 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
331 CloseHandle(hOpened);
333 SetLastError(0xdeadbeef);
334 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX");
335 ok(hOpened != NULL, "CreateMutex failed with error %ld\n", GetLastError());
336 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
337 CloseHandle(hOpened);
339 CloseHandle(hCreated);
342 static void test_slist(void)
344 struct item
346 SLIST_ENTRY entry;
347 int value;
348 } item1, item2, item3, *item;
349 SLIST_HEADER slist_header;
350 SLIST_ENTRY *entry;
351 USHORT size;
352 int i;
354 item1.value = 1;
355 item2.value = 2;
356 item3.value = 3;
358 memset(&slist_header, 0xff, sizeof(slist_header));
359 InitializeSListHead(&slist_header);
360 size = QueryDepthSList(&slist_header);
361 ok(size == 0, "Expected size == 0, got %u\n", size);
363 /* test PushEntry, PopEntry and Flush */
364 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
365 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
366 size = QueryDepthSList(&slist_header);
367 ok(size == 1, "Expected size == 1, got %u\n", size);
369 entry = InterlockedPushEntrySList(&slist_header, &item2.entry);
370 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
371 item = CONTAINING_RECORD(entry, struct item, entry);
372 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
373 size = QueryDepthSList(&slist_header);
374 ok(size == 2, "Expected size == 2, got %u\n", size);
376 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
377 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
378 item = CONTAINING_RECORD(entry, struct item, entry);
379 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
380 size = QueryDepthSList(&slist_header);
381 ok(size == 3, "Expected size == 3, got %u\n", size);
383 entry = InterlockedPopEntrySList(&slist_header);
384 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
385 item = CONTAINING_RECORD(entry, struct item, entry);
386 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
387 size = QueryDepthSList(&slist_header);
388 ok(size == 2, "Expected size == 2, got %u\n", size);
390 entry = InterlockedFlushSList(&slist_header);
391 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
392 item = CONTAINING_RECORD(entry, struct item, entry);
393 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
394 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
395 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
396 size = QueryDepthSList(&slist_header);
397 ok(size == 0, "Expected size == 0, got %u\n", size);
398 entry = InterlockedPopEntrySList(&slist_header);
399 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
401 /* test RtlInterlockedPushListSList */
402 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
403 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
404 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42);
405 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
406 item = CONTAINING_RECORD(entry, struct item, entry);
407 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
408 size = QueryDepthSList(&slist_header);
409 ok(size == 43, "Expected size == 43, got %u\n", size);
411 entry = InterlockedPopEntrySList(&slist_header);
412 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
413 item = CONTAINING_RECORD(entry, struct item, entry);
414 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
415 size = QueryDepthSList(&slist_header);
416 ok(size == 42, "Expected size == 42, got %u\n", size);
418 entry = InterlockedPopEntrySList(&slist_header);
419 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
420 item = CONTAINING_RECORD(entry, struct item, entry);
421 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
422 size = QueryDepthSList(&slist_header);
423 ok(size == 41, "Expected size == 41, got %u\n", size);
425 entry = InterlockedPopEntrySList(&slist_header);
426 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
427 item = CONTAINING_RECORD(entry, struct item, entry);
428 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
429 size = QueryDepthSList(&slist_header);
430 ok(size == 40, "Expected size == 40, got %u\n", size);
432 entry = InterlockedPopEntrySList(&slist_header);
433 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
434 size = QueryDepthSList(&slist_header);
435 ok(size == 40, "Expected size == 40, got %u\n", size);
437 entry = InterlockedFlushSList(&slist_header);
438 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
439 size = QueryDepthSList(&slist_header);
440 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size);
442 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
443 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
444 entry = InterlockedFlushSList(&slist_header);
445 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
446 item = CONTAINING_RECORD(entry, struct item, entry);
447 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
448 size = QueryDepthSList(&slist_header);
449 ok(size == 0, "Expected size == 0, got %u\n", size);
451 /* test RtlInterlockedPushListSListEx */
452 if (pRtlInterlockedPushListSListEx)
454 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
455 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
456 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42);
457 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
458 item = CONTAINING_RECORD(entry, struct item, entry);
459 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
460 size = QueryDepthSList(&slist_header);
461 ok(size == 43, "Expected size == 43, got %u\n", size);
463 entry = InterlockedFlushSList(&slist_header);
464 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
465 item = CONTAINING_RECORD(entry, struct item, entry);
466 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
467 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
468 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
469 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
470 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
471 size = QueryDepthSList(&slist_header);
472 ok(size == 0, "Expected size == 0, got %u\n", size);
474 else
475 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
477 /* test with a lot of items */
478 for (i = 0; i < 65536; i++)
480 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
481 item->value = i + 1;
482 entry = InterlockedPushEntrySList(&slist_header, &item->entry);
483 if (i)
485 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
486 item = CONTAINING_RECORD(entry, struct item, entry);
487 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
489 else
491 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
493 size = QueryDepthSList(&slist_header);
494 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size);
497 entry = InterlockedFlushSList(&slist_header);
498 for (i = 65536; i > 0; i--)
500 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
501 item = CONTAINING_RECORD(entry, struct item, entry);
502 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
503 entry = item->entry.Next;
504 HeapFree(GetProcessHeap(), 0, item);
506 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
507 size = QueryDepthSList(&slist_header);
508 ok(size == 0, "Expected size == 0, got %u\n", size);
509 entry = InterlockedPopEntrySList(&slist_header);
510 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
513 static void test_event(void)
515 HANDLE handle, handle2;
516 SECURITY_ATTRIBUTES sa;
517 SECURITY_DESCRIPTOR sd;
518 ACL acl;
519 DWORD ret;
520 BOOL val;
522 /* no sd */
523 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
524 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
525 CloseHandle(handle);
527 sa.nLength = sizeof(sa);
528 sa.lpSecurityDescriptor = &sd;
529 sa.bInheritHandle = FALSE;
531 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
533 /* blank sd */
534 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
535 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
536 CloseHandle(handle);
538 /* sd with NULL dacl */
539 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
540 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
541 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
542 CloseHandle(handle);
544 /* sd with empty dacl */
545 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
546 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
547 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
548 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
549 CloseHandle(handle);
551 /* test case sensitivity */
553 SetLastError(0xdeadbeef);
554 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
555 ok( handle != NULL, "CreateEvent failed with error %lu\n", GetLastError());
556 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
558 SetLastError(0xdeadbeef);
559 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
560 ok( handle2 != NULL, "CreateEvent failed with error %ld\n", GetLastError());
561 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
562 CloseHandle( handle2 );
564 SetLastError(0xdeadbeef);
565 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
566 ok( handle2 != NULL, "CreateEvent failed with error %ld\n", GetLastError());
567 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
568 CloseHandle( handle2 );
570 SetLastError(0xdeadbeef);
571 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
572 ok( handle2 != NULL, "OpenEvent failed with error %ld\n", GetLastError());
573 CloseHandle( handle2 );
575 SetLastError(0xdeadbeef);
576 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
577 ok( !handle2, "OpenEvent succeeded\n");
578 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
580 SetLastError(0xdeadbeef);
581 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, NULL );
582 ok( !handle2, "OpenEvent succeeded\n");
583 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
585 SetLastError(0xdeadbeef);
586 handle2 = OpenEventW( EVENT_ALL_ACCESS, FALSE, NULL );
587 ok( !handle2, "OpenEvent succeeded\n");
588 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
590 CloseHandle( handle );
592 /* resource notifications are events too */
594 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
596 trace( "memory resource notifications not supported\n" );
597 return;
599 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
600 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
601 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
602 ret = pQueryMemoryResourceNotification( handle, &val );
603 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
604 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
606 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
607 ok( handle != 0, "CreateMemoryResourceNotification failed err %lu\n", GetLastError() );
608 ret = WaitForSingleObject( handle, 10 );
609 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %lu\n", ret );
611 val = ~0;
612 ret = pQueryMemoryResourceNotification( handle, &val );
613 ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() );
614 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
615 ret = CloseHandle( handle );
616 ok( ret, "CloseHandle failed err %lu\n", GetLastError() );
618 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
619 val = ~0;
620 ret = pQueryMemoryResourceNotification( handle, &val );
621 ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() );
622 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
623 CloseHandle( handle );
626 static void test_semaphore(void)
628 HANDLE handle, handle2;
630 /* test case sensitivity */
632 SetLastError(0xdeadbeef);
633 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
634 ok(handle != NULL, "CreateSemaphore failed with error %lu\n", GetLastError());
635 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
637 SetLastError(0xdeadbeef);
638 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
639 ok( handle2 != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
640 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
641 CloseHandle( handle2 );
643 SetLastError(0xdeadbeef);
644 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
645 ok( handle2 != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
646 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
647 CloseHandle( handle2 );
649 SetLastError(0xdeadbeef);
650 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
651 ok( handle2 != NULL, "OpenSemaphore failed with error %ld\n", GetLastError());
652 CloseHandle( handle2 );
654 SetLastError(0xdeadbeef);
655 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
656 ok( !handle2, "OpenSemaphore succeeded\n");
657 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
659 SetLastError(0xdeadbeef);
660 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
661 ok( !handle2, "OpenSemaphore succeeded\n");
662 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
664 SetLastError(0xdeadbeef);
665 handle2 = OpenSemaphoreW( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
666 ok( !handle2, "OpenSemaphore succeeded\n");
667 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
669 CloseHandle( handle );
672 static void test_waitable_timer(void)
674 HANDLE handle, handle2;
676 /* test case sensitivity */
678 SetLastError(0xdeadbeef);
679 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
680 ok(handle != NULL, "CreateWaitableTimer failed with error %lu\n", GetLastError());
681 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
683 SetLastError(0xdeadbeef);
684 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
685 ok( handle2 != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
686 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
687 CloseHandle( handle2 );
689 SetLastError(0xdeadbeef);
690 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
691 ok( handle2 != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
692 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
693 CloseHandle( handle2 );
695 SetLastError(0xdeadbeef);
696 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
697 ok( handle2 != NULL, "OpenWaitableTimer failed with error %ld\n", GetLastError());
698 CloseHandle( handle2 );
700 SetLastError(0xdeadbeef);
701 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
702 ok( !handle2, "OpenWaitableTimer succeeded\n");
703 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
705 SetLastError(0xdeadbeef);
706 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, NULL );
707 ok( !handle2, "OpenWaitableTimer failed with error %ld\n", GetLastError());
708 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
710 SetLastError(0xdeadbeef);
711 handle2 = OpenWaitableTimerW( TIMER_ALL_ACCESS, FALSE, NULL );
712 ok( !handle2, "OpenWaitableTimer failed with error %ld\n", GetLastError());
713 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
715 CloseHandle( handle );
718 static HANDLE sem = 0;
720 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
722 ReleaseSemaphore(sem, 1, NULL);
725 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
727 static void test_iocp_callback(void)
729 char temp_path[MAX_PATH];
730 char filename[MAX_PATH];
731 DWORD ret;
732 BOOL retb;
733 static const char prefix[] = "pfx";
734 HANDLE hFile;
735 HMODULE hmod = GetModuleHandleA("kernel32.dll");
736 DWORD bytesWritten;
737 const char *buffer = "12345678123456781234567812345678";
738 OVERLAPPED overlapped;
740 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
741 if(!p_BindIoCompletionCallback) {
742 win_skip("BindIoCompletionCallback not found in this DLL\n");
743 return;
746 sem = CreateSemaphoreW(NULL, 0, 1, NULL);
747 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
749 ret = GetTempPathA(MAX_PATH, temp_path);
750 ok(ret != 0, "GetTempPathA error %ld\n", GetLastError());
751 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
753 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
754 ok(ret != 0, "GetTempFileNameA error %ld\n", GetLastError());
756 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
757 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
758 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
760 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
761 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
762 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
764 ret = CloseHandle(hFile);
765 ok( ret, "CloseHandle: error %ld\n", GetLastError());
766 ret = DeleteFileA(filename);
767 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
769 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
770 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
771 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
773 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
774 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
776 memset(&overlapped, 0, sizeof(overlapped));
777 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
778 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %ld\n", GetLastError());
780 ret = WaitForSingleObject(sem, 5000);
781 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
782 CloseHandle(sem);
784 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
785 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
786 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
787 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
788 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
789 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
791 ret = CloseHandle(hFile);
792 ok( ret, "CloseHandle: error %ld\n", GetLastError());
793 ret = DeleteFileA(filename);
794 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
796 /* win2k3 requires the Flags parameter to be zero */
797 SetLastError(0xdeadbeef);
798 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
799 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
800 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
801 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
802 if (!retb)
803 ok(GetLastError() == ERROR_INVALID_PARAMETER,
804 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
805 else
806 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
807 ret = CloseHandle(hFile);
808 ok( ret, "CloseHandle: error %ld\n", GetLastError());
809 ret = DeleteFileA(filename);
810 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
812 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
813 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
814 ok(GetLastError() == ERROR_INVALID_HANDLE ||
815 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
816 "Last error is %ld\n", GetLastError());
819 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
821 int *pn = p;
822 ok(timedOut, "Timer callbacks should always time out\n");
823 ++*pn;
826 struct timer_queue_data1
828 int num_calls;
829 int max_calls;
830 HANDLE q, t;
833 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
835 struct timer_queue_data1 *d = p;
836 ok(timedOut, "Timer callbacks should always time out\n");
837 if (d->t && ++d->num_calls == d->max_calls)
839 BOOL ret;
840 SetLastError(0xdeadbeef);
841 /* Note, XP SP2 does *not* do any deadlock checking, so passing
842 INVALID_HANDLE_VALUE here will just hang. */
843 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
844 ok(!ret, "DeleteTimerQueueTimer\n");
845 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
849 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
851 struct timer_queue_data1 *d = p;
852 ok(timedOut, "Timer callbacks should always time out\n");
853 if (d->t && ++d->num_calls == d->max_calls)
855 /* Basically kill the timer since it won't have time to run
856 again. */
857 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0);
858 ok(ret, "ChangeTimerQueueTimer\n");
862 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
864 struct timer_queue_data1 *d = p;
865 ok(timedOut, "Timer callbacks should always time out\n");
866 if (d->t)
868 /* This tests whether a timer gets flagged for deletion before
869 or after the callback runs. If we start this timer with a
870 period of zero (run once), then ChangeTimerQueueTimer will
871 fail if the timer is already flagged. Hence we really run
872 only once. Otherwise we will run multiple times. */
873 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50);
874 ok(ret, "ChangeTimerQueueTimer\n");
875 ++d->num_calls;
879 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
881 DWORD_PTR delay = (DWORD_PTR) p;
882 ok(timedOut, "Timer callbacks should always time out\n");
883 if (delay)
884 Sleep(delay);
887 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
889 struct timer_queue_data1 *d = p;
890 ok(timedOut, "Timer callbacks should always time out\n");
891 /* This tests an original implementation bug where a deleted timer may get
892 to run, but it is tricky to set up. */
893 if (d->q && d->num_calls++ == 0)
895 /* First run: delete ourselves, then insert and remove a timer
896 that goes in front of us in the sorted timeout list. Once
897 removed, we will still timeout at the faster timer's due time,
898 but this should be a no-op if we are bug-free. There should
899 not be a second run. We can test the value of num_calls later. */
900 BOOL ret;
901 HANDLE t;
903 /* The delete will pend while we are in this callback. */
904 SetLastError(0xdeadbeef);
905 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
906 ok(!ret, "DeleteTimerQueueTimer\n");
907 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
909 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
910 ok(ret, "CreateTimerQueueTimer\n");
911 ok(t != NULL, "CreateTimerQueueTimer\n");
913 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
914 ok(ret, "DeleteTimerQueueTimer\n");
916 /* Now we stay alive by hanging around in the callback. */
917 Sleep(500);
921 static void test_timer_queue(void)
923 HANDLE q, t0, t1, t2, t3, t4, t5;
924 int n0, n1, n2, n3, n4, n5;
925 struct timer_queue_data1 d1, d2, d3, d4;
926 HANDLE e, et1, et2;
927 BOOL ret, ret0;
929 /* Test asynchronous deletion of the queue. */
930 q = CreateTimerQueue();
931 ok(q != NULL, "CreateTimerQueue\n");
933 SetLastError(0xdeadbeef);
934 ret = DeleteTimerQueueEx(q, NULL);
935 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
936 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
937 GetLastError());
939 /* Test synchronous deletion of the queue and running timers. */
940 q = CreateTimerQueue();
941 ok(q != NULL, "CreateTimerQueue\n");
943 /* Not called. */
944 t0 = NULL;
945 n0 = 0;
946 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0);
947 ok(ret, "CreateTimerQueueTimer\n");
948 ok(t0 != NULL, "CreateTimerQueueTimer\n");
949 ret0 = DeleteTimerQueueTimer(q, t0, NULL);
950 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
951 broken(ret0), /* Win 2000 & XP & 2003 */
952 "DeleteTimerQueueTimer ret=%d le=%lu\n", ret0, GetLastError());
954 /* Called once. */
955 t1 = NULL;
956 n1 = 0;
957 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0);
958 ok(ret, "CreateTimerQueueTimer\n");
959 ok(t1 != NULL, "CreateTimerQueueTimer\n");
961 /* A slow one. */
962 t2 = NULL;
963 n2 = 0;
964 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0);
965 ok(ret, "CreateTimerQueueTimer\n");
966 ok(t2 != NULL, "CreateTimerQueueTimer\n");
968 /* A fast one. */
969 t3 = NULL;
970 n3 = 0;
971 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0);
972 ok(ret, "CreateTimerQueueTimer\n");
973 ok(t3 != NULL, "CreateTimerQueueTimer\n");
975 /* Start really late (it won't start). */
976 t4 = NULL;
977 n4 = 0;
978 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0);
979 ok(ret, "CreateTimerQueueTimer\n");
980 ok(t4 != NULL, "CreateTimerQueueTimer\n");
982 /* Start soon, but delay so long it won't run again. */
983 t5 = NULL;
984 n5 = 0;
985 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0);
986 ok(ret, "CreateTimerQueueTimer\n");
987 ok(t5 != NULL, "CreateTimerQueueTimer\n");
989 /* Give them a chance to do some work. */
990 Sleep(500);
992 /* Test deleting a once-only timer. */
993 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
994 ok(ret, "DeleteTimerQueueTimer\n");
996 /* A periodic timer. */
997 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
998 ok(ret, "DeleteTimerQueueTimer\n");
1000 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1001 ok(ret, "DeleteTimerQueueEx\n");
1002 todo_wine
1003 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
1004 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
1005 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
1006 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
1007 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
1009 /* Test synchronous deletion of the timer/queue with event trigger. */
1010 e = CreateEventW(NULL, TRUE, FALSE, NULL);
1011 et1 = CreateEventW(NULL, TRUE, FALSE, NULL);
1012 et2 = CreateEventW(NULL, TRUE, FALSE, NULL);
1013 if (!e || !et1 || !et2)
1015 skip("Failed to create timer queue descruction event\n");
1016 return;
1019 q = CreateTimerQueue();
1020 ok(q != NULL, "CreateTimerQueue\n");
1022 /* Run once and finish quickly (should be done when we delete it). */
1023 t1 = NULL;
1024 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
1025 ok(ret, "CreateTimerQueueTimer\n");
1026 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1028 /* Run once and finish slowly (shouldn't be done when we delete it). */
1029 t2 = NULL;
1030 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
1031 ok(ret, "CreateTimerQueueTimer\n");
1032 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1034 /* Run once and finish quickly (should be done when we delete it). */
1035 t3 = NULL;
1036 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
1037 ok(ret, "CreateTimerQueueTimer\n");
1038 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1040 /* Run once and finish slowly (shouldn't be done when we delete it). */
1041 t4 = NULL;
1042 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
1043 ok(ret, "CreateTimerQueueTimer\n");
1044 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1046 /* Give them a chance to start. */
1047 Sleep(400);
1049 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1050 even if the timer is finished. */
1051 SetLastError(0xdeadbeef);
1052 ret = DeleteTimerQueueTimer(q, t1, NULL);
1053 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1054 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1055 GetLastError());
1057 SetLastError(0xdeadbeef);
1058 ret = DeleteTimerQueueTimer(q, t2, NULL);
1059 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1060 ok(GetLastError() == ERROR_IO_PENDING,
1061 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1062 GetLastError());
1064 SetLastError(0xdeadbeef);
1065 ret = DeleteTimerQueueTimer(q, t3, et1);
1066 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
1067 ok(GetLastError() == 0xdeadbeef,
1068 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %ld\n",
1069 GetLastError());
1070 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
1071 "Timer destruction event not triggered\n");
1073 SetLastError(0xdeadbeef);
1074 ret = DeleteTimerQueueTimer(q, t4, et2);
1075 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1076 ok(GetLastError() == ERROR_IO_PENDING,
1077 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1078 GetLastError());
1079 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
1080 "Timer destruction event not triggered\n");
1082 SetLastError(0xdeadbeef);
1083 ret = DeleteTimerQueueEx(q, e);
1084 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1085 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1086 GetLastError());
1087 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
1088 "Queue destruction event not triggered\n");
1089 CloseHandle(e);
1091 /* Test deleting/changing a timer in execution. */
1092 q = CreateTimerQueue();
1093 ok(q != NULL, "CreateTimerQueue\n");
1095 /* Test changing a once-only timer before it fires (this is allowed,
1096 whereas after it fires you cannot). */
1097 n1 = 0;
1098 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0);
1099 ok(ret, "CreateTimerQueueTimer\n");
1100 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1101 ret = ChangeTimerQueueTimer(q, t1, 0, 0);
1102 ok(ret, "ChangeTimerQueueTimer\n");
1104 d2.t = t2 = NULL;
1105 d2.num_calls = 0;
1106 d2.max_calls = 3;
1107 d2.q = q;
1108 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0);
1109 d2.t = t2;
1110 ok(ret, "CreateTimerQueueTimer\n");
1111 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1113 d3.t = t3 = NULL;
1114 d3.num_calls = 0;
1115 d3.max_calls = 4;
1116 d3.q = q;
1117 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0);
1118 d3.t = t3;
1119 ok(ret, "CreateTimerQueueTimer\n");
1120 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1122 d4.t = t4 = NULL;
1123 d4.num_calls = 0;
1124 d4.q = q;
1125 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0);
1126 d4.t = t4;
1127 ok(ret, "CreateTimerQueueTimer\n");
1128 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1130 Sleep(500);
1132 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1133 ok(ret, "DeleteTimerQueueEx\n");
1134 ok(n1 == 1, "ChangeTimerQueueTimer\n");
1135 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
1136 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
1137 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
1139 /* Test an obscure bug that was in the original implementation. */
1140 q = CreateTimerQueue();
1141 ok(q != NULL, "CreateTimerQueue\n");
1143 /* All the work is done in the callback. */
1144 d1.t = t1 = NULL;
1145 d1.num_calls = 0;
1146 d1.q = q;
1147 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION);
1148 d1.t = t1;
1149 ok(ret, "CreateTimerQueueTimer\n");
1150 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1152 Sleep(750);
1154 SetLastError(0xdeadbeef);
1155 ret = DeleteTimerQueueEx(q, NULL);
1156 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1157 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1158 GetLastError());
1159 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
1161 /* Test functions on the default timer queue. */
1162 t1 = NULL;
1163 n1 = 0;
1164 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0);
1165 ok(ret, "CreateTimerQueueTimer, default queue\n");
1166 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
1168 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1169 ok(ret, "ChangeTimerQueueTimer, default queue\n");
1171 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1172 ok(ret, "DeleteTimerQueueTimer, default queue\n");
1174 /* Try mixing default and non-default queues. Apparently this works. */
1175 q = CreateTimerQueue();
1176 ok(q != NULL, "CreateTimerQueue\n");
1178 t1 = NULL;
1179 n1 = 0;
1180 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0);
1181 ok(ret, "CreateTimerQueueTimer\n");
1182 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1184 t2 = NULL;
1185 n2 = 0;
1186 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0);
1187 ok(ret, "CreateTimerQueueTimer\n");
1188 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1190 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1191 ok(ret, "ChangeTimerQueueTimer\n");
1193 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000);
1194 ok(ret, "ChangeTimerQueueTimer\n");
1196 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1197 ok(ret, "DeleteTimerQueueTimer\n");
1199 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1200 ok(ret, "DeleteTimerQueueTimer\n");
1202 /* Try to delete the default queue? In any case: not allowed. */
1203 SetLastError(0xdeadbeef);
1204 ret = DeleteTimerQueueEx(NULL, NULL);
1205 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1206 ok(GetLastError() == ERROR_INVALID_HANDLE,
1207 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %ld\n",
1208 GetLastError());
1210 SetLastError(0xdeadbeef);
1211 ret = DeleteTimerQueueEx(q, NULL);
1212 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1213 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1214 GetLastError());
1217 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1219 DWORD tmp = HandleToULong(handle);
1220 tmp |= modify;
1221 return ULongToHandle(tmp);
1224 static void test_WaitForSingleObject(void)
1226 HANDLE signaled, nonsignaled, invalid;
1227 LARGE_INTEGER timeout;
1228 NTSTATUS status;
1229 DWORD ret;
1231 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1232 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1233 invalid = (HANDLE) 0xdeadbee0;
1235 /* invalid handle with different values for lower 2 bits */
1236 SetLastError(0xdeadbeef);
1237 ret = WaitForSingleObject(invalid, 0);
1238 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1239 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1241 SetLastError(0xdeadbeef);
1242 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1243 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1244 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1246 SetLastError(0xdeadbeef);
1247 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1248 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1249 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1251 SetLastError(0xdeadbeef);
1252 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1253 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1254 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1256 /* valid handle with different values for lower 2 bits */
1257 SetLastError(0xdeadbeef);
1258 ret = WaitForSingleObject(nonsignaled, 0);
1259 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1260 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1262 SetLastError(0xdeadbeef);
1263 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1264 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1265 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1267 SetLastError(0xdeadbeef);
1268 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1269 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1270 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1272 SetLastError(0xdeadbeef);
1273 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1274 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1275 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1277 /* valid handle with different values for lower 2 bits */
1278 SetLastError(0xdeadbeef);
1279 ret = WaitForSingleObject(signaled, 0);
1280 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1281 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1283 SetLastError(0xdeadbeef);
1284 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1285 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1286 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1288 SetLastError(0xdeadbeef);
1289 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1290 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1291 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1293 SetLastError(0xdeadbeef);
1294 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1295 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1296 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1298 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1299 ret = WaitForSingleObject(GetCurrentProcess(), 100);
1300 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret);
1302 ret = WaitForSingleObject(GetCurrentThread(), 100);
1303 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret);
1305 timeout.QuadPart = -1000000;
1306 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout);
1307 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status);
1309 timeout.QuadPart = -1000000;
1310 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout);
1311 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status);
1313 CloseHandle(signaled);
1314 CloseHandle(nonsignaled);
1317 static void test_WaitForMultipleObjects(void)
1319 LARGE_INTEGER timeout;
1320 NTSTATUS status;
1321 DWORD r;
1322 int i;
1323 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1325 /* create the maximum number of events and make sure
1326 * we can wait on that many */
1327 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1329 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL);
1330 ok( maxevents[i] != 0, "should create enough events\n");
1333 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1334 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1335 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %ld\n", r);
1336 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1337 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %ld\n", r);
1338 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1339 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1341 /* the lowest index is checked first and remaining events are untouched */
1342 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1343 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %ld\n", i, r);
1346 /* run same test with Nt* call */
1347 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1348 SetEvent(maxevents[i]);
1350 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1351 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1352 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08lx\n", status);
1353 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1354 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08lx\n", status);
1355 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1356 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1358 /* the lowest index is checked first and remaining events are untouched */
1359 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1360 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08lx\n", i, status);
1363 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1364 if (maxevents[i]) CloseHandle(maxevents[i]);
1366 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1367 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1368 maxevents[0] = GetCurrentProcess();
1369 SetLastError(0xdeadbeef);
1370 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1371 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r);
1372 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1373 "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError());
1375 maxevents[0] = GetCurrentThread();
1376 SetLastError(0xdeadbeef);
1377 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1378 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r);
1379 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1380 "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError());
1382 timeout.QuadPart = -1000000;
1383 maxevents[0] = GetCurrentProcess();
1384 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1385 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1387 timeout.QuadPart = -1000000;
1388 maxevents[0] = GetCurrentThread();
1389 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1390 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1393 static BOOL g_initcallback_ret, g_initcallback_called;
1394 static void *g_initctxt;
1396 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1398 g_initcallback_called = TRUE;
1399 /* zero bit set means here that initialization is taking place - initialization locked */
1400 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1401 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1402 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1403 return g_initcallback_ret;
1406 static void test_initonce(void)
1408 INIT_ONCE initonce;
1409 BOOL ret, pending;
1411 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1413 win_skip("one-time initialization API not supported\n");
1414 return;
1417 /* blocking initialization with callback */
1418 initonce.Ptr = (void*)0xdeadbeef;
1419 pInitOnceInitialize(&initonce);
1420 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1422 /* initialisation completed successfully */
1423 g_initcallback_ret = TRUE;
1424 g_initctxt = NULL;
1425 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1426 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1427 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1428 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1429 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1431 /* so it's been called already so won't be called again */
1432 g_initctxt = NULL;
1433 g_initcallback_called = FALSE;
1434 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1435 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1436 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1437 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1438 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1440 pInitOnceInitialize(&initonce);
1441 g_initcallback_called = FALSE;
1442 /* 2 lower order bits should never be used, you'll get a crash in result */
1443 g_initctxt = (void*)0xFFFFFFF0;
1444 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1445 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1446 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1447 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1448 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1450 /* callback failed */
1451 g_initcallback_ret = FALSE;
1452 g_initcallback_called = FALSE;
1453 g_initctxt = NULL;
1454 pInitOnceInitialize(&initonce);
1455 SetLastError( 0xdeadbeef );
1456 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1457 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %lu\n", ret, GetLastError());
1458 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1459 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1460 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1462 /* blocking initialization without a callback */
1463 pInitOnceInitialize(&initonce);
1464 g_initctxt = NULL;
1465 pending = FALSE;
1466 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1467 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1468 ok(pending, "got %d\n", pending);
1469 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1470 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1471 /* another attempt to begin initialization with block a single thread */
1473 g_initctxt = NULL;
1474 pending = 0xf;
1475 SetLastError( 0xdeadbeef );
1476 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1477 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1478 ok(pending == 0xf, "got %d\n", pending);
1479 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1480 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1482 g_initctxt = (void*)0xdeadbee0;
1483 SetLastError( 0xdeadbeef );
1484 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1485 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1486 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1488 /* once failed already */
1489 g_initctxt = (void*)0xdeadbee0;
1490 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1491 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1492 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1494 pInitOnceInitialize(&initonce);
1495 SetLastError( 0xdeadbeef );
1496 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1497 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1498 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1500 SetLastError( 0xdeadbeef );
1501 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1502 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1503 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1505 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1506 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1507 ok(pending, "got %d\n", pending);
1508 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1510 SetLastError( 0xdeadbeef );
1511 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1512 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1514 SetLastError( 0xdeadbeef );
1515 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1516 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1517 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1519 SetLastError( 0xdeadbeef );
1520 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef);
1521 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1522 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1524 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1525 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1526 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1528 pInitOnceInitialize(&initonce);
1529 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1530 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1531 ok(pending, "got %d\n", pending);
1532 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1534 SetLastError( 0xdeadbeef );
1535 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1536 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1538 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1539 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1540 ok(pending, "got %d\n", pending);
1541 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1543 SetLastError( 0xdeadbeef );
1544 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1545 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1546 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1548 SetLastError( 0xdeadbeef );
1549 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1550 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1551 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1553 SetLastError( 0xdeadbeef );
1554 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef);
1555 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1556 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1558 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1559 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1560 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1562 SetLastError( 0xdeadbeef );
1563 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1564 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1565 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1567 pInitOnceInitialize(&initonce);
1568 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1569 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1570 ok(pending, "got %d\n", pending);
1571 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1573 /* test INIT_ONCE_CHECK_ONLY */
1575 pInitOnceInitialize(&initonce);
1576 SetLastError( 0xdeadbeef );
1577 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1578 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1579 SetLastError( 0xdeadbeef );
1580 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1581 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1583 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1584 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1585 ok(pending, "got %d\n", pending);
1586 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1588 SetLastError( 0xdeadbeef );
1589 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1590 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1591 SetLastError( 0xdeadbeef );
1592 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1593 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1595 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0);
1596 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1597 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1599 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1600 ok(ret, "got wrong ret value %d err %lu\n", ret, GetLastError());
1601 ok(!pending, "got %d\n", pending);
1602 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1603 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1605 SetLastError( 0xdeadbeef );
1606 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1607 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1609 pInitOnceInitialize(&initonce);
1610 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1611 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1612 ok(pending, "got %d\n", pending);
1613 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1615 SetLastError( 0xdeadbeef );
1616 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1617 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1618 SetLastError( 0xdeadbeef );
1619 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1620 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1622 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1623 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1624 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1626 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1627 ok(ret, "got wrong ret value %d err %lu\n", ret, GetLastError());
1628 ok(!pending, "got %d\n", pending);
1629 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1630 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1632 SetLastError( 0xdeadbeef );
1633 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1634 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1637 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT;
1638 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT;
1639 static CRITICAL_SECTION buffercrit;
1640 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1641 static LONG bufferlen,totalproduced,totalconsumed;
1642 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1644 #define BUFFER_SIZE 5
1646 static DWORD WINAPI condvar_producer(LPVOID x) {
1647 DWORD sleepinterval = 5;
1649 while (1) {
1650 Sleep(sleepinterval);
1651 if (sleepinterval > 1)
1652 sleepinterval -= 1;
1654 EnterCriticalSection(&buffercrit);
1655 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1656 condvar_producer_sleepcnt++;
1657 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) {
1658 if (GetLastError() != ERROR_TIMEOUT)
1659 condvar_sleeperr = TRUE;
1662 if (condvar_stop) {
1663 LeaveCriticalSection(&buffercrit);
1664 break;
1666 bufferlen++;
1667 totalproduced++;
1668 LeaveCriticalSection(&buffercrit);
1669 pWakeConditionVariable(&buffernotempty);
1671 return 0;
1674 static DWORD WINAPI condvar_consumer(LPVOID x) {
1675 DWORD *cnt = (DWORD*)x;
1676 DWORD sleepinterval = 1;
1678 while (1) {
1679 EnterCriticalSection(&buffercrit);
1680 while ((bufferlen == 0) && !condvar_stop) {
1681 condvar_consumer_sleepcnt++;
1682 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) {
1683 if (GetLastError() != ERROR_TIMEOUT)
1684 condvar_sleeperr = TRUE;
1687 if (condvar_stop && (bufferlen == 0)) {
1688 LeaveCriticalSection(&buffercrit);
1689 break;
1691 bufferlen--;
1692 totalconsumed++;
1693 (*cnt)++;
1694 LeaveCriticalSection(&buffercrit);
1695 pWakeConditionVariable(&buffernotfull);
1696 Sleep(sleepinterval);
1697 if (sleepinterval < 5) sleepinterval += 1;
1699 return 0;
1702 static void test_condvars_consumer_producer(void)
1704 HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
1705 DWORD dummy;
1706 DWORD cnt1,cnt2,cnt3;
1708 if (!pInitializeConditionVariable) {
1709 /* function is not yet in XP, only in newer Windows */
1710 win_skip("no condition variable support.\n");
1711 return;
1714 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1716 /* If we have static initialized condition variables, InitializeConditionVariable
1717 * is not strictly necessary.
1718 * pInitializeConditionVariable(&buffernotfull);
1720 pInitializeConditionVariable(&buffernotempty);
1721 InitializeCriticalSection(&buffercrit);
1723 /* Larger Test: consumer/producer example */
1725 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
1727 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1728 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1729 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1730 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1731 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1732 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy);
1734 /* Limit run to 0.5 seconds. */
1735 Sleep(500);
1737 /* tear down start */
1738 condvar_stop = TRUE;
1740 /* final wake up call */
1741 pWakeAllConditionVariable (&buffernotfull);
1742 pWakeAllConditionVariable (&buffernotempty);
1744 /* (mostly an implementation detail)
1745 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1748 WaitForSingleObject(hp1, 1000);
1749 WaitForSingleObject(hp2, 1000);
1750 WaitForSingleObject(hp3, 1000);
1751 WaitForSingleObject(hc1, 1000);
1752 WaitForSingleObject(hc2, 1000);
1753 WaitForSingleObject(hc3, 1000);
1755 ok(totalconsumed == totalproduced,
1756 "consumed %ld != produced %ld\n", totalconsumed, totalproduced);
1757 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1759 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1760 * one consumer does not get anything to do is possible. */
1761 trace("produced %ld, c1 %ld, c2 %ld, c3 %ld\n", totalproduced, cnt1, cnt2, cnt3);
1762 /* The sleeps of the producer or consumer should not go above 100* produced count,
1763 * otherwise the implementation does not sleep correctly. But yet again, this is
1764 * not hard defined. */
1765 trace("producer sleep %ld, consumer sleep %ld\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1768 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1769 static DWORD condvar_seq = 0;
1770 static CONDITION_VARIABLE aligned_cv;
1771 static CRITICAL_SECTION condvar_crit;
1772 static SRWLOCK condvar_srwlock;
1774 #include "pshpack1.h"
1775 static struct
1777 char c;
1778 CONDITION_VARIABLE cv;
1779 } unaligned_cv;
1780 #include "poppack.h"
1782 /* Sequence of wake/sleep to check boundary conditions:
1783 * 0: init
1784 * 1: producer emits a WakeConditionVariable without consumer waiting.
1785 * 2: consumer sleeps without a wake expecting timeout
1786 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1787 * 4: consumer sleeps without a wake expecting timeout
1788 * 5: a wake is handed to a SleepConditionVariableCS
1789 * 6: a wakeall is handed to a SleepConditionVariableCS
1790 * 7: sleep after above should timeout
1791 * 8: wake with crit section locked into the sleep timeout
1793 * the following tests will only be executed if InitializeSRWLock is available
1795 * 9: producer (exclusive) wakes up consumer (exclusive)
1796 * 10: producer (exclusive) wakes up consumer (shared)
1797 * 11: producer (shared) wakes up consumer (exclusive)
1798 * 12: producer (shared) wakes up consumer (shared)
1799 * 13: end
1801 static DWORD WINAPI condvar_base_producer(void *arg)
1803 CONDITION_VARIABLE *cv = arg;
1805 while (condvar_seq < 1) Sleep(1);
1807 pWakeConditionVariable(cv);
1808 condvar_seq = 2;
1810 while (condvar_seq < 3) Sleep(1);
1811 pWakeAllConditionVariable(cv);
1812 condvar_seq = 4;
1814 while (condvar_seq < 5) Sleep(1);
1815 EnterCriticalSection (&condvar_crit);
1816 pWakeConditionVariable(cv);
1817 LeaveCriticalSection (&condvar_crit);
1818 while (condvar_seq < 6) Sleep(1);
1819 EnterCriticalSection (&condvar_crit);
1820 pWakeAllConditionVariable(cv);
1821 LeaveCriticalSection (&condvar_crit);
1823 while (condvar_seq < 8) Sleep(1);
1824 EnterCriticalSection (&condvar_crit);
1825 pWakeConditionVariable(cv);
1826 Sleep(50);
1827 LeaveCriticalSection (&condvar_crit);
1829 /* skip over remaining tests if InitializeSRWLock is not available */
1830 if (!pInitializeSRWLock)
1831 return 0;
1833 while (condvar_seq < 9) Sleep(1);
1834 pAcquireSRWLockExclusive(&condvar_srwlock);
1835 pWakeConditionVariable(cv);
1836 pReleaseSRWLockExclusive(&condvar_srwlock);
1838 while (condvar_seq < 10) Sleep(1);
1839 pAcquireSRWLockExclusive(&condvar_srwlock);
1840 pWakeConditionVariable(cv);
1841 pReleaseSRWLockExclusive(&condvar_srwlock);
1843 while (condvar_seq < 11) Sleep(1);
1844 pAcquireSRWLockShared(&condvar_srwlock);
1845 pWakeConditionVariable(cv);
1846 pReleaseSRWLockShared(&condvar_srwlock);
1848 while (condvar_seq < 12) Sleep(1);
1849 Sleep(50); /* ensure that consumer waits for cond variable */
1850 pAcquireSRWLockShared(&condvar_srwlock);
1851 pWakeConditionVariable(cv);
1852 pReleaseSRWLockShared(&condvar_srwlock);
1854 return 0;
1857 static DWORD WINAPI condvar_base_consumer(void *arg)
1859 CONDITION_VARIABLE *cv = arg;
1860 BOOL ret;
1862 while (condvar_seq < 2) Sleep(1);
1864 /* wake was emitted, but we were not sleeping */
1865 EnterCriticalSection (&condvar_crit);
1866 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1867 LeaveCriticalSection (&condvar_crit);
1868 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1869 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
1871 condvar_seq = 3;
1872 while (condvar_seq < 4) Sleep(1);
1874 /* wake all was emitted, but we were not sleeping */
1875 EnterCriticalSection (&condvar_crit);
1876 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1877 LeaveCriticalSection (&condvar_crit);
1878 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1879 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
1881 EnterCriticalSection (&condvar_crit);
1882 condvar_seq = 5;
1883 ret = pSleepConditionVariableCS(cv, &condvar_crit, 200);
1884 LeaveCriticalSection (&condvar_crit);
1885 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
1887 EnterCriticalSection (&condvar_crit);
1888 condvar_seq = 6;
1889 ret = pSleepConditionVariableCS(cv, &condvar_crit, 200);
1890 LeaveCriticalSection (&condvar_crit);
1891 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1892 condvar_seq = 7;
1894 EnterCriticalSection (&condvar_crit);
1895 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1896 LeaveCriticalSection (&condvar_crit);
1897 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1898 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
1900 EnterCriticalSection (&condvar_crit);
1901 condvar_seq = 8;
1902 ret = pSleepConditionVariableCS(cv, &condvar_crit, 20);
1903 LeaveCriticalSection (&condvar_crit);
1904 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1906 /* skip over remaining tests if InitializeSRWLock is not available */
1907 if (!pInitializeSRWLock)
1909 win_skip("no srw lock support.\n");
1910 condvar_seq = 13; /* end */
1911 return 0;
1914 pAcquireSRWLockExclusive(&condvar_srwlock);
1915 condvar_seq = 9;
1916 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0);
1917 pReleaseSRWLockExclusive(&condvar_srwlock);
1918 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1920 pAcquireSRWLockShared(&condvar_srwlock);
1921 condvar_seq = 10;
1922 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1923 pReleaseSRWLockShared(&condvar_srwlock);
1924 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1926 pAcquireSRWLockExclusive(&condvar_srwlock);
1927 condvar_seq = 11;
1928 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0);
1929 pReleaseSRWLockExclusive(&condvar_srwlock);
1930 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1932 pAcquireSRWLockShared(&condvar_srwlock);
1933 condvar_seq = 12;
1934 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1935 pReleaseSRWLockShared(&condvar_srwlock);
1936 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1938 condvar_seq = 13;
1939 return 0;
1942 static void test_condvars_base(RTL_CONDITION_VARIABLE *cv)
1944 HANDLE hp, hc;
1945 DWORD dummy;
1946 BOOL ret;
1948 if (!pInitializeConditionVariable) {
1949 /* function is not yet in XP, only in newer Windows */
1950 win_skip("no condition variable support.\n");
1951 return;
1954 InitializeCriticalSection (&condvar_crit);
1956 if (pInitializeSRWLock)
1957 pInitializeSRWLock(&condvar_srwlock);
1959 EnterCriticalSection (&condvar_crit);
1960 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1961 LeaveCriticalSection (&condvar_crit);
1963 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1964 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
1966 if (pInitializeSRWLock)
1968 pAcquireSRWLockExclusive(&condvar_srwlock);
1969 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, 0);
1970 pReleaseSRWLockExclusive(&condvar_srwlock);
1972 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1973 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
1975 pAcquireSRWLockShared(&condvar_srwlock);
1976 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED);
1977 pReleaseSRWLockShared(&condvar_srwlock);
1979 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1980 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
1983 condvar_seq = 0;
1984 hp = CreateThread(NULL, 0, condvar_base_producer, cv, 0, &dummy);
1985 hc = CreateThread(NULL, 0, condvar_base_consumer, cv, 0, &dummy);
1987 condvar_seq = 1; /* go */
1989 while (condvar_seq < 9)
1990 Sleep (5);
1991 WaitForSingleObject(hp, 100);
1992 WaitForSingleObject(hc, 100);
1995 static LONG srwlock_seq = 0;
1996 static SRWLOCK aligned_srwlock;
1997 static struct
1999 LONG wrong_execution_order;
2000 LONG samethread_excl_excl;
2001 LONG samethread_excl_shared;
2002 LONG samethread_shared_excl;
2003 LONG multithread_excl_excl;
2004 LONG excl_not_preferred;
2005 LONG trylock_excl;
2006 LONG trylock_shared;
2007 } srwlock_base_errors;
2009 #if defined(__i386__) || defined(__x86_64__)
2010 #include "pshpack1.h"
2011 struct
2013 char c;
2014 SRWLOCK lock;
2015 } unaligned_srwlock;
2016 #include "poppack.h"
2017 #endif
2019 /* Sequence of acquire/release to check boundary conditions:
2020 * 0: init
2022 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
2023 * 2: thread1 expects a deadlock and releases the waiting lock
2024 * thread2 releases the lock again
2026 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
2027 * 4: thread1 expects a deadlock and releases the waiting lock
2028 * thread2 releases the lock again
2030 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
2031 * 6: thread1 expects a deadlock and releases the waiting lock
2032 * thread2 releases the lock again
2034 * 7: thread2 acquires and releases two nested shared locks
2036 * 8: thread1 acquires an exclusive lock
2037 * 9: thread2 tries to acquire the exclusive lock, too
2038 * thread1 releases the exclusive lock again
2039 * 10: thread2 enters the exclusive lock and leaves it immediately again
2041 * 11: thread1 acquires a shared lock
2042 * 12: thread2 acquires and releases a shared lock
2043 * thread1 releases the lock again
2045 * 13: thread1 acquires a shared lock
2046 * 14: thread2 tries to acquire an exclusive lock
2047 * 15: thread3 tries to acquire a shared lock
2048 * 16: thread1 releases the shared lock
2049 * 17: thread2 wakes up and releases the exclusive lock
2050 * 18: thread3 wakes up and releases the shared lock
2052 * the following tests will only be executed if TryAcquireSRWLock* is available
2054 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
2055 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2056 * thread1 releases the exclusive lock
2058 * thread1 calls TryAcquireSRWLockShared which should return TRUE
2059 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2060 * thread1 releases the shared lock
2062 * thread1 acquires an exclusive lock
2063 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
2064 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2065 * 21: thread1 releases the exclusive lock
2067 * thread1 acquires an shared lock
2068 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2069 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2070 * 23: thread1 releases the shared lock
2072 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2073 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2074 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2075 * 25: thread1 releases the exclusive lock
2077 * thread1 acquires two shared locks
2078 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2079 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2080 * 27: thread1 releases one shared lock
2081 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2082 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2083 * 29: thread1 releases the second shared lock
2084 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2085 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2087 * 31: end
2090 static DWORD WINAPI srwlock_base_thread1(void *arg)
2092 SRWLOCK *lock = arg;
2094 /* seq 2 */
2095 while (srwlock_seq < 2) Sleep(1);
2096 Sleep(100);
2097 if (InterlockedIncrement(&srwlock_seq) != 3)
2098 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2099 pReleaseSRWLockExclusive(lock);
2101 /* seq 4 */
2102 while (srwlock_seq < 4) Sleep(1);
2103 Sleep(100);
2104 if (InterlockedIncrement(&srwlock_seq) != 5)
2105 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2106 pReleaseSRWLockExclusive(lock);
2108 /* seq 6 */
2109 while (srwlock_seq < 6) Sleep(1);
2110 Sleep(100);
2111 if (InterlockedIncrement(&srwlock_seq) != 7)
2112 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2113 pReleaseSRWLockShared(lock);
2115 /* seq 8 */
2116 while (srwlock_seq < 8) Sleep(1);
2117 pAcquireSRWLockExclusive(lock);
2118 if (InterlockedIncrement(&srwlock_seq) != 9)
2119 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2120 Sleep(100);
2121 if (InterlockedIncrement(&srwlock_seq) != 10)
2122 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2123 pReleaseSRWLockExclusive(lock);
2125 /* seq 11 */
2126 while (srwlock_seq < 11) Sleep(1);
2127 pAcquireSRWLockShared(lock);
2128 if (InterlockedIncrement(&srwlock_seq) != 12)
2129 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2131 /* seq 13 */
2132 while (srwlock_seq < 13) Sleep(1);
2133 pReleaseSRWLockShared(lock);
2134 pAcquireSRWLockShared(lock);
2135 if (InterlockedIncrement(&srwlock_seq) != 14)
2136 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2138 /* seq 16 */
2139 while (srwlock_seq < 16) Sleep(1);
2140 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2141 if (InterlockedIncrement(&srwlock_seq) != 17)
2142 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2143 pReleaseSRWLockShared(lock);
2145 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2146 if (!pTryAcquireSRWLockExclusive)
2147 return 0;
2149 /* seq 19 */
2150 while (srwlock_seq < 19) Sleep(1);
2151 if (pTryAcquireSRWLockExclusive(lock))
2153 if (pTryAcquireSRWLockShared(lock))
2154 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2155 if (pTryAcquireSRWLockExclusive(lock))
2156 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2157 pReleaseSRWLockExclusive(lock);
2159 else
2160 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2162 if (pTryAcquireSRWLockShared(lock))
2164 if (pTryAcquireSRWLockShared(lock))
2165 pReleaseSRWLockShared(lock);
2166 else
2167 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2168 if (pTryAcquireSRWLockExclusive(lock))
2169 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2170 pReleaseSRWLockShared(lock);
2172 else
2173 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2175 pAcquireSRWLockExclusive(lock);
2176 if (InterlockedIncrement(&srwlock_seq) != 20)
2177 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2179 /* seq 21 */
2180 while (srwlock_seq < 21) Sleep(1);
2181 pReleaseSRWLockExclusive(lock);
2182 pAcquireSRWLockShared(lock);
2183 if (InterlockedIncrement(&srwlock_seq) != 22)
2184 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2186 /* seq 23 */
2187 while (srwlock_seq < 23) Sleep(1);
2188 pReleaseSRWLockShared(lock);
2189 pAcquireSRWLockShared(lock);
2190 if (InterlockedIncrement(&srwlock_seq) != 24)
2191 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2193 /* seq 25 */
2194 pAcquireSRWLockExclusive(lock);
2195 if (srwlock_seq != 25)
2196 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2197 pReleaseSRWLockExclusive(lock);
2199 pAcquireSRWLockShared(lock);
2200 pAcquireSRWLockShared(lock);
2201 if (InterlockedIncrement(&srwlock_seq) != 26)
2202 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2204 /* seq 27 */
2205 while (srwlock_seq < 27) Sleep(1);
2206 pReleaseSRWLockShared(lock);
2207 if (InterlockedIncrement(&srwlock_seq) != 28)
2208 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2210 /* seq 29 */
2211 while (srwlock_seq < 29) Sleep(1);
2212 pReleaseSRWLockShared(lock);
2213 if (InterlockedIncrement(&srwlock_seq) != 30)
2214 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2216 return 0;
2219 static DWORD WINAPI srwlock_base_thread2(void *arg)
2221 SRWLOCK *lock = arg;
2223 /* seq 1 */
2224 while (srwlock_seq < 1) Sleep(1);
2225 pAcquireSRWLockExclusive(lock);
2226 if (InterlockedIncrement(&srwlock_seq) != 2)
2227 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2229 /* seq 3 */
2230 pAcquireSRWLockExclusive(lock);
2231 if (srwlock_seq != 3)
2232 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2233 pReleaseSRWLockExclusive(lock);
2234 pAcquireSRWLockExclusive(lock);
2235 if (InterlockedIncrement(&srwlock_seq) != 4)
2236 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2238 /* seq 5 */
2239 pAcquireSRWLockShared(lock);
2240 if (srwlock_seq != 5)
2241 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2242 pReleaseSRWLockShared(lock);
2243 pAcquireSRWLockShared(lock);
2244 if (InterlockedIncrement(&srwlock_seq) != 6)
2245 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2247 /* seq 7 */
2248 pAcquireSRWLockExclusive(lock);
2249 if (srwlock_seq != 7)
2250 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2251 pReleaseSRWLockExclusive(lock);
2252 pAcquireSRWLockShared(lock);
2253 pAcquireSRWLockShared(lock);
2254 pReleaseSRWLockShared(lock);
2255 pReleaseSRWLockShared(lock);
2256 if (InterlockedIncrement(&srwlock_seq) != 8)
2257 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2259 /* seq 9, 10 */
2260 while (srwlock_seq < 9) Sleep(1);
2261 pAcquireSRWLockExclusive(lock);
2262 if (srwlock_seq != 10)
2263 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2264 pReleaseSRWLockExclusive(lock);
2265 if (InterlockedIncrement(&srwlock_seq) != 11)
2266 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2268 /* seq 12 */
2269 while (srwlock_seq < 12) Sleep(1);
2270 pAcquireSRWLockShared(lock);
2271 pReleaseSRWLockShared(lock);
2272 if (InterlockedIncrement(&srwlock_seq) != 13)
2273 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2275 /* seq 14 */
2276 while (srwlock_seq < 14) Sleep(1);
2277 if (InterlockedIncrement(&srwlock_seq) != 15)
2278 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2280 /* seq 17 */
2281 pAcquireSRWLockExclusive(lock);
2282 if (srwlock_seq != 17)
2283 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2284 if (InterlockedIncrement(&srwlock_seq) != 18)
2285 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2286 pReleaseSRWLockExclusive(lock);
2288 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2289 if (!pTryAcquireSRWLockExclusive)
2290 return 0;
2292 /* seq 20 */
2293 while (srwlock_seq < 20) Sleep(1);
2294 if (pTryAcquireSRWLockShared(lock))
2295 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2296 if (pTryAcquireSRWLockExclusive(lock))
2297 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2298 if (InterlockedIncrement(&srwlock_seq) != 21)
2299 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2301 /* seq 22 */
2302 while (srwlock_seq < 22) Sleep(1);
2303 if (pTryAcquireSRWLockShared(lock))
2304 pReleaseSRWLockShared(lock);
2305 else
2306 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2307 if (pTryAcquireSRWLockExclusive(lock))
2308 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2309 if (InterlockedIncrement(&srwlock_seq) != 23)
2310 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2312 /* seq 24 */
2313 while (srwlock_seq < 24) Sleep(1);
2314 Sleep(50); /* ensure that exclusive access request is queued */
2315 if (pTryAcquireSRWLockShared(lock))
2317 pReleaseSRWLockShared(lock);
2318 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2320 if (pTryAcquireSRWLockExclusive(lock))
2321 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2322 if (InterlockedIncrement(&srwlock_seq) != 25)
2323 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2324 pReleaseSRWLockShared(lock);
2326 /* seq 26 */
2327 while (srwlock_seq < 26) Sleep(1);
2328 if (pTryAcquireSRWLockShared(lock))
2329 pReleaseSRWLockShared(lock);
2330 else
2331 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2332 if (pTryAcquireSRWLockExclusive(lock))
2333 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2334 if (InterlockedIncrement(&srwlock_seq) != 27)
2335 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2337 /* seq 28 */
2338 while (srwlock_seq < 28) Sleep(1);
2339 if (pTryAcquireSRWLockShared(lock))
2340 pReleaseSRWLockShared(lock);
2341 else
2342 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2343 if (pTryAcquireSRWLockExclusive(lock))
2344 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2345 if (InterlockedIncrement(&srwlock_seq) != 29)
2346 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2348 /* seq 30 */
2349 while (srwlock_seq < 30) Sleep(1);
2350 if (pTryAcquireSRWLockShared(lock))
2351 pReleaseSRWLockShared(lock);
2352 else
2353 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2354 if (pTryAcquireSRWLockExclusive(lock))
2355 pReleaseSRWLockExclusive(lock);
2356 else
2357 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2358 if (InterlockedIncrement(&srwlock_seq) != 31)
2359 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2361 return 0;
2364 static DWORD WINAPI srwlock_base_thread3(void *arg)
2366 SRWLOCK *lock = arg;
2368 /* seq 15 */
2369 while (srwlock_seq < 15) Sleep(1);
2370 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2371 if (InterlockedIncrement(&srwlock_seq) != 16)
2372 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2374 /* seq 18 */
2375 pAcquireSRWLockShared(lock);
2376 if (srwlock_seq != 18)
2377 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2378 pReleaseSRWLockShared(lock);
2379 if (InterlockedIncrement(&srwlock_seq) != 19)
2380 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2382 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2383 if (!pTryAcquireSRWLockExclusive)
2385 /* function is only in Windows 7 and newer */
2386 win_skip("no srw trylock support.\n");
2387 srwlock_seq = 31; /* end */
2388 return 0;
2391 return 0;
2394 static void test_srwlock_base(SRWLOCK *lock)
2396 HANDLE h1, h2, h3;
2397 DWORD dummy;
2399 if (!pInitializeSRWLock)
2401 /* function is not yet in XP, only in newer Windows */
2402 win_skip("no srw lock support.\n");
2403 return;
2406 pInitializeSRWLock(lock);
2407 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors));
2408 srwlock_seq = 0;
2410 h1 = CreateThread(NULL, 0, srwlock_base_thread1, lock, 0, &dummy);
2411 h2 = CreateThread(NULL, 0, srwlock_base_thread2, lock, 0, &dummy);
2412 h3 = CreateThread(NULL, 0, srwlock_base_thread3, lock, 0, &dummy);
2414 srwlock_seq = 1; /* go */
2415 while (srwlock_seq < 31)
2416 Sleep(5);
2418 WaitForSingleObject(h1, 100);
2419 WaitForSingleObject(h2, 100);
2420 WaitForSingleObject(h3, 100);
2422 ok(!srwlock_base_errors.wrong_execution_order,
2423 "thread commands were executed in the wrong order (occurred %ld times).\n",
2424 srwlock_base_errors.wrong_execution_order);
2426 ok(!srwlock_base_errors.samethread_excl_excl,
2427 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %ld times).\n",
2428 srwlock_base_errors.samethread_excl_excl);
2430 ok(!srwlock_base_errors.samethread_excl_shared,
2431 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %ld times).\n",
2432 srwlock_base_errors.samethread_excl_shared);
2434 ok(!srwlock_base_errors.samethread_shared_excl,
2435 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %ld times).\n",
2436 srwlock_base_errors.samethread_shared_excl);
2438 ok(!srwlock_base_errors.multithread_excl_excl,
2439 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %ld times).\n",
2440 srwlock_base_errors.multithread_excl_excl);
2442 ok(!srwlock_base_errors.excl_not_preferred,
2443 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %ld times).\n",
2444 srwlock_base_errors.excl_not_preferred);
2446 ok(!srwlock_base_errors.trylock_excl,
2447 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %ld times).\n",
2448 srwlock_base_errors.trylock_excl);
2450 ok(!srwlock_base_errors.trylock_shared,
2451 "TryAcquireSRWLockShared didn't behave as expected (occurred %ld times).\n",
2452 srwlock_base_errors.trylock_shared);
2456 static SRWLOCK srwlock_example;
2457 static LONG srwlock_protected_value = 0;
2458 static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0;
2459 static BOOL srwlock_stop = FALSE;
2461 static DWORD WINAPI srwlock_example_thread(LPVOID x) {
2462 DWORD *cnt = x;
2463 LONG old;
2465 while (!srwlock_stop)
2468 /* periodically request exclusive access */
2469 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0)
2471 pAcquireSRWLockExclusive(&srwlock_example);
2472 if (InterlockedIncrement(&srwlock_inside) != 1)
2473 InterlockedIncrement(&srwlock_example_errors);
2475 InterlockedIncrement(&srwlock_protected_value);
2476 Sleep(1);
2478 if (InterlockedDecrement(&srwlock_inside) != 0)
2479 InterlockedIncrement(&srwlock_example_errors);
2480 pReleaseSRWLockExclusive(&srwlock_example);
2483 /* request shared access */
2484 pAcquireSRWLockShared(&srwlock_example);
2485 InterlockedIncrement(&srwlock_inside);
2486 old = srwlock_protected_value;
2488 (*cnt)++;
2489 Sleep(1);
2491 if (old != srwlock_protected_value)
2492 InterlockedIncrement(&srwlock_example_errors);
2493 InterlockedDecrement(&srwlock_inside);
2494 pReleaseSRWLockShared(&srwlock_example);
2497 return 0;
2500 static void test_srwlock_example(void)
2502 HANDLE h1, h2, h3;
2503 DWORD dummy;
2504 DWORD cnt1, cnt2, cnt3;
2506 if (!pInitializeSRWLock) {
2507 /* function is not yet in XP, only in newer Windows */
2508 win_skip("no srw lock support.\n");
2509 return;
2512 pInitializeSRWLock(&srwlock_example);
2514 cnt1 = cnt2 = cnt3 = 0;
2516 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy);
2517 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy);
2518 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy);
2520 /* limit run to 1 second. */
2521 Sleep(1000);
2523 /* tear down start */
2524 srwlock_stop = TRUE;
2526 WaitForSingleObject(h1, 1000);
2527 WaitForSingleObject(h2, 1000);
2528 WaitForSingleObject(h3, 1000);
2530 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %ld.\n", srwlock_inside);
2531 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %ld)\n",
2532 srwlock_example_errors);
2534 trace("number of shared accesses per thread are c1 %ld, c2 %ld, c3 %ld\n", cnt1, cnt2, cnt3);
2535 trace("number of total exclusive accesses is %ld\n", srwlock_protected_value);
2538 static void test_srwlock_quirk(void)
2540 union { SRWLOCK *s; LONG *l; } u = { &srwlock_example };
2542 if (!pInitializeSRWLock) {
2543 /* function is not yet in XP, only in newer Windows */
2544 win_skip("no srw lock support.\n");
2545 return;
2548 /* WeCom 4.x checks releasing a lock with value 0x1 results in it becoming 0x0. */
2549 *u.l = 1;
2550 pReleaseSRWLockExclusive(&srwlock_example);
2551 ok(*u.l == 0, "expected 0x0, got %lx\n", *u.l);
2554 static DWORD WINAPI alertable_wait_thread(void *param)
2556 HANDLE *semaphores = param;
2557 LARGE_INTEGER timeout;
2558 NTSTATUS status;
2559 DWORD result;
2561 ReleaseSemaphore(semaphores[0], 1, NULL);
2562 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE);
2563 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %lu\n", result);
2564 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE);
2565 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2567 ReleaseSemaphore(semaphores[0], 1, NULL);
2568 timeout.QuadPart = -10000000;
2569 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2570 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status);
2571 timeout.QuadPart = -2000000;
2572 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2573 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08lx\n", status);
2575 ReleaseSemaphore(semaphores[0], 1, NULL);
2576 timeout.QuadPart = -10000000;
2577 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2578 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status);
2579 result = WaitForSingleObject(semaphores[0], 0);
2580 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", result);
2582 return 0;
2585 static void CALLBACK alertable_wait_apc(ULONG_PTR userdata)
2587 HANDLE *semaphores = (void *)userdata;
2588 ReleaseSemaphore(semaphores[1], 1, NULL);
2591 static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata)
2593 HANDLE *semaphores = (void *)userdata;
2594 DWORD result;
2596 result = WaitForSingleObject(semaphores[0], 1000);
2597 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2600 static void test_alertable_wait(void)
2602 HANDLE thread, semaphores[2];
2603 DWORD result;
2605 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
2606 ok(semaphores[0] != NULL, "CreateSemaphore failed with %lu\n", GetLastError());
2607 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
2608 ok(semaphores[1] != NULL, "CreateSemaphore failed with %lu\n", GetLastError());
2609 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL);
2610 ok(thread != NULL, "CreateThread failed with %lu\n", GetLastError());
2612 result = WaitForSingleObject(semaphores[0], 1000);
2613 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2614 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2615 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2616 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2618 result = WaitForSingleObject(semaphores[0], 1000);
2619 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2620 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2621 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2622 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2624 result = WaitForSingleObject(semaphores[0], 1000);
2625 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2626 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2627 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2628 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2629 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2630 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2631 ReleaseSemaphore(semaphores[0], 2, NULL);
2633 result = WaitForSingleObject(thread, 1000);
2634 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2635 CloseHandle(thread);
2636 CloseHandle(semaphores[0]);
2637 CloseHandle(semaphores[1]);
2640 struct apc_deadlock_info
2642 PROCESS_INFORMATION *pi;
2643 HANDLE event;
2644 BOOL running;
2647 static DWORD WINAPI apc_deadlock_thread(void *param)
2649 struct apc_deadlock_info *info = param;
2650 PROCESS_INFORMATION *pi = info->pi;
2651 NTSTATUS status;
2652 SIZE_T size;
2653 void *base;
2655 while (info->running)
2657 base = NULL;
2658 size = 0x1000;
2659 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
2660 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
2661 ok(!status, "expected STATUS_SUCCESS, got %08lx\n", status);
2662 ok(base != NULL, "expected base != NULL, got %p\n", base);
2663 SetEvent(info->event);
2665 size = 0;
2666 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
2667 ok(!status, "expected STATUS_SUCCESS, got %08lx\n", status);
2668 SetEvent(info->event);
2671 return 0;
2674 static void test_apc_deadlock(void)
2676 struct apc_deadlock_info info;
2677 PROCESS_INFORMATION pi;
2678 STARTUPINFOA si = { sizeof(si) };
2679 char cmdline[MAX_PATH];
2680 HANDLE event, thread;
2681 DWORD result;
2682 BOOL success;
2683 char **argv;
2684 int i;
2686 winetest_get_mainargs(&argv);
2687 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
2688 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2689 ok(success, "CreateProcess failed with %lu\n", GetLastError());
2691 event = CreateEventA(NULL, FALSE, FALSE, NULL);
2692 ok(event != NULL, "CreateEvent failed with %lu\n", GetLastError());
2694 info.pi = &pi;
2695 info.event = event;
2696 info.running = TRUE;
2698 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
2699 ok(thread != NULL, "CreateThread failed with %lu\n", GetLastError());
2700 result = WaitForSingleObject(event, 1000);
2701 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2703 for (i = 0; i < 1000 && info.running; i++)
2705 result = SuspendThread(pi.hThread);
2706 ok(result == 0, "expected 0, got %lu\n", result);
2708 WaitForSingleObject(event, 0); /* reset event */
2709 result = WaitForSingleObject(event, 1000);
2710 if (result == WAIT_TIMEOUT)
2712 todo_wine
2713 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2714 info.running = FALSE;
2716 else
2717 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2719 result = ResumeThread(pi.hThread);
2720 ok(result == 1, "expected 1, got %lu\n", result);
2721 Sleep(1);
2724 info.running = FALSE;
2725 result = WaitForSingleObject(thread, 1000);
2726 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2727 CloseHandle(thread);
2728 CloseHandle(event);
2730 TerminateProcess(pi.hProcess, 0);
2731 CloseHandle(pi.hThread);
2732 CloseHandle(pi.hProcess);
2735 static void test_crit_section(void)
2737 CRITICAL_SECTION cs;
2738 BOOL ret;
2740 /* Win8+ does not initialize debug info, one has to use RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
2741 to override that. */
2742 memset(&cs, 0, sizeof(cs));
2743 InitializeCriticalSection(&cs);
2744 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2745 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2746 DeleteCriticalSection(&cs);
2747 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2749 if (!pInitializeCriticalSectionEx)
2751 win_skip("InitializeCriticalSectionEx isn't available, skipping tests.\n");
2752 return;
2755 memset(&cs, 0, sizeof(cs));
2756 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2757 ok(ret, "Failed to initialize critical section.\n");
2758 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2759 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2760 DeleteCriticalSection(&cs);
2761 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2763 memset(&cs, 0, sizeof(cs));
2764 ret = pInitializeCriticalSectionEx(&cs, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
2765 ok(ret, "Failed to initialize critical section.\n");
2766 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2767 DeleteCriticalSection(&cs);
2768 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2770 memset(&cs, 0, sizeof(cs));
2771 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2772 ok(ret, "Failed to initialize critical section.\n");
2773 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2774 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2775 DeleteCriticalSection(&cs);
2776 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2778 memset(&cs, 0, sizeof(cs));
2779 ret = pInitializeCriticalSectionEx(&cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
2780 ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* before Win8 */,
2781 "Failed to initialize critical section, error %lu.\n", GetLastError());
2782 if (!ret)
2784 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2785 ok(ret, "Failed to initialize critical section.\n");
2787 ok(cs.DebugInfo && cs.DebugInfo != (void *)(ULONG_PTR)-1, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2789 ret = TryEnterCriticalSection(&cs);
2790 ok(ret, "Failed to enter critical section.\n");
2791 LeaveCriticalSection(&cs);
2793 cs.DebugInfo = NULL;
2795 ret = TryEnterCriticalSection(&cs);
2796 ok(ret, "Failed to enter critical section.\n");
2797 LeaveCriticalSection(&cs);
2799 DeleteCriticalSection(&cs);
2800 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2803 static DWORD WINAPI thread_proc(LPVOID unused)
2805 Sleep(INFINITE);
2806 return 0;
2809 static int apc_count;
2811 static void CALLBACK user_apc(ULONG_PTR unused)
2813 apc_count++;
2816 static void CALLBACK call_user_apc(ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)
2818 PAPCFUNC func = (PAPCFUNC)arg1;
2819 func(arg2);
2822 static void test_QueueUserAPC(void)
2824 HANDLE thread;
2825 DWORD tid, ret;
2826 NTSTATUS status;
2828 thread = CreateThread(NULL, 0, thread_proc, NULL, CREATE_SUSPENDED, &tid);
2829 ok(thread != NULL, "CreateThread error %lu\n", GetLastError());
2831 ret = TerminateThread(thread, 0xdeadbeef);
2832 ok(ret, "TerminateThread error %lu\n", GetLastError());
2834 ret = WaitForSingleObject(thread, 1000);
2835 ok(ret == WAIT_OBJECT_0, "got %lu\n", ret);
2837 ret = pNtQueueApcThread(thread, call_user_apc, (ULONG_PTR)user_apc, 0, 0);
2838 ok(ret == STATUS_UNSUCCESSFUL, "got %#lx\n", ret);
2839 ret = pNtQueueApcThread(thread, NULL, 0, 0, 0);
2840 ok(ret == STATUS_UNSUCCESSFUL, "got %#lx\n", ret);
2842 SetLastError(0xdeadbeef);
2843 ret = QueueUserAPC(user_apc, thread, 0);
2844 ok(!ret, "QueueUserAPC should fail\n");
2845 ok(GetLastError() == ERROR_GEN_FAILURE, "got %lu\n", GetLastError());
2847 CloseHandle(thread);
2849 apc_count = 0;
2850 ret = QueueUserAPC(user_apc, GetCurrentThread(), 0);
2851 ok(ret, "QueueUserAPC failed err %lu\n", GetLastError());
2852 ok(!apc_count, "APC count %u\n", apc_count);
2853 ret = SleepEx( 100, TRUE );
2854 ok( ret == WAIT_IO_COMPLETION, "SleepEx returned %lu\n", ret);
2855 ok(apc_count == 1, "APC count %u\n", apc_count);
2857 ret = pNtQueueApcThread( GetCurrentThread(), NULL, 0, 0, 0 );
2858 ok( !ret, "got %#lx\n", ret);
2859 ret = SleepEx( 100, TRUE );
2860 ok( ret == WAIT_OBJECT_0, "SleepEx returned %lu\n", ret);
2862 apc_count = 0;
2863 ret = QueueUserAPC(user_apc, GetCurrentThread(), 0);
2864 ok(ret, "QueueUserAPC failed err %lu\n", GetLastError());
2865 ok(!apc_count, "APC count %u\n", apc_count);
2866 status = pNtTestAlert();
2867 ok(!status, "got %lx\n", status);
2868 ok(apc_count == 1, "APC count %u\n", apc_count);
2869 status = pNtTestAlert();
2870 ok(!status, "got %lx\n", status);
2871 ok(apc_count == 1, "APC count %u\n", apc_count);
2874 START_TEST(sync)
2876 char **argv;
2877 int argc;
2878 HMODULE hdll = GetModuleHandleA("kernel32.dll");
2879 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
2881 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
2882 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
2883 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
2884 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
2885 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
2886 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
2887 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW");
2888 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
2889 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
2890 pInitializeCriticalSectionEx = (void *)GetProcAddress(hdll, "InitializeCriticalSectionEx");
2891 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock");
2892 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive");
2893 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared");
2894 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive");
2895 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
2896 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
2897 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
2898 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
2899 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
2900 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
2901 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
2902 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList");
2903 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx");
2904 pNtQueueApcThread = (void *)GetProcAddress(hntdll, "NtQueueApcThread");
2905 pNtTestAlert = (void *)GetProcAddress(hntdll, "NtTestAlert");
2907 argc = winetest_get_mainargs( &argv );
2908 if (argc >= 3)
2910 if (!strcmp(argv[2], "apc_deadlock"))
2912 for (;;) SleepEx(INFINITE, TRUE);
2914 return;
2917 init_fastcall_thunk();
2919 test_QueueUserAPC();
2920 test_signalandwait();
2921 test_temporary_objects();
2922 test_mutex();
2923 test_slist();
2924 test_event();
2925 test_semaphore();
2926 test_waitable_timer();
2927 test_iocp_callback();
2928 test_timer_queue();
2929 test_WaitForSingleObject();
2930 test_WaitForMultipleObjects();
2931 test_initonce();
2932 test_condvars_base(&aligned_cv);
2933 test_condvars_base(&unaligned_cv.cv);
2934 test_condvars_consumer_producer();
2935 test_srwlock_base(&aligned_srwlock);
2936 test_srwlock_quirk();
2937 #if defined(__i386__) || defined(__x86_64__)
2938 /* unaligned locks only work on x86 platforms */
2939 test_srwlock_base(&unaligned_srwlock.lock);
2940 #endif
2941 test_srwlock_example();
2942 test_alertable_wait();
2943 test_apc_deadlock();
2944 test_crit_section();