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