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