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