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