kernel32/tests: Remove some win9x workarounds.
[wine.git] / dlls / kernel32 / tests / sync.c
blob83ab5344037708058caa5e70cccd09da2c6f7682
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 HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
35 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
36 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
37 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
38 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
39 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
41 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
42 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
43 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG);
44 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
45 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
47 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK);
48 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK);
49 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK);
50 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
51 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
52 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
53 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
55 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG);
56 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
57 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *);
58 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
59 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first,
60 PSLIST_ENTRY last, ULONG count);
61 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first,
62 PSLIST_ENTRY last, ULONG count);
64 #ifdef __i386__
66 #include "pshpack1.h"
67 struct fastcall_thunk
69 BYTE pop_edx; /* popl %edx (ret addr) */
70 BYTE pop_eax; /* popl %eax (func) */
71 BYTE pop_ecx; /* popl %ecx (param 1) */
72 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */
73 WORD jmp_eax; /* jmp *%eax */
75 #include "poppack.h"
77 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d);
79 static void init_fastcall_thunk(void)
81 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
82 thunk->pop_edx = 0x5a; /* popl %edx */
83 thunk->pop_eax = 0x58; /* popl %eax */
84 thunk->pop_ecx = 0x59; /* popl %ecx */
85 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */
86 thunk->xchg[1] = 0x14;
87 thunk->xchg[2] = 0x24;
88 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */
89 call_fastcall_func4 = (void *)thunk;
92 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
93 (const void *)(b), (const void *)(c), (const void *)(d))
95 #else /* __i386__ */
97 #define init_fastcall_thunk() do { } while(0)
98 #define call_func4(func, a, b, c, d) func(a, b, c, d)
100 #endif /* __i386__ */
102 static void test_signalandwait(void)
104 DWORD r;
105 HANDLE event[2], semaphore[2], file;
106 int i;
108 /* invalid parameters */
109 r = SignalObjectAndWait(NULL, NULL, 0, 0);
110 ok( r == WAIT_FAILED, "should fail\n");
112 event[0] = CreateEventW(NULL, 0, 0, NULL);
113 event[1] = CreateEventW(NULL, 1, 1, NULL);
115 ok( event[0] && event[1], "failed to create event flags\n");
117 r = SignalObjectAndWait(event[0], NULL, 0, FALSE);
118 ok( r == WAIT_FAILED, "should fail\n");
120 r = SignalObjectAndWait(NULL, event[0], 0, FALSE);
121 ok( r == WAIT_FAILED, "should fail\n");
124 /* valid parameters */
125 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
126 ok( r == WAIT_OBJECT_0, "should succeed\n");
128 /* event[0] is now signalled - we repeat this test multiple times
129 * to ensure that the wineserver handles this situation properly. */
130 for (i = 0; i < 10000; i++)
132 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
133 ok(r == WAIT_OBJECT_0, "should succeed\n");
136 /* event[0] is not signalled */
137 r = WaitForSingleObject(event[0], 0);
138 ok( r == WAIT_TIMEOUT, "event was signalled\n");
140 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
141 ok( r == WAIT_OBJECT_0, "should succeed\n");
143 /* clear event[1] and check for a timeout */
144 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
145 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
146 ok( r == WAIT_TIMEOUT, "should timeout\n");
148 CloseHandle(event[0]);
149 CloseHandle(event[1]);
151 /* semaphores */
152 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL );
153 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL );
154 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
156 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
157 ok( r == WAIT_OBJECT_0, "should succeed\n");
159 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
160 ok( r == WAIT_FAILED, "should fail\n");
162 r = ReleaseSemaphore(semaphore[0],1,NULL);
163 ok( r == FALSE, "should fail\n");
165 r = ReleaseSemaphore(semaphore[1],1,NULL);
166 ok( r == TRUE, "should succeed\n");
168 CloseHandle(semaphore[0]);
169 CloseHandle(semaphore[1]);
171 /* try a registry key */
172 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
173 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
174 r = SignalObjectAndWait(file, file, 0, FALSE);
175 ok( r == WAIT_FAILED, "should fail\n");
176 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
177 CloseHandle(file);
180 static void test_mutex(void)
182 DWORD wait_ret;
183 BOOL ret;
184 HANDLE hCreated;
185 HANDLE hOpened;
186 int i;
187 DWORD failed = 0;
189 SetLastError(0xdeadbeef);
190 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
191 ok(hOpened == NULL, "OpenMutex succeeded\n");
192 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
194 SetLastError(0xdeadbeef);
195 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex");
196 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
198 SetLastError(0xdeadbeef);
199 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
200 todo_wine
201 ok(hOpened == NULL, "OpenMutex succeeded\n");
202 todo_wine
203 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
205 SetLastError(0xdeadbeef);
206 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex");
207 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
208 wait_ret = WaitForSingleObject(hOpened, INFINITE);
209 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
210 CloseHandle(hOpened);
212 for(i=0; i < 31; i++)
214 wait_ret = WaitForSingleObject(hCreated, INFINITE);
215 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
218 SetLastError(0xdeadbeef);
219 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
220 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
221 wait_ret = WaitForSingleObject(hOpened, INFINITE);
222 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
223 CloseHandle(hOpened);
225 for (i = 0; i < 32; i++)
227 SetLastError(0xdeadbeef);
228 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex");
229 if(hOpened != NULL)
231 SetLastError(0xdeadbeef);
232 ret = ReleaseMutex(hOpened);
233 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
234 CloseHandle(hOpened);
236 else
238 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
239 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
240 else
241 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
242 ReleaseMutex(hCreated);
243 failed |=0x1 << i;
247 todo_wine
248 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
250 SetLastError(0xdeadbeef);
251 ret = ReleaseMutex(hCreated);
252 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
253 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
255 /* test case sensitivity */
257 SetLastError(0xdeadbeef);
258 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX");
259 ok(!hOpened, "OpenMutex succeeded\n");
260 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
262 SetLastError(0xdeadbeef);
263 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex");
264 ok(!hOpened, "OpenMutex succeeded\n");
265 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
267 SetLastError(0xdeadbeef);
268 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex");
269 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
270 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
271 CloseHandle(hOpened);
273 SetLastError(0xdeadbeef);
274 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX");
275 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
276 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
277 CloseHandle(hOpened);
279 CloseHandle(hCreated);
282 static void test_slist(void)
284 struct item
286 SLIST_ENTRY entry;
287 int value;
288 } item1, item2, item3, *item;
289 SLIST_HEADER slist_header;
290 SLIST_ENTRY *entry;
291 USHORT size;
292 int i;
294 item1.value = 1;
295 item2.value = 2;
296 item3.value = 3;
298 memset(&slist_header, 0xff, sizeof(slist_header));
299 InitializeSListHead(&slist_header);
300 size = QueryDepthSList(&slist_header);
301 ok(size == 0, "Expected size == 0, got %u\n", size);
303 /* test PushEntry, PopEntry and Flush */
304 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
305 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
306 size = QueryDepthSList(&slist_header);
307 ok(size == 1, "Expected size == 1, got %u\n", size);
309 entry = InterlockedPushEntrySList(&slist_header, &item2.entry);
310 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
311 item = CONTAINING_RECORD(entry, struct item, entry);
312 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
313 size = QueryDepthSList(&slist_header);
314 ok(size == 2, "Expected size == 2, got %u\n", size);
316 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
317 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
318 item = CONTAINING_RECORD(entry, struct item, entry);
319 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
320 size = QueryDepthSList(&slist_header);
321 ok(size == 3, "Expected size == 3, got %u\n", size);
323 entry = InterlockedPopEntrySList(&slist_header);
324 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
325 item = CONTAINING_RECORD(entry, struct item, entry);
326 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
327 size = QueryDepthSList(&slist_header);
328 ok(size == 2, "Expected size == 2, got %u\n", size);
330 entry = InterlockedFlushSList(&slist_header);
331 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
332 item = CONTAINING_RECORD(entry, struct item, entry);
333 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
334 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
335 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
336 size = QueryDepthSList(&slist_header);
337 ok(size == 0, "Expected size == 0, got %u\n", size);
338 entry = InterlockedPopEntrySList(&slist_header);
339 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
341 /* test RtlInterlockedPushListSList */
342 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
343 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
344 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42);
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 == 43, "Expected size == 43, got %u\n", size);
351 entry = InterlockedPopEntrySList(&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 size = QueryDepthSList(&slist_header);
356 ok(size == 42, "Expected size == 42, got %u\n", size);
358 entry = InterlockedPopEntrySList(&slist_header);
359 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
360 item = CONTAINING_RECORD(entry, struct item, entry);
361 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
362 size = QueryDepthSList(&slist_header);
363 ok(size == 41, "Expected size == 41, got %u\n", size);
365 entry = InterlockedPopEntrySList(&slist_header);
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 == 40, "Expected size == 40, got %u\n", size);
372 entry = InterlockedPopEntrySList(&slist_header);
373 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
374 size = QueryDepthSList(&slist_header);
375 ok(size == 40, "Expected size == 40, got %u\n", size);
377 entry = InterlockedFlushSList(&slist_header);
378 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
379 size = QueryDepthSList(&slist_header);
380 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size);
382 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
383 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
384 entry = InterlockedFlushSList(&slist_header);
385 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
386 item = CONTAINING_RECORD(entry, struct item, entry);
387 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
388 size = QueryDepthSList(&slist_header);
389 ok(size == 0, "Expected size == 0, got %u\n", size);
391 /* test RtlInterlockedPushListSListEx */
392 if (pRtlInterlockedPushListSListEx)
394 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
395 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
396 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42);
397 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
398 item = CONTAINING_RECORD(entry, struct item, entry);
399 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
400 size = QueryDepthSList(&slist_header);
401 ok(size == 43, "Expected size == 43, got %u\n", size);
403 entry = InterlockedFlushSList(&slist_header);
404 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
405 item = CONTAINING_RECORD(entry, struct item, entry);
406 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
407 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
408 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
409 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
410 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
411 size = QueryDepthSList(&slist_header);
412 ok(size == 0, "Expected size == 0, got %u\n", size);
414 else
415 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
417 /* test with a lot of items */
418 for (i = 0; i < 65536; i++)
420 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
421 item->value = i + 1;
422 entry = InterlockedPushEntrySList(&slist_header, &item->entry);
423 if (i)
425 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
426 item = CONTAINING_RECORD(entry, struct item, entry);
427 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
429 else
431 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
433 size = QueryDepthSList(&slist_header);
434 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size);
437 entry = InterlockedFlushSList(&slist_header);
438 for (i = 65536; i > 0; i--)
440 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
441 item = CONTAINING_RECORD(entry, struct item, entry);
442 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
443 entry = item->entry.Next;
444 HeapFree(GetProcessHeap(), 0, item);
446 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
447 size = QueryDepthSList(&slist_header);
448 ok(size == 0, "Expected size == 0, got %u\n", size);
449 entry = InterlockedPopEntrySList(&slist_header);
450 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
453 static void test_event(void)
455 HANDLE handle, handle2;
456 SECURITY_ATTRIBUTES sa;
457 SECURITY_DESCRIPTOR sd;
458 ACL acl;
459 DWORD ret;
460 BOOL val;
462 /* no sd */
463 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
464 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
465 CloseHandle(handle);
467 sa.nLength = sizeof(sa);
468 sa.lpSecurityDescriptor = &sd;
469 sa.bInheritHandle = FALSE;
471 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
473 /* blank sd */
474 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
475 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
476 CloseHandle(handle);
478 /* sd with NULL dacl */
479 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
480 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
481 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
482 CloseHandle(handle);
484 /* sd with empty dacl */
485 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
486 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
487 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
488 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
489 CloseHandle(handle);
491 /* test case sensitivity */
493 SetLastError(0xdeadbeef);
494 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
495 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
496 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
498 SetLastError(0xdeadbeef);
499 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
500 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
501 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
502 CloseHandle( handle2 );
504 SetLastError(0xdeadbeef);
505 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
506 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
507 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
508 CloseHandle( handle2 );
510 SetLastError(0xdeadbeef);
511 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
512 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
513 CloseHandle( handle2 );
515 SetLastError(0xdeadbeef);
516 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
517 ok( !handle2, "OpenEvent succeeded\n");
518 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
520 CloseHandle( handle );
522 /* resource notifications are events too */
524 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
526 trace( "memory resource notifications not supported\n" );
527 return;
529 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
530 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
531 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
532 ret = pQueryMemoryResourceNotification( handle, &val );
533 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
534 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
536 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
537 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
538 ret = WaitForSingleObject( handle, 10 );
539 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
541 val = ~0;
542 ret = pQueryMemoryResourceNotification( handle, &val );
543 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
544 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
545 ret = CloseHandle( handle );
546 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
548 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
549 val = ~0;
550 ret = pQueryMemoryResourceNotification( handle, &val );
551 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
552 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
553 CloseHandle( handle );
556 static void test_semaphore(void)
558 HANDLE handle, handle2;
560 /* test case sensitivity */
562 SetLastError(0xdeadbeef);
563 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
564 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
565 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
567 SetLastError(0xdeadbeef);
568 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
569 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
570 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
571 CloseHandle( handle2 );
573 SetLastError(0xdeadbeef);
574 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
575 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
576 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
577 CloseHandle( handle2 );
579 SetLastError(0xdeadbeef);
580 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
581 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
582 CloseHandle( handle2 );
584 SetLastError(0xdeadbeef);
585 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
586 ok( !handle2, "OpenSemaphore succeeded\n");
587 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
589 CloseHandle( handle );
592 static void test_waitable_timer(void)
594 HANDLE handle, handle2;
596 /* test case sensitivity */
598 SetLastError(0xdeadbeef);
599 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
600 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
601 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
603 SetLastError(0xdeadbeef);
604 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
605 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
606 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
607 CloseHandle( handle2 );
609 SetLastError(0xdeadbeef);
610 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
611 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
612 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
613 CloseHandle( handle2 );
615 SetLastError(0xdeadbeef);
616 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
617 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
618 CloseHandle( handle2 );
620 SetLastError(0xdeadbeef);
621 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
622 ok( !handle2, "OpenWaitableTimer succeeded\n");
623 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
625 CloseHandle( handle );
628 static HANDLE sem = 0;
630 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
632 ReleaseSemaphore(sem, 1, NULL);
635 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
637 static void test_iocp_callback(void)
639 char temp_path[MAX_PATH];
640 char filename[MAX_PATH];
641 DWORD ret;
642 BOOL retb;
643 static const char prefix[] = "pfx";
644 HANDLE hFile;
645 HMODULE hmod = GetModuleHandleA("kernel32.dll");
646 DWORD bytesWritten;
647 const char *buffer = "12345678123456781234567812345678";
648 OVERLAPPED overlapped;
650 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
651 if(!p_BindIoCompletionCallback) {
652 win_skip("BindIoCompletionCallback not found in this DLL\n");
653 return;
656 sem = CreateSemaphoreW(NULL, 0, 1, NULL);
657 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
659 ret = GetTempPathA(MAX_PATH, temp_path);
660 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
661 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
663 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
664 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
666 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
667 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
668 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
670 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
671 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
672 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
674 ret = CloseHandle(hFile);
675 ok( ret, "CloseHandle: error %d\n", GetLastError());
676 ret = DeleteFileA(filename);
677 ok( ret, "DeleteFileA: error %d\n", GetLastError());
679 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
680 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
681 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
683 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
684 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
686 memset(&overlapped, 0, sizeof(overlapped));
687 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
688 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
690 ret = WaitForSingleObject(sem, 5000);
691 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
692 CloseHandle(sem);
694 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
695 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
696 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
697 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
698 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
699 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
701 ret = CloseHandle(hFile);
702 ok( ret, "CloseHandle: error %d\n", GetLastError());
703 ret = DeleteFileA(filename);
704 ok( ret, "DeleteFileA: error %d\n", GetLastError());
706 /* win2k3 requires the Flags parameter to be zero */
707 SetLastError(0xdeadbeef);
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());
711 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
712 if (!retb)
713 ok(GetLastError() == ERROR_INVALID_PARAMETER,
714 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
715 else
716 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
717 ret = CloseHandle(hFile);
718 ok( ret, "CloseHandle: error %d\n", GetLastError());
719 ret = DeleteFileA(filename);
720 ok( ret, "DeleteFileA: error %d\n", GetLastError());
722 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
723 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
724 ok(GetLastError() == ERROR_INVALID_HANDLE ||
725 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
726 "Last error is %d\n", GetLastError());
729 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
731 int *pn = p;
732 ok(timedOut, "Timer callbacks should always time out\n");
733 ++*pn;
736 struct timer_queue_data1
738 int num_calls;
739 int max_calls;
740 HANDLE q, t;
743 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
745 struct timer_queue_data1 *d = p;
746 ok(timedOut, "Timer callbacks should always time out\n");
747 if (d->t && ++d->num_calls == d->max_calls)
749 BOOL ret;
750 SetLastError(0xdeadbeef);
751 /* Note, XP SP2 does *not* do any deadlock checking, so passing
752 INVALID_HANDLE_VALUE here will just hang. */
753 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
754 ok(!ret, "DeleteTimerQueueTimer\n");
755 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
759 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
761 struct timer_queue_data1 *d = p;
762 ok(timedOut, "Timer callbacks should always time out\n");
763 if (d->t && ++d->num_calls == d->max_calls)
765 /* Basically kill the timer since it won't have time to run
766 again. */
767 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0);
768 ok(ret, "ChangeTimerQueueTimer\n");
772 static void CALLBACK timer_queue_cb4(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)
778 /* This tests whether a timer gets flagged for deletion before
779 or after the callback runs. If we start this timer with a
780 period of zero (run once), then ChangeTimerQueueTimer will
781 fail if the timer is already flagged. Hence we really run
782 only once. Otherwise we will run multiple times. */
783 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50);
784 ok(ret, "ChangeTimerQueueTimer\n");
785 ++d->num_calls;
789 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
791 DWORD_PTR delay = (DWORD_PTR) p;
792 ok(timedOut, "Timer callbacks should always time out\n");
793 if (delay)
794 Sleep(delay);
797 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
799 struct timer_queue_data1 *d = p;
800 ok(timedOut, "Timer callbacks should always time out\n");
801 /* This tests an original implementation bug where a deleted timer may get
802 to run, but it is tricky to set up. */
803 if (d->q && d->num_calls++ == 0)
805 /* First run: delete ourselves, then insert and remove a timer
806 that goes in front of us in the sorted timeout list. Once
807 removed, we will still timeout at the faster timer's due time,
808 but this should be a no-op if we are bug-free. There should
809 not be a second run. We can test the value of num_calls later. */
810 BOOL ret;
811 HANDLE t;
813 /* The delete will pend while we are in this callback. */
814 SetLastError(0xdeadbeef);
815 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
816 ok(!ret, "DeleteTimerQueueTimer\n");
817 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
819 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
820 ok(ret, "CreateTimerQueueTimer\n");
821 ok(t != NULL, "CreateTimerQueueTimer\n");
823 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
824 ok(ret, "DeleteTimerQueueTimer\n");
826 /* Now we stay alive by hanging around in the callback. */
827 Sleep(500);
831 static void test_timer_queue(void)
833 HANDLE q, t0, t1, t2, t3, t4, t5;
834 int n0, n1, n2, n3, n4, n5;
835 struct timer_queue_data1 d1, d2, d3, d4;
836 HANDLE e, et1, et2;
837 BOOL ret, ret0;
839 /* Test asynchronous deletion of the queue. */
840 q = CreateTimerQueue();
841 ok(q != NULL, "CreateTimerQueue\n");
843 SetLastError(0xdeadbeef);
844 ret = DeleteTimerQueueEx(q, NULL);
845 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
846 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
847 GetLastError());
849 /* Test synchronous deletion of the queue and running timers. */
850 q = CreateTimerQueue();
851 ok(q != NULL, "CreateTimerQueue\n");
853 /* Not called. */
854 t0 = NULL;
855 n0 = 0;
856 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0);
857 ok(ret, "CreateTimerQueueTimer\n");
858 ok(t0 != NULL, "CreateTimerQueueTimer\n");
859 ret0 = DeleteTimerQueueTimer(q, t0, NULL);
860 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
861 broken(ret0), /* Win 2000 & XP & 2003 */
862 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
864 /* Called once. */
865 t1 = NULL;
866 n1 = 0;
867 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0);
868 ok(ret, "CreateTimerQueueTimer\n");
869 ok(t1 != NULL, "CreateTimerQueueTimer\n");
871 /* A slow one. */
872 t2 = NULL;
873 n2 = 0;
874 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0);
875 ok(ret, "CreateTimerQueueTimer\n");
876 ok(t2 != NULL, "CreateTimerQueueTimer\n");
878 /* A fast one. */
879 t3 = NULL;
880 n3 = 0;
881 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0);
882 ok(ret, "CreateTimerQueueTimer\n");
883 ok(t3 != NULL, "CreateTimerQueueTimer\n");
885 /* Start really late (it won't start). */
886 t4 = NULL;
887 n4 = 0;
888 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0);
889 ok(ret, "CreateTimerQueueTimer\n");
890 ok(t4 != NULL, "CreateTimerQueueTimer\n");
892 /* Start soon, but delay so long it won't run again. */
893 t5 = NULL;
894 n5 = 0;
895 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0);
896 ok(ret, "CreateTimerQueueTimer\n");
897 ok(t5 != NULL, "CreateTimerQueueTimer\n");
899 /* Give them a chance to do some work. */
900 Sleep(500);
902 /* Test deleting a once-only timer. */
903 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
904 ok(ret, "DeleteTimerQueueTimer\n");
906 /* A periodic timer. */
907 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
908 ok(ret, "DeleteTimerQueueTimer\n");
910 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
911 ok(ret, "DeleteTimerQueueEx\n");
912 todo_wine
913 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
914 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
915 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
916 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
917 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
919 /* Test synchronous deletion of the timer/queue with event trigger. */
920 e = CreateEventW(NULL, TRUE, FALSE, NULL);
921 et1 = CreateEventW(NULL, TRUE, FALSE, NULL);
922 et2 = CreateEventW(NULL, TRUE, FALSE, NULL);
923 if (!e || !et1 || !et2)
925 skip("Failed to create timer queue descruction event\n");
926 return;
929 q = CreateTimerQueue();
930 ok(q != NULL, "CreateTimerQueue\n");
932 /* Run once and finish quickly (should be done when we delete it). */
933 t1 = NULL;
934 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
935 ok(ret, "CreateTimerQueueTimer\n");
936 ok(t1 != NULL, "CreateTimerQueueTimer\n");
938 /* Run once and finish slowly (shouldn't be done when we delete it). */
939 t2 = NULL;
940 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
941 ok(ret, "CreateTimerQueueTimer\n");
942 ok(t2 != NULL, "CreateTimerQueueTimer\n");
944 /* Run once and finish quickly (should be done when we delete it). */
945 t3 = NULL;
946 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
947 ok(ret, "CreateTimerQueueTimer\n");
948 ok(t3 != NULL, "CreateTimerQueueTimer\n");
950 /* Run once and finish slowly (shouldn't be done when we delete it). */
951 t4 = NULL;
952 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
953 ok(ret, "CreateTimerQueueTimer\n");
954 ok(t4 != NULL, "CreateTimerQueueTimer\n");
956 /* Give them a chance to start. */
957 Sleep(400);
959 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
960 even if the timer is finished. */
961 SetLastError(0xdeadbeef);
962 ret = DeleteTimerQueueTimer(q, t1, NULL);
963 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
964 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
965 GetLastError());
967 SetLastError(0xdeadbeef);
968 ret = DeleteTimerQueueTimer(q, t2, NULL);
969 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
970 ok(GetLastError() == ERROR_IO_PENDING,
971 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
972 GetLastError());
974 SetLastError(0xdeadbeef);
975 ret = DeleteTimerQueueTimer(q, t3, et1);
976 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
977 ok(GetLastError() == 0xdeadbeef,
978 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
979 GetLastError());
980 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
981 "Timer destruction event not triggered\n");
983 SetLastError(0xdeadbeef);
984 ret = DeleteTimerQueueTimer(q, t4, et2);
985 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
986 ok(GetLastError() == ERROR_IO_PENDING,
987 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
988 GetLastError());
989 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
990 "Timer destruction event not triggered\n");
992 SetLastError(0xdeadbeef);
993 ret = DeleteTimerQueueEx(q, e);
994 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
995 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
996 GetLastError());
997 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
998 "Queue destruction event not triggered\n");
999 CloseHandle(e);
1001 /* Test deleting/changing a timer in execution. */
1002 q = CreateTimerQueue();
1003 ok(q != NULL, "CreateTimerQueue\n");
1005 /* Test changing a once-only timer before it fires (this is allowed,
1006 whereas after it fires you cannot). */
1007 n1 = 0;
1008 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0);
1009 ok(ret, "CreateTimerQueueTimer\n");
1010 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1011 ret = ChangeTimerQueueTimer(q, t1, 0, 0);
1012 ok(ret, "ChangeTimerQueueTimer\n");
1014 d2.t = t2 = NULL;
1015 d2.num_calls = 0;
1016 d2.max_calls = 3;
1017 d2.q = q;
1018 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0);
1019 d2.t = t2;
1020 ok(ret, "CreateTimerQueueTimer\n");
1021 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1023 d3.t = t3 = NULL;
1024 d3.num_calls = 0;
1025 d3.max_calls = 4;
1026 d3.q = q;
1027 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0);
1028 d3.t = t3;
1029 ok(ret, "CreateTimerQueueTimer\n");
1030 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1032 d4.t = t4 = NULL;
1033 d4.num_calls = 0;
1034 d4.q = q;
1035 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0);
1036 d4.t = t4;
1037 ok(ret, "CreateTimerQueueTimer\n");
1038 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1040 Sleep(500);
1042 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1043 ok(ret, "DeleteTimerQueueEx\n");
1044 ok(n1 == 1, "ChangeTimerQueueTimer\n");
1045 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
1046 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
1047 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
1049 /* Test an obscure bug that was in the original implementation. */
1050 q = CreateTimerQueue();
1051 ok(q != NULL, "CreateTimerQueue\n");
1053 /* All the work is done in the callback. */
1054 d1.t = t1 = NULL;
1055 d1.num_calls = 0;
1056 d1.q = q;
1057 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION);
1058 d1.t = t1;
1059 ok(ret, "CreateTimerQueueTimer\n");
1060 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1062 Sleep(750);
1064 SetLastError(0xdeadbeef);
1065 ret = DeleteTimerQueueEx(q, NULL);
1066 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1067 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1068 GetLastError());
1069 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
1071 /* Test functions on the default timer queue. */
1072 t1 = NULL;
1073 n1 = 0;
1074 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0);
1075 ok(ret, "CreateTimerQueueTimer, default queue\n");
1076 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
1078 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1079 ok(ret, "ChangeTimerQueueTimer, default queue\n");
1081 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1082 ok(ret, "DeleteTimerQueueTimer, default queue\n");
1084 /* Try mixing default and non-default queues. Apparently this works. */
1085 q = CreateTimerQueue();
1086 ok(q != NULL, "CreateTimerQueue\n");
1088 t1 = NULL;
1089 n1 = 0;
1090 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0);
1091 ok(ret, "CreateTimerQueueTimer\n");
1092 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1094 t2 = NULL;
1095 n2 = 0;
1096 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0);
1097 ok(ret, "CreateTimerQueueTimer\n");
1098 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1100 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1101 ok(ret, "ChangeTimerQueueTimer\n");
1103 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000);
1104 ok(ret, "ChangeTimerQueueTimer\n");
1106 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1107 ok(ret, "DeleteTimerQueueTimer\n");
1109 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1110 ok(ret, "DeleteTimerQueueTimer\n");
1112 /* Try to delete the default queue? In any case: not allowed. */
1113 SetLastError(0xdeadbeef);
1114 ret = DeleteTimerQueueEx(NULL, NULL);
1115 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1116 ok(GetLastError() == ERROR_INVALID_HANDLE,
1117 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1118 GetLastError());
1120 SetLastError(0xdeadbeef);
1121 ret = DeleteTimerQueueEx(q, NULL);
1122 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1123 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1124 GetLastError());
1127 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1129 DWORD tmp = HandleToULong(handle);
1130 tmp |= modify;
1131 return ULongToHandle(tmp);
1134 static void test_WaitForSingleObject(void)
1136 HANDLE signaled, nonsignaled, invalid;
1137 LARGE_INTEGER timeout;
1138 NTSTATUS status;
1139 DWORD ret;
1141 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1142 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1143 invalid = (HANDLE) 0xdeadbee0;
1145 /* invalid handle with different values for lower 2 bits */
1146 SetLastError(0xdeadbeef);
1147 ret = WaitForSingleObject(invalid, 0);
1148 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1149 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1151 SetLastError(0xdeadbeef);
1152 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1153 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1154 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1156 SetLastError(0xdeadbeef);
1157 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1158 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1159 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1161 SetLastError(0xdeadbeef);
1162 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1163 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1164 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1166 /* valid handle with different values for lower 2 bits */
1167 SetLastError(0xdeadbeef);
1168 ret = WaitForSingleObject(nonsignaled, 0);
1169 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1170 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1172 SetLastError(0xdeadbeef);
1173 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1174 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1175 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1177 SetLastError(0xdeadbeef);
1178 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1179 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1180 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1182 SetLastError(0xdeadbeef);
1183 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1184 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1185 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1187 /* valid handle with different values for lower 2 bits */
1188 SetLastError(0xdeadbeef);
1189 ret = WaitForSingleObject(signaled, 0);
1190 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1191 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1193 SetLastError(0xdeadbeef);
1194 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1195 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1196 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1198 SetLastError(0xdeadbeef);
1199 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1200 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1201 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1203 SetLastError(0xdeadbeef);
1204 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1205 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1206 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1208 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1209 ret = WaitForSingleObject(GetCurrentProcess(), 100);
1210 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret);
1212 ret = WaitForSingleObject(GetCurrentThread(), 100);
1213 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret);
1215 timeout.QuadPart = -1000000;
1216 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout);
1217 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status);
1219 timeout.QuadPart = -1000000;
1220 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout);
1221 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status);
1223 CloseHandle(signaled);
1224 CloseHandle(nonsignaled);
1227 static void test_WaitForMultipleObjects(void)
1229 LARGE_INTEGER timeout;
1230 NTSTATUS status;
1231 DWORD r;
1232 int i;
1233 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1235 /* create the maximum number of events and make sure
1236 * we can wait on that many */
1237 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1239 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL);
1240 ok( maxevents[i] != 0, "should create enough events\n");
1243 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1244 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1245 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1246 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1247 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1248 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1249 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1251 /* the lowest index is checked first and remaining events are untouched */
1252 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1253 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1256 /* run same test with Nt* call */
1257 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1258 SetEvent(maxevents[i]);
1260 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1261 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1262 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08x\n", status);
1263 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1264 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08x\n", status);
1265 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1266 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1268 /* the lowest index is checked first and remaining events are untouched */
1269 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1270 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08x\n", i, status);
1273 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1274 if (maxevents[i]) CloseHandle(maxevents[i]);
1276 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1277 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1278 maxevents[0] = GetCurrentProcess();
1279 SetLastError(0xdeadbeef);
1280 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1281 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r);
1282 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1283 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1285 maxevents[0] = GetCurrentThread();
1286 SetLastError(0xdeadbeef);
1287 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1288 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r);
1289 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1290 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1292 timeout.QuadPart = -1000000;
1293 maxevents[0] = GetCurrentProcess();
1294 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1295 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status);
1297 timeout.QuadPart = -1000000;
1298 maxevents[0] = GetCurrentThread();
1299 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1300 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status);
1303 static BOOL g_initcallback_ret, g_initcallback_called;
1304 static void *g_initctxt;
1306 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1308 g_initcallback_called = TRUE;
1309 /* zero bit set means here that initialization is taking place - initialization locked */
1310 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1311 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1312 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1313 return g_initcallback_ret;
1316 static void test_initonce(void)
1318 INIT_ONCE initonce;
1319 BOOL ret, pending;
1321 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1323 win_skip("one-time initialization API not supported\n");
1324 return;
1327 /* blocking initialization with callback */
1328 initonce.Ptr = (void*)0xdeadbeef;
1329 pInitOnceInitialize(&initonce);
1330 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1332 /* initialisation completed successfully */
1333 g_initcallback_ret = TRUE;
1334 g_initctxt = NULL;
1335 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1336 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1337 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1338 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1339 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1341 /* so it's been called already so won't be called again */
1342 g_initctxt = NULL;
1343 g_initcallback_called = FALSE;
1344 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1345 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1346 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1347 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1348 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1350 pInitOnceInitialize(&initonce);
1351 g_initcallback_called = FALSE;
1352 /* 2 lower order bits should never be used, you'll get a crash in result */
1353 g_initctxt = (void*)0xFFFFFFF0;
1354 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1355 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1356 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1357 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1358 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1360 /* callback failed */
1361 g_initcallback_ret = FALSE;
1362 g_initcallback_called = FALSE;
1363 g_initctxt = NULL;
1364 pInitOnceInitialize(&initonce);
1365 SetLastError( 0xdeadbeef );
1366 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1367 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret, GetLastError());
1368 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1369 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1370 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1372 /* blocking initialization without a callback */
1373 pInitOnceInitialize(&initonce);
1374 g_initctxt = NULL;
1375 pending = FALSE;
1376 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1377 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1378 ok(pending, "got %d\n", pending);
1379 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1380 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1381 /* another attempt to begin initialization with block a single thread */
1383 g_initctxt = NULL;
1384 pending = 0xf;
1385 SetLastError( 0xdeadbeef );
1386 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1387 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1388 ok(pending == 0xf, "got %d\n", pending);
1389 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1390 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1392 g_initctxt = (void*)0xdeadbee0;
1393 SetLastError( 0xdeadbeef );
1394 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1395 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1396 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1398 /* once failed already */
1399 g_initctxt = (void*)0xdeadbee0;
1400 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1401 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1402 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1404 pInitOnceInitialize(&initonce);
1405 SetLastError( 0xdeadbeef );
1406 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1407 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1408 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1410 SetLastError( 0xdeadbeef );
1411 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1412 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1413 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1415 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1416 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1417 ok(pending, "got %d\n", pending);
1418 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1420 SetLastError( 0xdeadbeef );
1421 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1422 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1424 SetLastError( 0xdeadbeef );
1425 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1426 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1427 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1429 SetLastError( 0xdeadbeef );
1430 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef);
1431 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1432 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1434 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1435 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1436 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1438 pInitOnceInitialize(&initonce);
1439 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1440 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1441 ok(pending, "got %d\n", pending);
1442 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1444 SetLastError( 0xdeadbeef );
1445 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1446 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1448 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1449 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1450 ok(pending, "got %d\n", pending);
1451 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1453 SetLastError( 0xdeadbeef );
1454 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1455 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1456 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1458 SetLastError( 0xdeadbeef );
1459 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1460 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1461 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1463 SetLastError( 0xdeadbeef );
1464 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef);
1465 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1466 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1468 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1469 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1470 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1472 SetLastError( 0xdeadbeef );
1473 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1474 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1475 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1477 pInitOnceInitialize(&initonce);
1478 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1479 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1480 ok(pending, "got %d\n", pending);
1481 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1483 /* test INIT_ONCE_CHECK_ONLY */
1485 pInitOnceInitialize(&initonce);
1486 SetLastError( 0xdeadbeef );
1487 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1488 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1489 SetLastError( 0xdeadbeef );
1490 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1491 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1493 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1494 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1495 ok(pending, "got %d\n", pending);
1496 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1498 SetLastError( 0xdeadbeef );
1499 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1500 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1501 SetLastError( 0xdeadbeef );
1502 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1503 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1505 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0);
1506 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1507 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1509 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1510 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError());
1511 ok(!pending, "got %d\n", pending);
1512 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1513 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1515 SetLastError( 0xdeadbeef );
1516 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1517 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1519 pInitOnceInitialize(&initonce);
1520 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1521 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1522 ok(pending, "got %d\n", pending);
1523 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1525 SetLastError( 0xdeadbeef );
1526 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1527 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError());
1528 SetLastError( 0xdeadbeef );
1529 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1530 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1532 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1533 ok(ret, "wrong ret %d err %u\n", ret, GetLastError());
1534 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1536 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1537 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError());
1538 ok(!pending, "got %d\n", pending);
1539 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1540 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1542 SetLastError( 0xdeadbeef );
1543 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1544 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError());
1547 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT;
1548 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT;
1549 static CRITICAL_SECTION buffercrit;
1550 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1551 static LONG bufferlen,totalproduced,totalconsumed;
1552 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1554 #define BUFFER_SIZE 5
1556 static DWORD WINAPI condvar_producer(LPVOID x) {
1557 DWORD sleepinterval = 5;
1559 while (1) {
1560 Sleep(sleepinterval);
1561 if (sleepinterval > 1)
1562 sleepinterval -= 1;
1564 EnterCriticalSection(&buffercrit);
1565 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1566 condvar_producer_sleepcnt++;
1567 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) {
1568 if (GetLastError() != ERROR_TIMEOUT)
1569 condvar_sleeperr = TRUE;
1572 if (condvar_stop) {
1573 LeaveCriticalSection(&buffercrit);
1574 break;
1576 bufferlen++;
1577 totalproduced++;
1578 LeaveCriticalSection(&buffercrit);
1579 pWakeConditionVariable(&buffernotempty);
1581 return 0;
1584 static DWORD WINAPI condvar_consumer(LPVOID x) {
1585 DWORD *cnt = (DWORD*)x;
1586 DWORD sleepinterval = 1;
1588 while (1) {
1589 EnterCriticalSection(&buffercrit);
1590 while ((bufferlen == 0) && !condvar_stop) {
1591 condvar_consumer_sleepcnt++;
1592 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) {
1593 if (GetLastError() != ERROR_TIMEOUT)
1594 condvar_sleeperr = TRUE;
1597 if (condvar_stop && (bufferlen == 0)) {
1598 LeaveCriticalSection(&buffercrit);
1599 break;
1601 bufferlen--;
1602 totalconsumed++;
1603 (*cnt)++;
1604 LeaveCriticalSection(&buffercrit);
1605 pWakeConditionVariable(&buffernotfull);
1606 Sleep(sleepinterval);
1607 if (sleepinterval < 5) sleepinterval += 1;
1609 return 0;
1612 static void test_condvars_consumer_producer(void)
1614 HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
1615 DWORD dummy;
1616 DWORD cnt1,cnt2,cnt3;
1618 if (!pInitializeConditionVariable) {
1619 /* function is not yet in XP, only in newer Windows */
1620 win_skip("no condition variable support.\n");
1621 return;
1624 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1626 /* If we have static initialized condition variables, InitializeConditionVariable
1627 * is not strictly necessary.
1628 * pInitializeConditionVariable(&buffernotfull);
1630 pInitializeConditionVariable(&buffernotempty);
1631 InitializeCriticalSection(&buffercrit);
1633 /* Larger Test: consumer/producer example */
1635 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
1637 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1638 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1639 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1640 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1641 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1642 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy);
1644 /* Limit run to 0.5 seconds. */
1645 Sleep(500);
1647 /* tear down start */
1648 condvar_stop = TRUE;
1650 /* final wake up call */
1651 pWakeAllConditionVariable (&buffernotfull);
1652 pWakeAllConditionVariable (&buffernotempty);
1654 /* (mostly an implementation detail)
1655 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1658 WaitForSingleObject(hp1, 1000);
1659 WaitForSingleObject(hp2, 1000);
1660 WaitForSingleObject(hp3, 1000);
1661 WaitForSingleObject(hc1, 1000);
1662 WaitForSingleObject(hc2, 1000);
1663 WaitForSingleObject(hc3, 1000);
1665 ok(totalconsumed == totalproduced,
1666 "consumed %d != produced %d\n", totalconsumed, totalproduced);
1667 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1669 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1670 * one consumer does not get anything to do is possible. */
1671 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced, cnt1, cnt2, cnt3);
1672 /* The sleeps of the producer or consumer should not go above 100* produced count,
1673 * otherwise the implementation does not sleep correctly. But yet again, this is
1674 * not hard defined. */
1675 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1678 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1679 static DWORD condvar_seq = 0;
1680 static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT;
1681 static CRITICAL_SECTION condvar_crit;
1682 static SRWLOCK condvar_srwlock;
1684 /* Sequence of wake/sleep to check boundary conditions:
1685 * 0: init
1686 * 1: producer emits a WakeConditionVariable without consumer waiting.
1687 * 2: consumer sleeps without a wake expecting timeout
1688 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1689 * 4: consumer sleeps without a wake expecting timeout
1690 * 5: a wake is handed to a SleepConditionVariableCS
1691 * 6: a wakeall is handed to a SleepConditionVariableCS
1692 * 7: sleep after above should timeout
1693 * 8: wake with crit section locked into the sleep timeout
1695 * the following tests will only be executed if InitializeSRWLock is available
1697 * 9: producer (exclusive) wakes up consumer (exclusive)
1698 * 10: producer (exclusive) wakes up consumer (shared)
1699 * 11: producer (shared) wakes up consumer (exclusive)
1700 * 12: producer (shared) wakes up consumer (shared)
1701 * 13: end
1703 static DWORD WINAPI condvar_base_producer(LPVOID x) {
1704 while (condvar_seq < 1) Sleep(1);
1706 pWakeConditionVariable (&condvar_base);
1707 condvar_seq = 2;
1709 while (condvar_seq < 3) Sleep(1);
1710 pWakeAllConditionVariable (&condvar_base);
1711 condvar_seq = 4;
1713 while (condvar_seq < 5) Sleep(1);
1714 EnterCriticalSection (&condvar_crit);
1715 pWakeConditionVariable (&condvar_base);
1716 LeaveCriticalSection (&condvar_crit);
1717 while (condvar_seq < 6) Sleep(1);
1718 EnterCriticalSection (&condvar_crit);
1719 pWakeAllConditionVariable (&condvar_base);
1720 LeaveCriticalSection (&condvar_crit);
1722 while (condvar_seq < 8) Sleep(1);
1723 EnterCriticalSection (&condvar_crit);
1724 pWakeConditionVariable (&condvar_base);
1725 Sleep(50);
1726 LeaveCriticalSection (&condvar_crit);
1728 /* skip over remaining tests if InitializeSRWLock is not available */
1729 if (!pInitializeSRWLock)
1730 return 0;
1732 while (condvar_seq < 9) Sleep(1);
1733 pAcquireSRWLockExclusive(&condvar_srwlock);
1734 pWakeConditionVariable(&condvar_base);
1735 pReleaseSRWLockExclusive(&condvar_srwlock);
1737 while (condvar_seq < 10) Sleep(1);
1738 pAcquireSRWLockExclusive(&condvar_srwlock);
1739 pWakeConditionVariable(&condvar_base);
1740 pReleaseSRWLockExclusive(&condvar_srwlock);
1742 while (condvar_seq < 11) Sleep(1);
1743 pAcquireSRWLockShared(&condvar_srwlock);
1744 pWakeConditionVariable(&condvar_base);
1745 pReleaseSRWLockShared(&condvar_srwlock);
1747 while (condvar_seq < 12) Sleep(1);
1748 Sleep(50); /* ensure that consumer waits for cond variable */
1749 pAcquireSRWLockShared(&condvar_srwlock);
1750 pWakeConditionVariable(&condvar_base);
1751 pReleaseSRWLockShared(&condvar_srwlock);
1753 return 0;
1756 static DWORD WINAPI condvar_base_consumer(LPVOID x) {
1757 BOOL ret;
1759 while (condvar_seq < 2) Sleep(1);
1761 /* wake was emitted, but we were not sleeping */
1762 EnterCriticalSection (&condvar_crit);
1763 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1764 LeaveCriticalSection (&condvar_crit);
1765 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1766 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1768 condvar_seq = 3;
1769 while (condvar_seq < 4) Sleep(1);
1771 /* wake all was emitted, but we were not sleeping */
1772 EnterCriticalSection (&condvar_crit);
1773 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1774 LeaveCriticalSection (&condvar_crit);
1775 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1776 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1778 EnterCriticalSection (&condvar_crit);
1779 condvar_seq = 5;
1780 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1781 LeaveCriticalSection (&condvar_crit);
1782 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
1784 EnterCriticalSection (&condvar_crit);
1785 condvar_seq = 6;
1786 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1787 LeaveCriticalSection (&condvar_crit);
1788 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1789 condvar_seq = 7;
1791 EnterCriticalSection (&condvar_crit);
1792 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1793 LeaveCriticalSection (&condvar_crit);
1794 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1795 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1797 EnterCriticalSection (&condvar_crit);
1798 condvar_seq = 8;
1799 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20);
1800 LeaveCriticalSection (&condvar_crit);
1801 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1803 /* skip over remaining tests if InitializeSRWLock is not available */
1804 if (!pInitializeSRWLock)
1806 win_skip("no srw lock support.\n");
1807 condvar_seq = 13; /* end */
1808 return 0;
1811 pAcquireSRWLockExclusive(&condvar_srwlock);
1812 condvar_seq = 9;
1813 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0);
1814 pReleaseSRWLockExclusive(&condvar_srwlock);
1815 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1817 pAcquireSRWLockShared(&condvar_srwlock);
1818 condvar_seq = 10;
1819 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1820 pReleaseSRWLockShared(&condvar_srwlock);
1821 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1823 pAcquireSRWLockExclusive(&condvar_srwlock);
1824 condvar_seq = 11;
1825 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0);
1826 pReleaseSRWLockExclusive(&condvar_srwlock);
1827 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1829 pAcquireSRWLockShared(&condvar_srwlock);
1830 condvar_seq = 12;
1831 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
1832 pReleaseSRWLockShared(&condvar_srwlock);
1833 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1835 condvar_seq = 13;
1836 return 0;
1839 static void test_condvars_base(void) {
1840 HANDLE hp, hc;
1841 DWORD dummy;
1842 BOOL ret;
1845 if (!pInitializeConditionVariable) {
1846 /* function is not yet in XP, only in newer Windows */
1847 win_skip("no condition variable support.\n");
1848 return;
1851 InitializeCriticalSection (&condvar_crit);
1853 if (pInitializeSRWLock)
1854 pInitializeSRWLock(&condvar_srwlock);
1856 EnterCriticalSection (&condvar_crit);
1857 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1858 LeaveCriticalSection (&condvar_crit);
1860 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1861 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1863 if (pInitializeSRWLock)
1865 pAcquireSRWLockExclusive(&condvar_srwlock);
1866 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, 0);
1867 pReleaseSRWLockExclusive(&condvar_srwlock);
1869 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1870 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1872 pAcquireSRWLockShared(&condvar_srwlock);
1873 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED);
1874 pReleaseSRWLockShared(&condvar_srwlock);
1876 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1877 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1881 hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy);
1882 hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy);
1884 condvar_seq = 1; /* go */
1886 while (condvar_seq < 9)
1887 Sleep (5);
1888 WaitForSingleObject(hp, 100);
1889 WaitForSingleObject(hc, 100);
1892 static LONG srwlock_seq = 0;
1893 static SRWLOCK srwlock_base;
1894 static struct
1896 LONG wrong_execution_order;
1897 LONG samethread_excl_excl;
1898 LONG samethread_excl_shared;
1899 LONG samethread_shared_excl;
1900 LONG multithread_excl_excl;
1901 LONG excl_not_preferred;
1902 LONG trylock_excl;
1903 LONG trylock_shared;
1904 } srwlock_base_errors;
1906 /* Sequence of acquire/release to check boundary conditions:
1907 * 0: init
1909 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1910 * 2: thread1 expects a deadlock and releases the waiting lock
1911 * thread2 releases the lock again
1913 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1914 * 4: thread1 expects a deadlock and releases the waiting lock
1915 * thread2 releases the lock again
1917 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1918 * 6: thread1 expects a deadlock and releases the waiting lock
1919 * thread2 releases the lock again
1921 * 7: thread2 acquires and releases two nested shared locks
1923 * 8: thread1 acquires an exclusive lock
1924 * 9: thread2 tries to acquire the exclusive lock, too
1925 * thread1 releases the exclusive lock again
1926 * 10: thread2 enters the exclusive lock and leaves it immediately again
1928 * 11: thread1 acquires a shared lock
1929 * 12: thread2 acquires and releases a shared lock
1930 * thread1 releases the lock again
1932 * 13: thread1 acquires a shared lock
1933 * 14: thread2 tries to acquire an exclusive lock
1934 * 15: thread3 tries to acquire a shared lock
1935 * 16: thread1 releases the shared lock
1936 * 17: thread2 wakes up and releases the exclusive lock
1937 * 18: thread3 wakes up and releases the shared lock
1939 * the following tests will only be executed if TryAcquireSRWLock* is available
1941 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1942 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1943 * thread1 releases the exclusive lock
1945 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1946 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1947 * thread1 releases the shared lock
1949 * thread1 acquires an exclusive lock
1950 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1951 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1952 * 21: thread1 releases the exclusive lock
1954 * thread1 acquires an shared lock
1955 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
1956 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1957 * 23: thread1 releases the shared lock
1959 * thread1 acquires a shared lock and tries to acquire an exclusive lock
1960 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
1961 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1962 * 25: thread1 releases the exclusive lock
1964 * thread1 acquires two shared locks
1965 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
1966 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1967 * 27: thread1 releases one shared lock
1968 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
1969 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1970 * 29: thread1 releases the second shared lock
1971 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
1972 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
1974 * 31: end
1977 static DWORD WINAPI srwlock_base_thread1(LPVOID x)
1979 /* seq 2 */
1980 while (srwlock_seq < 2) Sleep(1);
1981 Sleep(100);
1982 if (InterlockedIncrement(&srwlock_seq) != 3)
1983 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
1984 pReleaseSRWLockExclusive(&srwlock_base);
1986 /* seq 4 */
1987 while (srwlock_seq < 4) Sleep(1);
1988 Sleep(100);
1989 if (InterlockedIncrement(&srwlock_seq) != 5)
1990 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
1991 pReleaseSRWLockExclusive(&srwlock_base);
1993 /* seq 6 */
1994 while (srwlock_seq < 6) Sleep(1);
1995 Sleep(100);
1996 if (InterlockedIncrement(&srwlock_seq) != 7)
1997 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
1998 pReleaseSRWLockShared(&srwlock_base);
2000 /* seq 8 */
2001 while (srwlock_seq < 8) Sleep(1);
2002 pAcquireSRWLockExclusive(&srwlock_base);
2003 if (InterlockedIncrement(&srwlock_seq) != 9)
2004 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2005 Sleep(100);
2006 if (InterlockedIncrement(&srwlock_seq) != 10)
2007 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2008 pReleaseSRWLockExclusive(&srwlock_base);
2010 /* seq 11 */
2011 while (srwlock_seq < 11) Sleep(1);
2012 pAcquireSRWLockShared(&srwlock_base);
2013 if (InterlockedIncrement(&srwlock_seq) != 12)
2014 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2016 /* seq 13 */
2017 while (srwlock_seq < 13) Sleep(1);
2018 pReleaseSRWLockShared(&srwlock_base);
2019 pAcquireSRWLockShared(&srwlock_base);
2020 if (InterlockedIncrement(&srwlock_seq) != 14)
2021 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2023 /* seq 16 */
2024 while (srwlock_seq < 16) Sleep(1);
2025 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2026 if (InterlockedIncrement(&srwlock_seq) != 17)
2027 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2028 pReleaseSRWLockShared(&srwlock_base);
2030 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2031 if (!pTryAcquireSRWLockExclusive)
2032 return 0;
2034 /* seq 19 */
2035 while (srwlock_seq < 19) Sleep(1);
2036 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2038 if (pTryAcquireSRWLockShared(&srwlock_base))
2039 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2040 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2041 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2042 pReleaseSRWLockExclusive(&srwlock_base);
2044 else
2045 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2047 if (pTryAcquireSRWLockShared(&srwlock_base))
2049 if (pTryAcquireSRWLockShared(&srwlock_base))
2050 pReleaseSRWLockShared(&srwlock_base);
2051 else
2052 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2053 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2054 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2055 pReleaseSRWLockShared(&srwlock_base);
2057 else
2058 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2060 pAcquireSRWLockExclusive(&srwlock_base);
2061 if (InterlockedIncrement(&srwlock_seq) != 20)
2062 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2064 /* seq 21 */
2065 while (srwlock_seq < 21) Sleep(1);
2066 pReleaseSRWLockExclusive(&srwlock_base);
2067 pAcquireSRWLockShared(&srwlock_base);
2068 if (InterlockedIncrement(&srwlock_seq) != 22)
2069 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2071 /* seq 23 */
2072 while (srwlock_seq < 23) Sleep(1);
2073 pReleaseSRWLockShared(&srwlock_base);
2074 pAcquireSRWLockShared(&srwlock_base);
2075 if (InterlockedIncrement(&srwlock_seq) != 24)
2076 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2078 /* seq 25 */
2079 pAcquireSRWLockExclusive(&srwlock_base);
2080 if (srwlock_seq != 25)
2081 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2082 pReleaseSRWLockExclusive(&srwlock_base);
2084 pAcquireSRWLockShared(&srwlock_base);
2085 pAcquireSRWLockShared(&srwlock_base);
2086 if (InterlockedIncrement(&srwlock_seq) != 26)
2087 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2089 /* seq 27 */
2090 while (srwlock_seq < 27) Sleep(1);
2091 pReleaseSRWLockShared(&srwlock_base);
2092 if (InterlockedIncrement(&srwlock_seq) != 28)
2093 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2095 /* seq 29 */
2096 while (srwlock_seq < 29) Sleep(1);
2097 pReleaseSRWLockShared(&srwlock_base);
2098 if (InterlockedIncrement(&srwlock_seq) != 30)
2099 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2101 return 0;
2104 static DWORD WINAPI srwlock_base_thread2(LPVOID x)
2106 /* seq 1 */
2107 while (srwlock_seq < 1) Sleep(1);
2108 pAcquireSRWLockExclusive(&srwlock_base);
2109 if (InterlockedIncrement(&srwlock_seq) != 2)
2110 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2112 /* seq 3 */
2113 pAcquireSRWLockExclusive(&srwlock_base);
2114 if (srwlock_seq != 3)
2115 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2116 pReleaseSRWLockExclusive(&srwlock_base);
2117 pAcquireSRWLockExclusive(&srwlock_base);
2118 if (InterlockedIncrement(&srwlock_seq) != 4)
2119 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2121 /* seq 5 */
2122 pAcquireSRWLockShared(&srwlock_base);
2123 if (srwlock_seq != 5)
2124 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2125 pReleaseSRWLockShared(&srwlock_base);
2126 pAcquireSRWLockShared(&srwlock_base);
2127 if (InterlockedIncrement(&srwlock_seq) != 6)
2128 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2130 /* seq 7 */
2131 pAcquireSRWLockExclusive(&srwlock_base);
2132 if (srwlock_seq != 7)
2133 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2134 pReleaseSRWLockExclusive(&srwlock_base);
2135 pAcquireSRWLockShared(&srwlock_base);
2136 pAcquireSRWLockShared(&srwlock_base);
2137 pReleaseSRWLockShared(&srwlock_base);
2138 pReleaseSRWLockShared(&srwlock_base);
2139 if (InterlockedIncrement(&srwlock_seq) != 8)
2140 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2142 /* seq 9, 10 */
2143 while (srwlock_seq < 9) Sleep(1);
2144 pAcquireSRWLockExclusive(&srwlock_base);
2145 if (srwlock_seq != 10)
2146 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2147 pReleaseSRWLockExclusive(&srwlock_base);
2148 if (InterlockedIncrement(&srwlock_seq) != 11)
2149 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2151 /* seq 12 */
2152 while (srwlock_seq < 12) Sleep(1);
2153 pAcquireSRWLockShared(&srwlock_base);
2154 pReleaseSRWLockShared(&srwlock_base);
2155 if (InterlockedIncrement(&srwlock_seq) != 13)
2156 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2158 /* seq 14 */
2159 while (srwlock_seq < 14) Sleep(1);
2160 if (InterlockedIncrement(&srwlock_seq) != 15)
2161 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2163 /* seq 17 */
2164 pAcquireSRWLockExclusive(&srwlock_base);
2165 if (srwlock_seq != 17)
2166 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2167 if (InterlockedIncrement(&srwlock_seq) != 18)
2168 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2169 pReleaseSRWLockExclusive(&srwlock_base);
2171 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2172 if (!pTryAcquireSRWLockExclusive)
2173 return 0;
2175 /* seq 20 */
2176 while (srwlock_seq < 20) Sleep(1);
2177 if (pTryAcquireSRWLockShared(&srwlock_base))
2178 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2179 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2180 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2181 if (InterlockedIncrement(&srwlock_seq) != 21)
2182 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2184 /* seq 22 */
2185 while (srwlock_seq < 22) Sleep(1);
2186 if (pTryAcquireSRWLockShared(&srwlock_base))
2187 pReleaseSRWLockShared(&srwlock_base);
2188 else
2189 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2190 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2191 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2192 if (InterlockedIncrement(&srwlock_seq) != 23)
2193 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2195 /* seq 24 */
2196 while (srwlock_seq < 24) Sleep(1);
2197 Sleep(50); /* ensure that exclusive access request is queued */
2198 if (pTryAcquireSRWLockShared(&srwlock_base))
2200 pReleaseSRWLockShared(&srwlock_base);
2201 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2203 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2204 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2205 if (InterlockedIncrement(&srwlock_seq) != 25)
2206 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2207 pReleaseSRWLockShared(&srwlock_base);
2209 /* seq 26 */
2210 while (srwlock_seq < 26) Sleep(1);
2211 if (pTryAcquireSRWLockShared(&srwlock_base))
2212 pReleaseSRWLockShared(&srwlock_base);
2213 else
2214 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2215 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2216 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2217 if (InterlockedIncrement(&srwlock_seq) != 27)
2218 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2220 /* seq 28 */
2221 while (srwlock_seq < 28) Sleep(1);
2222 if (pTryAcquireSRWLockShared(&srwlock_base))
2223 pReleaseSRWLockShared(&srwlock_base);
2224 else
2225 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2226 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2227 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2228 if (InterlockedIncrement(&srwlock_seq) != 29)
2229 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2231 /* seq 30 */
2232 while (srwlock_seq < 30) Sleep(1);
2233 if (pTryAcquireSRWLockShared(&srwlock_base))
2234 pReleaseSRWLockShared(&srwlock_base);
2235 else
2236 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2237 if (pTryAcquireSRWLockExclusive(&srwlock_base))
2238 pReleaseSRWLockExclusive(&srwlock_base);
2239 else
2240 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2241 if (InterlockedIncrement(&srwlock_seq) != 31)
2242 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2244 return 0;
2247 static DWORD WINAPI srwlock_base_thread3(LPVOID x)
2249 /* seq 15 */
2250 while (srwlock_seq < 15) Sleep(1);
2251 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2252 if (InterlockedIncrement(&srwlock_seq) != 16)
2253 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2255 /* seq 18 */
2256 pAcquireSRWLockShared(&srwlock_base);
2257 if (srwlock_seq != 18)
2258 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2259 pReleaseSRWLockShared(&srwlock_base);
2260 if (InterlockedIncrement(&srwlock_seq) != 19)
2261 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2263 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2264 if (!pTryAcquireSRWLockExclusive)
2266 /* function is only in Windows 7 and newer */
2267 win_skip("no srw trylock support.\n");
2268 srwlock_seq = 31; /* end */
2269 return 0;
2272 return 0;
2275 static void test_srwlock_base(void)
2277 HANDLE h1, h2, h3;
2278 DWORD dummy;
2280 if (!pInitializeSRWLock)
2282 /* function is not yet in XP, only in newer Windows */
2283 win_skip("no srw lock support.\n");
2284 return;
2287 pInitializeSRWLock(&srwlock_base);
2288 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors));
2290 h1 = CreateThread(NULL, 0, srwlock_base_thread1, NULL, 0, &dummy);
2291 h2 = CreateThread(NULL, 0, srwlock_base_thread2, NULL, 0, &dummy);
2292 h3 = CreateThread(NULL, 0, srwlock_base_thread3, NULL, 0, &dummy);
2294 srwlock_seq = 1; /* go */
2295 while (srwlock_seq < 31)
2296 Sleep(5);
2298 WaitForSingleObject(h1, 100);
2299 WaitForSingleObject(h2, 100);
2300 WaitForSingleObject(h3, 100);
2302 ok(!srwlock_base_errors.wrong_execution_order,
2303 "thread commands were executed in the wrong order (occurred %d times).\n",
2304 srwlock_base_errors.wrong_execution_order);
2306 ok(!srwlock_base_errors.samethread_excl_excl,
2307 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2308 srwlock_base_errors.samethread_excl_excl);
2310 ok(!srwlock_base_errors.samethread_excl_shared,
2311 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2312 srwlock_base_errors.samethread_excl_shared);
2314 ok(!srwlock_base_errors.samethread_shared_excl,
2315 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2316 srwlock_base_errors.samethread_shared_excl);
2318 ok(!srwlock_base_errors.multithread_excl_excl,
2319 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2320 srwlock_base_errors.multithread_excl_excl);
2322 ok(!srwlock_base_errors.excl_not_preferred,
2323 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2324 srwlock_base_errors.excl_not_preferred);
2326 ok(!srwlock_base_errors.trylock_excl,
2327 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2328 srwlock_base_errors.trylock_excl);
2330 ok(!srwlock_base_errors.trylock_shared,
2331 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2332 srwlock_base_errors.trylock_shared);
2336 static SRWLOCK srwlock_example;
2337 static LONG srwlock_protected_value = 0;
2338 static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0;
2339 static BOOL srwlock_stop = FALSE;
2341 static DWORD WINAPI srwlock_example_thread(LPVOID x) {
2342 DWORD *cnt = x;
2343 LONG old;
2345 while (!srwlock_stop)
2348 /* periodically request exclusive access */
2349 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0)
2351 pAcquireSRWLockExclusive(&srwlock_example);
2352 if (InterlockedIncrement(&srwlock_inside) != 1)
2353 InterlockedIncrement(&srwlock_example_errors);
2355 InterlockedIncrement(&srwlock_protected_value);
2356 Sleep(1);
2358 if (InterlockedDecrement(&srwlock_inside) != 0)
2359 InterlockedIncrement(&srwlock_example_errors);
2360 pReleaseSRWLockExclusive(&srwlock_example);
2363 /* request shared access */
2364 pAcquireSRWLockShared(&srwlock_example);
2365 InterlockedIncrement(&srwlock_inside);
2366 old = srwlock_protected_value;
2368 (*cnt)++;
2369 Sleep(1);
2371 if (old != srwlock_protected_value)
2372 InterlockedIncrement(&srwlock_example_errors);
2373 InterlockedDecrement(&srwlock_inside);
2374 pReleaseSRWLockShared(&srwlock_example);
2377 return 0;
2380 static void test_srwlock_example(void)
2382 HANDLE h1, h2, h3;
2383 DWORD dummy;
2384 DWORD cnt1, cnt2, cnt3;
2386 if (!pInitializeSRWLock) {
2387 /* function is not yet in XP, only in newer Windows */
2388 win_skip("no srw lock support.\n");
2389 return;
2392 pInitializeSRWLock(&srwlock_example);
2394 cnt1 = cnt2 = cnt3 = 0;
2396 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy);
2397 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy);
2398 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy);
2400 /* limit run to 1 second. */
2401 Sleep(1000);
2403 /* tear down start */
2404 srwlock_stop = TRUE;
2406 WaitForSingleObject(h1, 1000);
2407 WaitForSingleObject(h2, 1000);
2408 WaitForSingleObject(h3, 1000);
2410 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside);
2411 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2412 srwlock_example_errors);
2414 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1, cnt2, cnt3);
2415 trace("number of total exclusive accesses is %d\n", srwlock_protected_value);
2418 static DWORD WINAPI alertable_wait_thread(void *param)
2420 HANDLE *semaphores = param;
2421 LARGE_INTEGER timeout;
2422 NTSTATUS status;
2423 DWORD result;
2425 ReleaseSemaphore(semaphores[0], 1, NULL);
2426 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE);
2427 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %u\n", result);
2428 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE);
2429 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2431 ReleaseSemaphore(semaphores[0], 1, NULL);
2432 timeout.QuadPart = -10000000;
2433 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2434 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
2435 timeout.QuadPart = -2000000;
2436 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2437 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08x\n", status);
2439 ReleaseSemaphore(semaphores[0], 1, NULL);
2440 timeout.QuadPart = -10000000;
2441 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2442 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status);
2443 result = WaitForSingleObject(semaphores[0], 0);
2444 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", result);
2446 return 0;
2449 static void CALLBACK alertable_wait_apc(ULONG_PTR userdata)
2451 HANDLE *semaphores = (void *)userdata;
2452 ReleaseSemaphore(semaphores[1], 1, NULL);
2455 static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata)
2457 HANDLE *semaphores = (void *)userdata;
2458 DWORD result;
2460 result = WaitForSingleObject(semaphores[0], 1000);
2461 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2464 static void test_alertable_wait(void)
2466 HANDLE thread, semaphores[2];
2467 DWORD result;
2469 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
2470 ok(semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
2471 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
2472 ok(semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
2473 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL);
2474 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
2476 result = WaitForSingleObject(semaphores[0], 1000);
2477 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2478 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2479 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2480 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2482 result = WaitForSingleObject(semaphores[0], 1000);
2483 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2484 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2485 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2486 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2488 result = WaitForSingleObject(semaphores[0], 1000);
2489 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2490 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2491 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2492 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2493 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2494 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError());
2495 ReleaseSemaphore(semaphores[0], 2, NULL);
2497 result = WaitForSingleObject(thread, 1000);
2498 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2499 CloseHandle(thread);
2500 CloseHandle(semaphores[0]);
2501 CloseHandle(semaphores[1]);
2504 struct apc_deadlock_info
2506 PROCESS_INFORMATION *pi;
2507 HANDLE event;
2508 BOOL running;
2511 static DWORD WINAPI apc_deadlock_thread(void *param)
2513 struct apc_deadlock_info *info = param;
2514 PROCESS_INFORMATION *pi = info->pi;
2515 NTSTATUS status;
2516 SIZE_T size;
2517 void *base;
2519 while (info->running)
2521 base = NULL;
2522 size = 0x1000;
2523 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
2524 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
2525 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
2526 ok(base != NULL, "expected base != NULL, got %p\n", base);
2527 SetEvent(info->event);
2529 size = 0;
2530 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
2531 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
2532 SetEvent(info->event);
2535 return 0;
2538 static void test_apc_deadlock(void)
2540 struct apc_deadlock_info info;
2541 PROCESS_INFORMATION pi;
2542 STARTUPINFOA si = { sizeof(si) };
2543 char cmdline[MAX_PATH];
2544 HANDLE event, thread;
2545 DWORD result;
2546 BOOL success;
2547 char **argv;
2548 int i;
2550 winetest_get_mainargs(&argv);
2551 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
2552 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2553 ok(success, "CreateProcess failed with %u\n", GetLastError());
2555 event = CreateEventA(NULL, FALSE, FALSE, NULL);
2556 ok(event != NULL, "CreateEvent failed with %u\n", GetLastError());
2558 info.pi = &pi;
2559 info.event = event;
2560 info.running = TRUE;
2562 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
2563 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
2564 result = WaitForSingleObject(event, 1000);
2565 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2567 for (i = 0; i < 1000 && info.running; i++)
2569 result = SuspendThread(pi.hThread);
2570 ok(result == 0, "expected 0, got %u\n", result);
2572 WaitForSingleObject(event, 0); /* reset event */
2573 result = WaitForSingleObject(event, 1000);
2574 if (result == WAIT_TIMEOUT)
2576 todo_wine
2577 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2578 info.running = FALSE;
2580 else
2581 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2583 result = ResumeThread(pi.hThread);
2584 ok(result == 1, "expected 1, got %u\n", result);
2585 Sleep(1);
2588 info.running = FALSE;
2589 result = WaitForSingleObject(thread, 1000);
2590 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result);
2591 CloseHandle(thread);
2592 CloseHandle(event);
2594 TerminateProcess(pi.hProcess, 0);
2595 CloseHandle(pi.hThread);
2596 CloseHandle(pi.hProcess);
2599 START_TEST(sync)
2601 char **argv;
2602 int argc;
2603 HMODULE hdll = GetModuleHandleA("kernel32.dll");
2604 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
2606 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
2607 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
2608 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
2609 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
2610 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
2611 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
2612 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW");
2613 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
2614 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
2615 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock");
2616 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive");
2617 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared");
2618 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive");
2619 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
2620 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
2621 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
2622 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
2623 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
2624 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
2625 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
2626 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList");
2627 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx");
2629 argc = winetest_get_mainargs( &argv );
2630 if (argc >= 3)
2632 if (!strcmp(argv[2], "apc_deadlock"))
2634 for (;;) SleepEx(INFINITE, TRUE);
2636 return;
2639 init_fastcall_thunk();
2640 test_signalandwait();
2641 test_mutex();
2642 test_slist();
2643 test_event();
2644 test_semaphore();
2645 test_waitable_timer();
2646 test_iocp_callback();
2647 test_timer_queue();
2648 test_WaitForSingleObject();
2649 test_WaitForMultipleObjects();
2650 test_initonce();
2651 test_condvars_base();
2652 test_condvars_consumer_producer();
2653 test_srwlock_base();
2654 test_srwlock_example();
2655 test_alertable_wait();
2656 test_apc_deadlock();