2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 //#define _WIN32_WINNT 0x500
29 #include <wine/test.h>
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
);
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
);
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
*);
61 static void test_signalandwait(void)
63 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
66 HANDLE event
[2], semaphore
[2], file
;
68 kernel32
= GetModuleHandleA("kernel32.dll");
69 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
71 if (!pSignalObjectAndWait
)
74 /* invalid parameters */
75 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
76 if (r
== ERROR_INVALID_FUNCTION
)
78 win_skip("SignalObjectAndWait is not implemented\n");
79 return; /* Win98/ME */
81 ok( r
== WAIT_FAILED
, "should fail\n");
83 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
84 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
86 ok( event
[0] && event
[1], "failed to create event flags\n");
88 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
89 ok( r
== WAIT_FAILED
, "should fail\n");
91 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
92 ok( r
== WAIT_FAILED
, "should fail\n");
95 /* valid parameters */
96 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
97 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
99 /* event[0] is now signalled */
100 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
101 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
103 /* event[0] is not signalled */
104 r
= WaitForSingleObject(event
[0], 0);
105 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
107 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
108 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
110 /* clear event[1] and check for a timeout */
111 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
112 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
113 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
115 CloseHandle(event
[0]);
116 CloseHandle(event
[1]);
119 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
120 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
121 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
123 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
124 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
126 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
127 ok( r
== WAIT_FAILED
, "should fail\n");
129 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
130 ok( r
== FALSE
, "should fail\n");
132 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
133 ok( r
== TRUE
, "should succeed\n");
135 CloseHandle(semaphore
[0]);
136 CloseHandle(semaphore
[1]);
138 /* try a registry key */
139 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
140 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
141 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
142 ok( r
== WAIT_FAILED
, "should fail\n");
143 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
147 static void test_mutex(void)
156 SetLastError(0xdeadbeef);
157 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
158 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
159 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
161 SetLastError(0xdeadbeef);
162 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
163 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
165 SetLastError(0xdeadbeef);
166 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
168 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
170 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
172 SetLastError(0xdeadbeef);
173 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
174 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
175 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
176 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
177 CloseHandle(hOpened
);
179 for(i
=0; i
< 31; i
++)
181 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
182 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
185 SetLastError(0xdeadbeef);
186 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
187 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
188 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
189 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
190 CloseHandle(hOpened
);
192 for (i
= 0; i
< 32; i
++)
194 SetLastError(0xdeadbeef);
195 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
198 SetLastError(0xdeadbeef);
199 ret
= ReleaseMutex(hOpened
);
200 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
201 CloseHandle(hOpened
);
205 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
206 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
208 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
209 ReleaseMutex(hCreated
);
215 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
217 SetLastError(0xdeadbeef);
218 ret
= ReleaseMutex(hCreated
);
219 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
220 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
222 /* test case sensitivity */
224 SetLastError(0xdeadbeef);
225 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
226 ok(!hOpened
, "OpenMutex succeeded\n");
227 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
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());
234 SetLastError(0xdeadbeef);
235 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
236 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
237 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
238 CloseHandle(hOpened
);
240 SetLastError(0xdeadbeef);
241 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
242 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
243 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
244 CloseHandle(hOpened
);
246 CloseHandle(hCreated
);
249 static void test_slist(void)
255 } item1
, item2
, item3
, *pitem
;
257 SLIST_HEADER slist_header
;
258 PSLIST_ENTRY entry
, next
;
262 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
263 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
264 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
265 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
266 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
269 kernel32
= GetModuleHandleA("KERNEL32.DLL");
270 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
271 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
272 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
273 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
274 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
275 if (pInitializeSListHead
== NULL
||
276 pQueryDepthSList
== NULL
||
277 pInterlockedFlushSList
== NULL
||
278 pInterlockedPopEntrySList
== NULL
||
279 pInterlockedPushEntrySList
== NULL
)
281 win_skip("some required slist entrypoints were not found, skipping tests\n");
285 memset(&slist_header
, 0xFF, sizeof(slist_header
));
286 pInitializeSListHead(&slist_header
);
287 size
= pQueryDepthSList(&slist_header
);
288 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
291 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
292 "previous entry in empty slist wasn't NULL\n");
293 size
= pQueryDepthSList(&slist_header
);
294 ok(size
== 1, "slist with 1 item has size %d\n", size
);
297 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
298 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
301 pitem
= (struct item
*) entry
;
302 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
304 size
= pQueryDepthSList(&slist_header
);
305 ok(size
== 2, "slist with 2 items has size %d\n", size
);
308 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
309 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
312 pitem
= (struct item
*) entry
;
313 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
315 size
= pQueryDepthSList(&slist_header
);
316 ok(size
== 3, "slist with 3 items has size %d\n", size
);
318 entry
= pInterlockedPopEntrySList(&slist_header
);
319 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
322 pitem
= (struct item
*) entry
;
323 ok(pitem
->value
== 3, "unexpected entry removed\n");
325 size
= pQueryDepthSList(&slist_header
);
326 ok(size
== 2, "slist with 2 items has size %d\n", size
);
328 entry
= pInterlockedFlushSList(&slist_header
);
329 size
= pQueryDepthSList(&slist_header
);
330 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
333 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
334 "popping empty slist didn't return NULL\n");
336 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
337 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
339 for (i
= 0; i
< 65536; i
++)
341 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
342 pInterlockedPushEntrySList(&slist_header
, entry
);
345 entry
= pInterlockedFlushSList(&slist_header
);
346 ok(entry
!= NULL
, "not flushed\n");
350 HeapFree(GetProcessHeap(), 0, entry
);
355 static void test_event(void)
357 HANDLE handle
, handle2
;
358 SECURITY_ATTRIBUTES sa
;
359 SECURITY_DESCRIPTOR sd
;
365 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
366 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
369 sa
.nLength
= sizeof(sa
);
370 sa
.lpSecurityDescriptor
= &sd
;
371 sa
.bInheritHandle
= FALSE
;
373 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
376 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
377 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
380 /* sd with NULL dacl */
381 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
382 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
383 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
386 /* sd with empty dacl */
387 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
388 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
389 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
390 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
393 /* test case sensitivity */
395 SetLastError(0xdeadbeef);
396 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
397 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
398 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
400 SetLastError(0xdeadbeef);
401 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
402 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
403 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
404 CloseHandle( handle2
);
406 SetLastError(0xdeadbeef);
407 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
408 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
409 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
410 CloseHandle( handle2
);
412 SetLastError(0xdeadbeef);
413 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
414 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
415 CloseHandle( handle2
);
417 SetLastError(0xdeadbeef);
418 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
419 ok( !handle2
, "OpenEvent succeeded\n");
420 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
422 CloseHandle( handle
);
424 /* resource notifications are events too */
426 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
428 trace( "memory resource notifications not supported\n" );
431 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
432 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
433 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
434 ret
= pQueryMemoryResourceNotification( handle
, &val
);
435 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
436 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
438 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
439 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
440 ret
= WaitForSingleObject( handle
, 10 );
441 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
444 ret
= pQueryMemoryResourceNotification( handle
, &val
);
445 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
446 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
447 ret
= CloseHandle( handle
);
448 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
450 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
452 ret
= pQueryMemoryResourceNotification( handle
, &val
);
453 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
454 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
455 CloseHandle( handle
);
458 static void test_semaphore(void)
460 HANDLE handle
, handle2
;
462 /* test case sensitivity */
464 SetLastError(0xdeadbeef);
465 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
466 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
467 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
469 SetLastError(0xdeadbeef);
470 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
471 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
472 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
473 CloseHandle( handle2
);
475 SetLastError(0xdeadbeef);
476 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
477 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
478 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
479 CloseHandle( handle2
);
481 SetLastError(0xdeadbeef);
482 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
483 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
484 CloseHandle( handle2
);
486 SetLastError(0xdeadbeef);
487 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
488 ok( !handle2
, "OpenSemaphore succeeded\n");
489 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
491 CloseHandle( handle
);
494 static void test_waitable_timer(void)
496 HANDLE handle
, handle2
;
498 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
500 win_skip("{Create,Open}WaitableTimerA() is not available\n");
504 /* test case sensitivity */
506 SetLastError(0xdeadbeef);
507 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
508 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
509 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
511 SetLastError(0xdeadbeef);
512 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
513 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
514 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
515 CloseHandle( handle2
);
517 SetLastError(0xdeadbeef);
518 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
519 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
520 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
521 CloseHandle( handle2
);
523 SetLastError(0xdeadbeef);
524 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
525 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
526 CloseHandle( handle2
);
528 SetLastError(0xdeadbeef);
529 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
530 ok( !handle2
, "OpenWaitableTimer succeeded\n");
531 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
532 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
533 "wrong error %u\n", GetLastError());
535 CloseHandle( handle
);
538 static HANDLE sem
= 0;
540 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
542 ReleaseSemaphore(sem
, 1, NULL
);
545 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
547 static void test_iocp_callback(void)
549 char temp_path
[MAX_PATH
];
550 char filename
[MAX_PATH
];
553 static const char prefix
[] = "pfx";
555 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
557 const char *buffer
= "12345678123456781234567812345678";
558 OVERLAPPED overlapped
;
560 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
561 if(!p_BindIoCompletionCallback
) {
562 win_skip("BindIoCompletionCallback not found in this DLL\n");
566 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
567 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
569 ret
= GetTempPathA(MAX_PATH
, temp_path
);
570 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
571 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
573 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
574 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
576 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
577 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
578 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
580 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
581 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
582 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
584 ret
= CloseHandle(hFile
);
585 ok( ret
, "CloseHandle: error %d\n", GetLastError());
586 ret
= DeleteFileA(filename
);
587 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
589 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
590 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
591 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
593 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
594 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
596 memset(&overlapped
, 0, sizeof(overlapped
));
597 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
598 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
600 ret
= WaitForSingleObject(sem
, 5000);
601 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
604 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
605 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
606 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
607 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
608 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
609 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
611 ret
= CloseHandle(hFile
);
612 ok( ret
, "CloseHandle: error %d\n", GetLastError());
613 ret
= DeleteFileA(filename
);
614 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
616 /* win2k3 requires the Flags parameter to be zero */
617 SetLastError(0xdeadbeef);
618 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
619 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
620 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
621 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
623 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
624 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
626 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
627 ret
= CloseHandle(hFile
);
628 ok( ret
, "CloseHandle: error %d\n", GetLastError());
629 ret
= DeleteFileA(filename
);
630 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
632 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
633 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
634 ok(GetLastError() == ERROR_INVALID_HANDLE
||
635 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
636 "Last error is %d\n", GetLastError());
639 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
642 ok(timedOut
, "Timer callbacks should always time out\n");
646 struct timer_queue_data1
653 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
655 struct timer_queue_data1
*d
= p
;
656 ok(timedOut
, "Timer callbacks should always time out\n");
657 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
660 SetLastError(0xdeadbeef);
661 /* Note, XP SP2 does *not* do any deadlock checking, so passing
662 INVALID_HANDLE_VALUE here will just hang. */
663 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
664 ok(!ret
, "DeleteTimerQueueTimer\n");
665 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
669 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
671 struct timer_queue_data1
*d
= p
;
672 ok(timedOut
, "Timer callbacks should always time out\n");
673 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
675 /* Basically kill the timer since it won't have time to run
677 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
678 ok(ret
, "ChangeTimerQueueTimer\n");
682 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
684 struct timer_queue_data1
*d
= p
;
685 ok(timedOut
, "Timer callbacks should always time out\n");
688 /* This tests whether a timer gets flagged for deletion before
689 or after the callback runs. If we start this timer with a
690 period of zero (run once), then ChangeTimerQueueTimer will
691 fail if the timer is already flagged. Hence we really run
692 only once. Otherwise we will run multiple times. */
693 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
694 ok(ret
, "ChangeTimerQueueTimer\n");
699 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
701 DWORD_PTR delay
= (DWORD_PTR
) p
;
702 ok(timedOut
, "Timer callbacks should always time out\n");
707 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
709 struct timer_queue_data1
*d
= p
;
710 ok(timedOut
, "Timer callbacks should always time out\n");
711 /* This tests an original implementation bug where a deleted timer may get
712 to run, but it is tricky to set up. */
713 if (d
->q
&& d
->num_calls
++ == 0)
715 /* First run: delete ourselves, then insert and remove a timer
716 that goes in front of us in the sorted timeout list. Once
717 removed, we will still timeout at the faster timer's due time,
718 but this should be a no-op if we are bug-free. There should
719 not be a second run. We can test the value of num_calls later. */
723 /* The delete will pend while we are in this callback. */
724 SetLastError(0xdeadbeef);
725 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
726 ok(!ret
, "DeleteTimerQueueTimer\n");
727 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
729 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
730 ok(ret
, "CreateTimerQueueTimer\n");
731 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
733 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
734 ok(ret
, "DeleteTimerQueueTimer\n");
736 /* Now we stay alive by hanging around in the callback. */
741 static void test_timer_queue(void)
743 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
744 int n0
, n1
, n2
, n3
, n4
, n5
;
745 struct timer_queue_data1 d1
, d2
, d3
, d4
;
749 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
750 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
752 win_skip("TimerQueue API not present\n");
756 /* Test asynchronous deletion of the queue. */
757 q
= pCreateTimerQueue();
758 ok(q
!= NULL
, "CreateTimerQueue\n");
760 SetLastError(0xdeadbeef);
761 ret
= pDeleteTimerQueueEx(q
, NULL
);
762 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
763 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
766 /* Test synchronous deletion of the queue and running timers. */
767 q
= pCreateTimerQueue();
768 ok(q
!= NULL
, "CreateTimerQueue\n");
773 ret
= pCreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0,
775 ok(ret
, "CreateTimerQueueTimer\n");
776 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
777 ret0
= pDeleteTimerQueueTimer(q
, t0
, NULL
);
778 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
779 broken(ret0
), /* Win 2000 & XP & 2003 */
780 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
785 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
787 ok(ret
, "CreateTimerQueueTimer\n");
788 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
793 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
795 ok(ret
, "CreateTimerQueueTimer\n");
796 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
801 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
803 ok(ret
, "CreateTimerQueueTimer\n");
804 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
806 /* Start really late (it won't start). */
809 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
811 ok(ret
, "CreateTimerQueueTimer\n");
812 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
814 /* Start soon, but delay so long it won't run again. */
817 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
819 ok(ret
, "CreateTimerQueueTimer\n");
820 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
822 /* Give them a chance to do some work. */
825 /* Test deleting a once-only timer. */
826 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
827 ok(ret
, "DeleteTimerQueueTimer\n");
829 /* A periodic timer. */
830 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
831 ok(ret
, "DeleteTimerQueueTimer\n");
833 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
834 ok(ret
, "DeleteTimerQueueEx\n");
836 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
837 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
838 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
839 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
840 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
842 /* Test synchronous deletion of the timer/queue with event trigger. */
843 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
844 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
845 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
846 if (!e
|| !et1
|| !et2
)
848 skip("Failed to create timer queue descruction event\n");
852 q
= pCreateTimerQueue();
853 ok(q
!= NULL
, "CreateTimerQueue\n");
855 /* Run once and finish quickly (should be done when we delete it). */
857 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
858 ok(ret
, "CreateTimerQueueTimer\n");
859 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
861 /* Run once and finish slowly (shouldn't be done when we delete it). */
863 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
865 ok(ret
, "CreateTimerQueueTimer\n");
866 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
868 /* Run once and finish quickly (should be done when we delete it). */
870 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
871 ok(ret
, "CreateTimerQueueTimer\n");
872 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
874 /* Run once and finish slowly (shouldn't be done when we delete it). */
876 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
878 ok(ret
, "CreateTimerQueueTimer\n");
879 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
881 /* Give them a chance to start. */
884 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
885 even if the timer is finished. */
886 SetLastError(0xdeadbeef);
887 ret
= pDeleteTimerQueueTimer(q
, t1
, NULL
);
888 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
889 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
892 SetLastError(0xdeadbeef);
893 ret
= pDeleteTimerQueueTimer(q
, t2
, NULL
);
894 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
895 ok(GetLastError() == ERROR_IO_PENDING
,
896 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
899 SetLastError(0xdeadbeef);
900 ret
= pDeleteTimerQueueTimer(q
, t3
, et1
);
901 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
902 ok(GetLastError() == 0xdeadbeef,
903 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
905 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
906 "Timer destruction event not triggered\n");
908 SetLastError(0xdeadbeef);
909 ret
= pDeleteTimerQueueTimer(q
, t4
, et2
);
910 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
911 ok(GetLastError() == ERROR_IO_PENDING
,
912 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
914 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
915 "Timer destruction event not triggered\n");
917 SetLastError(0xdeadbeef);
918 ret
= pDeleteTimerQueueEx(q
, e
);
919 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
920 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
922 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
923 "Queue destruction event not triggered\n");
926 /* Test deleting/changing a timer in execution. */
927 q
= pCreateTimerQueue();
928 ok(q
!= NULL
, "CreateTimerQueue\n");
930 /* Test changing a once-only timer before it fires (this is allowed,
931 whereas after it fires you cannot). */
933 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
935 ok(ret
, "CreateTimerQueueTimer\n");
936 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
937 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
938 ok(ret
, "ChangeTimerQueueTimer\n");
944 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
947 ok(ret
, "CreateTimerQueueTimer\n");
948 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
954 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
957 ok(ret
, "CreateTimerQueueTimer\n");
958 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
963 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
966 ok(ret
, "CreateTimerQueueTimer\n");
967 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
971 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
972 ok(ret
, "DeleteTimerQueueEx\n");
973 ok(n1
== 1, "ChangeTimerQueueTimer\n");
974 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
975 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
976 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
978 /* Test an obscure bug that was in the original implementation. */
979 q
= pCreateTimerQueue();
980 ok(q
!= NULL
, "CreateTimerQueue\n");
982 /* All the work is done in the callback. */
986 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
987 100, WT_EXECUTELONGFUNCTION
);
989 ok(ret
, "CreateTimerQueueTimer\n");
990 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
994 SetLastError(0xdeadbeef);
995 ret
= pDeleteTimerQueueEx(q
, NULL
);
996 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
997 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
999 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1001 /* Test functions on the default timer queue. */
1004 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
1006 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1007 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1009 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1010 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1012 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1013 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1015 /* Try mixing default and non-default queues. Apparently this works. */
1016 q
= pCreateTimerQueue();
1017 ok(q
!= NULL
, "CreateTimerQueue\n");
1021 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
1023 ok(ret
, "CreateTimerQueueTimer\n");
1024 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1028 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
1030 ok(ret
, "CreateTimerQueueTimer\n");
1031 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1033 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1034 ok(ret
, "ChangeTimerQueueTimer\n");
1036 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1037 ok(ret
, "ChangeTimerQueueTimer\n");
1039 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1040 ok(ret
, "DeleteTimerQueueTimer\n");
1042 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1043 ok(ret
, "DeleteTimerQueueTimer\n");
1045 /* Try to delete the default queue? In any case: not allowed. */
1046 SetLastError(0xdeadbeef);
1047 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
1048 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1049 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1050 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1053 SetLastError(0xdeadbeef);
1054 ret
= pDeleteTimerQueueEx(q
, NULL
);
1055 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1056 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1060 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1062 DWORD tmp
= HandleToULong(handle
);
1064 return ULongToHandle(tmp
);
1067 static void test_WaitForSingleObject(void)
1069 HANDLE signaled
, nonsignaled
, invalid
;
1072 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1073 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1074 invalid
= (HANDLE
) 0xdeadbee0;
1076 /* invalid handle with different values for lower 2 bits */
1077 SetLastError(0xdeadbeef);
1078 ret
= WaitForSingleObject(invalid
, 0);
1079 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1080 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1082 SetLastError(0xdeadbeef);
1083 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1084 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1085 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1087 SetLastError(0xdeadbeef);
1088 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1089 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1090 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1092 SetLastError(0xdeadbeef);
1093 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1094 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1095 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1097 /* valid handle with different values for lower 2 bits */
1098 SetLastError(0xdeadbeef);
1099 ret
= WaitForSingleObject(nonsignaled
, 0);
1100 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1101 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1103 SetLastError(0xdeadbeef);
1104 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1105 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1106 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1108 SetLastError(0xdeadbeef);
1109 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1110 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1111 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1113 SetLastError(0xdeadbeef);
1114 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1115 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1116 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1118 /* valid handle with different values for lower 2 bits */
1119 SetLastError(0xdeadbeef);
1120 ret
= WaitForSingleObject(signaled
, 0);
1121 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1122 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1124 SetLastError(0xdeadbeef);
1125 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1126 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1127 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1129 SetLastError(0xdeadbeef);
1130 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1131 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1132 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1134 SetLastError(0xdeadbeef);
1135 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1136 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1137 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1139 CloseHandle(signaled
);
1140 CloseHandle(nonsignaled
);
1143 static void test_WaitForMultipleObjects(void)
1147 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1149 /* create the maximum number of events and make sure
1150 * we can wait on that many */
1151 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1153 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1154 ok( maxevents
[i
] != 0, "should create enough events\n");
1157 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1158 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1159 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1160 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1161 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1162 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1163 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1165 /* the lowest index is checked first and remaining events are untouched */
1166 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1167 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1170 /* run same test with Nt* call */
1171 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1172 SetEvent(maxevents
[i
]);
1174 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1175 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1176 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1177 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1178 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1179 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1180 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1182 /* the lowest index is checked first and remaining events are untouched */
1183 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1184 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1187 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1188 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1191 static BOOL g_initcallback_ret
, g_initcallback_called
;
1192 static void *g_initctxt
;
1194 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1196 g_initcallback_called
= TRUE
;
1197 /* zero bit set means here that initialization is taking place - initialization locked */
1198 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1199 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1200 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1201 return g_initcallback_ret
;
1204 static void test_initonce(void)
1209 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1211 win_skip("one-time initialization API not supported\n");
1215 /* blocking initialization with callback */
1216 initonce
.Ptr
= (void*)0xdeadbeef;
1217 pInitOnceInitialize(&initonce
);
1218 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1220 /* initialisation completed successfully */
1221 g_initcallback_ret
= TRUE
;
1223 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1224 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1225 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1226 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1227 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1229 /* so it's been called already so won't be called again */
1231 g_initcallback_called
= FALSE
;
1232 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1233 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1234 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1235 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1236 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1238 pInitOnceInitialize(&initonce
);
1239 g_initcallback_called
= FALSE
;
1240 /* 2 lower order bits should never be used, you'll get a crash in result */
1241 g_initctxt
= (void*)0xFFFFFFF0;
1242 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1243 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1244 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1245 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1246 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1248 /* callback failed */
1249 g_initcallback_ret
= FALSE
;
1250 g_initcallback_called
= FALSE
;
1252 pInitOnceInitialize(&initonce
);
1253 SetLastError( 0xdeadbeef );
1254 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1255 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1256 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1257 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1258 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1260 /* blocking initialization without a callback */
1261 pInitOnceInitialize(&initonce
);
1264 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1265 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1266 ok(pending
, "got %d\n", pending
);
1267 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1268 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1269 /* another attempt to begin initialization with block a single thread */
1273 SetLastError( 0xdeadbeef );
1274 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1275 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1276 ok(pending
== 0xf, "got %d\n", pending
);
1277 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1278 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1280 g_initctxt
= (void*)0xdeadbee0;
1281 SetLastError( 0xdeadbeef );
1282 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1283 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1284 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1286 /* once failed already */
1287 g_initctxt
= (void*)0xdeadbee0;
1288 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1289 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1290 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1292 pInitOnceInitialize(&initonce
);
1293 SetLastError( 0xdeadbeef );
1294 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1295 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1296 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1298 SetLastError( 0xdeadbeef );
1299 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1300 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1301 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1303 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1304 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1305 ok(pending
, "got %d\n", pending
);
1306 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1308 SetLastError( 0xdeadbeef );
1309 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1310 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1312 SetLastError( 0xdeadbeef );
1313 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1314 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1315 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1317 SetLastError( 0xdeadbeef );
1318 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1319 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1320 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1322 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1323 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1324 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1326 pInitOnceInitialize(&initonce
);
1327 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1328 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1329 ok(pending
, "got %d\n", pending
);
1330 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1332 SetLastError( 0xdeadbeef );
1333 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1334 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1336 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1337 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1338 ok(pending
, "got %d\n", pending
);
1339 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1341 SetLastError( 0xdeadbeef );
1342 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1343 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1344 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1346 SetLastError( 0xdeadbeef );
1347 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1348 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1349 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1351 SetLastError( 0xdeadbeef );
1352 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1353 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1354 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1356 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1357 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1358 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1360 SetLastError( 0xdeadbeef );
1361 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1362 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1363 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1365 pInitOnceInitialize(&initonce
);
1366 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1367 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1368 ok(pending
, "got %d\n", pending
);
1369 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1371 /* test INIT_ONCE_CHECK_ONLY */
1373 pInitOnceInitialize(&initonce
);
1374 SetLastError( 0xdeadbeef );
1375 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1376 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1377 SetLastError( 0xdeadbeef );
1378 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1379 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1381 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1382 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1383 ok(pending
, "got %d\n", pending
);
1384 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1386 SetLastError( 0xdeadbeef );
1387 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1388 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1389 SetLastError( 0xdeadbeef );
1390 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1391 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1393 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1394 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1395 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1397 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1398 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1399 ok(!pending
, "got %d\n", pending
);
1400 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1401 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1403 SetLastError( 0xdeadbeef );
1404 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1405 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1407 pInitOnceInitialize(&initonce
);
1408 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1409 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1410 ok(pending
, "got %d\n", pending
);
1411 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1413 SetLastError( 0xdeadbeef );
1414 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1415 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1416 SetLastError( 0xdeadbeef );
1417 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1418 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1420 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1421 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1422 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1424 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1425 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1426 ok(!pending
, "got %d\n", pending
);
1427 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1428 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1430 SetLastError( 0xdeadbeef );
1431 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1432 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1435 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1436 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1437 static CRITICAL_SECTION buffercrit
;
1438 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1439 static LONG bufferlen
,totalproduced
,totalconsumed
;
1440 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1442 #define BUFFER_SIZE 5
1444 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1445 DWORD sleepinterval
= 5;
1448 Sleep(sleepinterval
);
1449 if (sleepinterval
> 1)
1452 EnterCriticalSection(&buffercrit
);
1453 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1454 condvar_producer_sleepcnt
++;
1455 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1456 if (GetLastError() != ERROR_TIMEOUT
)
1457 condvar_sleeperr
= TRUE
;
1461 LeaveCriticalSection(&buffercrit
);
1466 LeaveCriticalSection(&buffercrit
);
1467 pWakeConditionVariable(&buffernotempty
);
1472 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1473 DWORD
*cnt
= (DWORD
*)x
;
1474 DWORD sleepinterval
= 1;
1477 EnterCriticalSection(&buffercrit
);
1478 while ((bufferlen
== 0) && !condvar_stop
) {
1479 condvar_consumer_sleepcnt
++;
1480 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1481 if (GetLastError() != ERROR_TIMEOUT
)
1482 condvar_sleeperr
= TRUE
;
1485 if (condvar_stop
&& (bufferlen
== 0)) {
1486 LeaveCriticalSection(&buffercrit
);
1492 LeaveCriticalSection(&buffercrit
);
1493 pWakeConditionVariable(&buffernotfull
);
1494 Sleep(sleepinterval
);
1495 if (sleepinterval
< 5) sleepinterval
+= 1;
1500 static void test_condvars_consumer_producer(void)
1502 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1504 DWORD cnt1
,cnt2
,cnt3
;
1506 if (!pInitializeConditionVariable
) {
1507 /* function is not yet in XP, only in newer Windows */
1508 win_skip("no condition variable support.\n");
1512 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1514 /* If we have static initialized condition variables, InitializeConditionVariable
1515 * is not strictly necessary.
1516 * pInitializeConditionVariable(&buffernotfull);
1518 pInitializeConditionVariable(&buffernotempty
);
1519 InitializeCriticalSection(&buffercrit
);
1521 /* Larger Test: consumer/producer example */
1523 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1525 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1526 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1527 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1528 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1529 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1530 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1532 /* Limit run to 0.5 seconds. */
1535 /* tear down start */
1536 condvar_stop
= TRUE
;
1538 /* final wake up call */
1539 pWakeAllConditionVariable (&buffernotfull
);
1540 pWakeAllConditionVariable (&buffernotempty
);
1542 /* (mostly an implementation detail)
1543 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1546 WaitForSingleObject(hp1
, 1000);
1547 WaitForSingleObject(hp2
, 1000);
1548 WaitForSingleObject(hp3
, 1000);
1549 WaitForSingleObject(hc1
, 1000);
1550 WaitForSingleObject(hc2
, 1000);
1551 WaitForSingleObject(hc3
, 1000);
1553 ok(totalconsumed
== totalproduced
,
1554 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1555 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1557 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1558 * one consumer does not get anything to do is possible. */
1559 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1560 /* The sleeps of the producer or consumer should not go above 100* produced count,
1561 * otherwise the implementation does not sleep correctly. But yet again, this is
1562 * not hard defined. */
1563 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1566 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1567 static DWORD condvar_seq
= 0;
1568 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1569 static CRITICAL_SECTION condvar_crit
;
1570 static SRWLOCK condvar_srwlock
;
1572 /* Sequence of wake/sleep to check boundary conditions:
1574 * 1: producer emits a WakeConditionVaribale without consumer waiting.
1575 * 2: consumer sleeps without a wake expecting timeout
1576 * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
1577 * 4: consumer sleeps without a wake expecting timeout
1578 * 5: a wake is handed to a SleepConditionVariableCS
1579 * 6: a wakeall is handed to a SleepConditionVariableCS
1580 * 7: sleep after above should timeout
1581 * 8: wake with crit section locked into the sleep timeout
1583 * the following tests will only be executed if InitializeSRWLock is available
1585 * 9: producer (exclusive) wakes up consumer (exclusive)
1586 * 10: producer (exclusive) wakes up consumer (shared)
1587 * 11: producer (shared) wakes up consumer (exclusive)
1588 * 12: producer (shared) wakes up consumer (shared)
1591 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1592 while (condvar_seq
< 1) Sleep(1);
1594 pWakeConditionVariable (&condvar_base
);
1597 while (condvar_seq
< 3) Sleep(1);
1598 pWakeAllConditionVariable (&condvar_base
);
1601 while (condvar_seq
< 5) Sleep(1);
1602 EnterCriticalSection (&condvar_crit
);
1603 pWakeConditionVariable (&condvar_base
);
1604 LeaveCriticalSection (&condvar_crit
);
1605 while (condvar_seq
< 6) Sleep(1);
1606 EnterCriticalSection (&condvar_crit
);
1607 pWakeAllConditionVariable (&condvar_base
);
1608 LeaveCriticalSection (&condvar_crit
);
1610 while (condvar_seq
< 8) Sleep(1);
1611 EnterCriticalSection (&condvar_crit
);
1612 pWakeConditionVariable (&condvar_base
);
1614 LeaveCriticalSection (&condvar_crit
);
1616 /* skip over remaining tests if InitializeSRWLock is not available */
1617 if (!pInitializeSRWLock
)
1620 while (condvar_seq
< 9) Sleep(1);
1621 pAcquireSRWLockExclusive(&condvar_srwlock
);
1622 pWakeConditionVariable(&condvar_base
);
1623 pReleaseSRWLockExclusive(&condvar_srwlock
);
1625 while (condvar_seq
< 10) Sleep(1);
1626 pAcquireSRWLockExclusive(&condvar_srwlock
);
1627 pWakeConditionVariable(&condvar_base
);
1628 pReleaseSRWLockExclusive(&condvar_srwlock
);
1630 while (condvar_seq
< 11) Sleep(1);
1631 pAcquireSRWLockShared(&condvar_srwlock
);
1632 pWakeConditionVariable(&condvar_base
);
1633 pReleaseSRWLockShared(&condvar_srwlock
);
1635 while (condvar_seq
< 12) Sleep(1);
1636 Sleep(50); /* ensure that consumer waits for cond variable */
1637 pAcquireSRWLockShared(&condvar_srwlock
);
1638 pWakeConditionVariable(&condvar_base
);
1639 pReleaseSRWLockShared(&condvar_srwlock
);
1644 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1647 while (condvar_seq
< 2) Sleep(1);
1649 /* wake was emitted, but we were not sleeping */
1650 EnterCriticalSection (&condvar_crit
);
1651 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1652 LeaveCriticalSection (&condvar_crit
);
1653 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1654 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1657 while (condvar_seq
< 4) Sleep(1);
1659 /* wake all was emitted, but we were not sleeping */
1660 EnterCriticalSection (&condvar_crit
);
1661 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1662 LeaveCriticalSection (&condvar_crit
);
1663 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1664 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1666 EnterCriticalSection (&condvar_crit
);
1668 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1669 LeaveCriticalSection (&condvar_crit
);
1670 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1672 EnterCriticalSection (&condvar_crit
);
1674 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1675 LeaveCriticalSection (&condvar_crit
);
1676 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1679 EnterCriticalSection (&condvar_crit
);
1680 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1681 LeaveCriticalSection (&condvar_crit
);
1682 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1683 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1685 EnterCriticalSection (&condvar_crit
);
1687 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1688 LeaveCriticalSection (&condvar_crit
);
1689 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1691 /* skip over remaining tests if InitializeSRWLock is not available */
1692 if (!pInitializeSRWLock
)
1694 win_skip("no srw lock support.\n");
1695 condvar_seq
= 13; /* end */
1699 pAcquireSRWLockExclusive(&condvar_srwlock
);
1701 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1702 pReleaseSRWLockExclusive(&condvar_srwlock
);
1703 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1705 pAcquireSRWLockShared(&condvar_srwlock
);
1707 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1708 pReleaseSRWLockShared(&condvar_srwlock
);
1709 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1711 pAcquireSRWLockExclusive(&condvar_srwlock
);
1713 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1714 pReleaseSRWLockExclusive(&condvar_srwlock
);
1715 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1717 pAcquireSRWLockShared(&condvar_srwlock
);
1719 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1720 pReleaseSRWLockShared(&condvar_srwlock
);
1721 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1727 static void test_condvars_base(void) {
1733 if (!pInitializeConditionVariable
) {
1734 /* function is not yet in XP, only in newer Windows */
1735 win_skip("no condition variable support.\n");
1739 InitializeCriticalSection (&condvar_crit
);
1741 if (pInitializeSRWLock
)
1742 pInitializeSRWLock(&condvar_srwlock
);
1744 EnterCriticalSection (&condvar_crit
);
1745 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1746 LeaveCriticalSection (&condvar_crit
);
1748 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1749 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1751 if (pInitializeSRWLock
)
1753 pAcquireSRWLockExclusive(&condvar_srwlock
);
1754 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1755 pReleaseSRWLockExclusive(&condvar_srwlock
);
1757 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1758 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1760 pAcquireSRWLockShared(&condvar_srwlock
);
1761 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1762 pReleaseSRWLockShared(&condvar_srwlock
);
1764 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1765 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1769 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1770 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1772 condvar_seq
= 1; /* go */
1774 while (condvar_seq
< 9)
1776 WaitForSingleObject(hp
, 100);
1777 WaitForSingleObject(hc
, 100);
1780 static LONG srwlock_seq
= 0;
1781 static SRWLOCK srwlock_base
;
1784 LONG wrong_execution_order
;
1785 LONG samethread_excl_excl
;
1786 LONG samethread_excl_shared
;
1787 LONG samethread_shared_excl
;
1788 LONG multithread_excl_excl
;
1789 LONG excl_not_preferred
;
1791 LONG trylock_shared
;
1792 } srwlock_base_errors
;
1794 /* Sequence of acquire/release to check boundary conditions:
1797 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1798 * 2: thread1 expects a deadlock and releases the waiting lock
1799 * thread2 releases the lock again
1801 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1802 * 4: thread1 expects a deadlock and releases the waiting lock
1803 * thread2 releases the lock again
1805 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1806 * 6: thread1 expects a deadlock and releases the waiting lock
1807 * thread2 releases the lock again
1809 * 7: thread2 acquires and releases two nested shared locks
1811 * 8: thread1 acquires an exclusive lock
1812 * 9: thread2 tries to acquire the exclusive lock, too
1813 * thread1 releases the exclusive lock again
1814 * 10: thread2 enters the exclusive lock and leaves it immediately again
1816 * 11: thread1 acquires a shared lock
1817 * 12: thread2 acquires and releases a shared lock
1818 * thread1 releases the lock again
1820 * 13: thread1 acquires a shared lock
1821 * 14: thread2 tries to acquire an exclusive lock
1822 * 15: thread3 tries to acquire a shared lock
1823 * 16: thread1 releases the shared lock
1824 * 17: thread2 wakes up and releases the exclusive lock
1825 * 18: thread3 wakes up and releases the shared lock
1827 * the following tests will only be executed if TryAcquireSRWLock* is available
1829 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1830 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1831 * thread1 releases the exclusive lock
1833 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1834 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1835 * thread1 releases the shared lock
1837 * thread1 acquires an exclusive lock
1838 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1839 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1840 * 21: thread1 releases the exclusive lock
1842 * thread1 acquires an shared lock
1843 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
1844 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1845 * 23: thread1 releases the shared lock
1847 * thread1 acquires a shared lock and tries to acquire an exclusive lock
1848 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
1849 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1850 * 25: thread1 releases the exclusive lock
1852 * thread1 acquires two shared locks
1853 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
1854 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1855 * 27: thread1 releases one shared lock
1856 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
1857 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1858 * 29: thread1 releases the second shared lock
1859 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
1860 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
1865 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
1868 while (srwlock_seq
< 2) Sleep(1);
1870 if (InterlockedIncrement(&srwlock_seq
) != 3)
1871 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
1872 pReleaseSRWLockExclusive(&srwlock_base
);
1875 while (srwlock_seq
< 4) Sleep(1);
1877 if (InterlockedIncrement(&srwlock_seq
) != 5)
1878 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
1879 pReleaseSRWLockExclusive(&srwlock_base
);
1882 while (srwlock_seq
< 6) Sleep(1);
1884 if (InterlockedIncrement(&srwlock_seq
) != 7)
1885 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
1886 pReleaseSRWLockShared(&srwlock_base
);
1889 while (srwlock_seq
< 8) Sleep(1);
1890 pAcquireSRWLockExclusive(&srwlock_base
);
1891 if (InterlockedIncrement(&srwlock_seq
) != 9)
1892 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1894 if (InterlockedIncrement(&srwlock_seq
) != 10)
1895 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
1896 pReleaseSRWLockExclusive(&srwlock_base
);
1899 while (srwlock_seq
< 11) Sleep(1);
1900 pAcquireSRWLockShared(&srwlock_base
);
1901 if (InterlockedIncrement(&srwlock_seq
) != 12)
1902 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1905 while (srwlock_seq
< 13) Sleep(1);
1906 pReleaseSRWLockShared(&srwlock_base
);
1907 pAcquireSRWLockShared(&srwlock_base
);
1908 if (InterlockedIncrement(&srwlock_seq
) != 14)
1909 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1912 while (srwlock_seq
< 16) Sleep(1);
1913 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
1914 if (InterlockedIncrement(&srwlock_seq
) != 17)
1915 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1916 pReleaseSRWLockShared(&srwlock_base
);
1918 /* skip over remaining tests if TryAcquireSRWLock* is not available */
1919 if (!pTryAcquireSRWLockExclusive
)
1923 while (srwlock_seq
< 19) Sleep(1);
1924 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1926 if (pTryAcquireSRWLockShared(&srwlock_base
))
1927 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1928 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1929 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1930 pReleaseSRWLockExclusive(&srwlock_base
);
1933 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1935 if (pTryAcquireSRWLockShared(&srwlock_base
))
1937 if (pTryAcquireSRWLockShared(&srwlock_base
))
1938 pReleaseSRWLockShared(&srwlock_base
);
1940 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1941 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1942 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1943 pReleaseSRWLockShared(&srwlock_base
);
1946 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1948 pAcquireSRWLockExclusive(&srwlock_base
);
1949 if (InterlockedIncrement(&srwlock_seq
) != 20)
1950 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1953 while (srwlock_seq
< 21) Sleep(1);
1954 pReleaseSRWLockExclusive(&srwlock_base
);
1955 pAcquireSRWLockShared(&srwlock_base
);
1956 if (InterlockedIncrement(&srwlock_seq
) != 22)
1957 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1960 while (srwlock_seq
< 23) Sleep(1);
1961 pReleaseSRWLockShared(&srwlock_base
);
1962 pAcquireSRWLockShared(&srwlock_base
);
1963 if (InterlockedIncrement(&srwlock_seq
) != 24)
1964 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1967 pAcquireSRWLockExclusive(&srwlock_base
);
1968 if (srwlock_seq
!= 25)
1969 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1970 pReleaseSRWLockExclusive(&srwlock_base
);
1972 pAcquireSRWLockShared(&srwlock_base
);
1973 pAcquireSRWLockShared(&srwlock_base
);
1974 if (InterlockedIncrement(&srwlock_seq
) != 26)
1975 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1978 while (srwlock_seq
< 27) Sleep(1);
1979 pReleaseSRWLockShared(&srwlock_base
);
1980 if (InterlockedIncrement(&srwlock_seq
) != 28)
1981 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1984 while (srwlock_seq
< 29) Sleep(1);
1985 pReleaseSRWLockShared(&srwlock_base
);
1986 if (InterlockedIncrement(&srwlock_seq
) != 30)
1987 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1992 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
1995 while (srwlock_seq
< 1) Sleep(1);
1996 pAcquireSRWLockExclusive(&srwlock_base
);
1997 if (InterlockedIncrement(&srwlock_seq
) != 2)
1998 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2001 pAcquireSRWLockExclusive(&srwlock_base
);
2002 if (srwlock_seq
!= 3)
2003 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2004 pReleaseSRWLockExclusive(&srwlock_base
);
2005 pAcquireSRWLockExclusive(&srwlock_base
);
2006 if (InterlockedIncrement(&srwlock_seq
) != 4)
2007 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2010 pAcquireSRWLockShared(&srwlock_base
);
2011 if (srwlock_seq
!= 5)
2012 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2013 pReleaseSRWLockShared(&srwlock_base
);
2014 pAcquireSRWLockShared(&srwlock_base
);
2015 if (InterlockedIncrement(&srwlock_seq
) != 6)
2016 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2019 pAcquireSRWLockExclusive(&srwlock_base
);
2020 if (srwlock_seq
!= 7)
2021 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2022 pReleaseSRWLockExclusive(&srwlock_base
);
2023 pAcquireSRWLockShared(&srwlock_base
);
2024 pAcquireSRWLockShared(&srwlock_base
);
2025 pReleaseSRWLockShared(&srwlock_base
);
2026 pReleaseSRWLockShared(&srwlock_base
);
2027 if (InterlockedIncrement(&srwlock_seq
) != 8)
2028 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2031 while (srwlock_seq
< 9) Sleep(1);
2032 pAcquireSRWLockExclusive(&srwlock_base
);
2033 if (srwlock_seq
!= 10)
2034 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2035 pReleaseSRWLockExclusive(&srwlock_base
);
2036 if (InterlockedIncrement(&srwlock_seq
) != 11)
2037 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2040 while (srwlock_seq
< 12) Sleep(1);
2041 pAcquireSRWLockShared(&srwlock_base
);
2042 pReleaseSRWLockShared(&srwlock_base
);
2043 if (InterlockedIncrement(&srwlock_seq
) != 13)
2044 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2047 while (srwlock_seq
< 14) Sleep(1);
2048 if (InterlockedIncrement(&srwlock_seq
) != 15)
2049 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2052 pAcquireSRWLockExclusive(&srwlock_base
);
2053 if (srwlock_seq
!= 17)
2054 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2055 if (InterlockedIncrement(&srwlock_seq
) != 18)
2056 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2057 pReleaseSRWLockExclusive(&srwlock_base
);
2059 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2060 if (!pTryAcquireSRWLockExclusive
)
2064 while (srwlock_seq
< 20) Sleep(1);
2065 if (pTryAcquireSRWLockShared(&srwlock_base
))
2066 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2067 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2068 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2069 if (InterlockedIncrement(&srwlock_seq
) != 21)
2070 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2073 while (srwlock_seq
< 22) Sleep(1);
2074 if (pTryAcquireSRWLockShared(&srwlock_base
))
2075 pReleaseSRWLockShared(&srwlock_base
);
2077 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2078 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2079 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2080 if (InterlockedIncrement(&srwlock_seq
) != 23)
2081 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2084 while (srwlock_seq
< 24) Sleep(1);
2085 Sleep(50); /* ensure that exclusive access request is queued */
2086 if (pTryAcquireSRWLockShared(&srwlock_base
))
2088 pReleaseSRWLockShared(&srwlock_base
);
2089 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2091 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2092 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2093 if (InterlockedIncrement(&srwlock_seq
) != 25)
2094 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2095 pReleaseSRWLockShared(&srwlock_base
);
2098 while (srwlock_seq
< 26) Sleep(1);
2099 if (pTryAcquireSRWLockShared(&srwlock_base
))
2100 pReleaseSRWLockShared(&srwlock_base
);
2102 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2103 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2104 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2105 if (InterlockedIncrement(&srwlock_seq
) != 27)
2106 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2109 while (srwlock_seq
< 28) Sleep(1);
2110 if (pTryAcquireSRWLockShared(&srwlock_base
))
2111 pReleaseSRWLockShared(&srwlock_base
);
2113 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2114 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2115 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2116 if (InterlockedIncrement(&srwlock_seq
) != 29)
2117 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2120 while (srwlock_seq
< 30) Sleep(1);
2121 if (pTryAcquireSRWLockShared(&srwlock_base
))
2122 pReleaseSRWLockShared(&srwlock_base
);
2124 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2125 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2126 pReleaseSRWLockExclusive(&srwlock_base
);
2128 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2129 if (InterlockedIncrement(&srwlock_seq
) != 31)
2130 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2135 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2138 while (srwlock_seq
< 15) Sleep(1);
2139 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2140 if (InterlockedIncrement(&srwlock_seq
) != 16)
2141 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2144 pAcquireSRWLockShared(&srwlock_base
);
2145 if (srwlock_seq
!= 18)
2146 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2147 pReleaseSRWLockShared(&srwlock_base
);
2148 if (InterlockedIncrement(&srwlock_seq
) != 19)
2149 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2151 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2152 if (!pTryAcquireSRWLockExclusive
)
2154 /* function is only in Windows 7 and newer */
2155 win_skip("no srw trylock support.\n");
2156 srwlock_seq
= 31; /* end */
2163 static void test_srwlock_base(void)
2168 if (!pInitializeSRWLock
)
2170 /* function is not yet in XP, only in newer Windows */
2171 win_skip("no srw lock support.\n");
2175 pInitializeSRWLock(&srwlock_base
);
2176 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2178 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2179 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2180 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2182 srwlock_seq
= 1; /* go */
2183 while (srwlock_seq
< 31)
2186 WaitForSingleObject(h1
, 100);
2187 WaitForSingleObject(h2
, 100);
2188 WaitForSingleObject(h3
, 100);
2190 ok(!srwlock_base_errors
.wrong_execution_order
,
2191 "thread commands were executed in the wrong order (occurred %d times).\n",
2192 srwlock_base_errors
.wrong_execution_order
);
2194 ok(!srwlock_base_errors
.samethread_excl_excl
,
2195 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2196 srwlock_base_errors
.samethread_excl_excl
);
2198 ok(!srwlock_base_errors
.samethread_excl_shared
,
2199 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2200 srwlock_base_errors
.samethread_excl_shared
);
2202 ok(!srwlock_base_errors
.samethread_shared_excl
,
2203 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2204 srwlock_base_errors
.samethread_shared_excl
);
2206 ok(!srwlock_base_errors
.multithread_excl_excl
,
2207 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2208 srwlock_base_errors
.multithread_excl_excl
);
2210 ok(!srwlock_base_errors
.excl_not_preferred
,
2211 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2212 srwlock_base_errors
.excl_not_preferred
);
2214 ok(!srwlock_base_errors
.trylock_excl
,
2215 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2216 srwlock_base_errors
.trylock_excl
);
2218 ok(!srwlock_base_errors
.trylock_shared
,
2219 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2220 srwlock_base_errors
.trylock_shared
);
2224 static SRWLOCK srwlock_example
;
2225 static LONG srwlock_protected_value
= 0;
2226 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2227 static BOOL srwlock_stop
= FALSE
;
2229 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2233 while (!srwlock_stop
)
2236 /* periodically request exclusive access */
2237 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2239 pAcquireSRWLockExclusive(&srwlock_example
);
2240 if (InterlockedIncrement(&srwlock_inside
) != 1)
2241 InterlockedIncrement(&srwlock_example_errors
);
2243 InterlockedIncrement(&srwlock_protected_value
);
2246 if (InterlockedDecrement(&srwlock_inside
) != 0)
2247 InterlockedIncrement(&srwlock_example_errors
);
2248 pReleaseSRWLockExclusive(&srwlock_example
);
2251 /* request shared access */
2252 pAcquireSRWLockShared(&srwlock_example
);
2253 InterlockedIncrement(&srwlock_inside
);
2254 old
= srwlock_protected_value
;
2259 if (old
!= srwlock_protected_value
)
2260 InterlockedIncrement(&srwlock_example_errors
);
2261 InterlockedDecrement(&srwlock_inside
);
2262 pReleaseSRWLockShared(&srwlock_example
);
2268 static void test_srwlock_example(void)
2272 DWORD cnt1
, cnt2
, cnt3
;
2274 if (!pInitializeSRWLock
) {
2275 /* function is not yet in XP, only in newer Windows */
2276 win_skip("no srw lock support.\n");
2280 pInitializeSRWLock(&srwlock_example
);
2282 cnt1
= cnt2
= cnt3
= 0;
2284 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2285 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2286 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2288 /* limit run to 1 second. */
2291 /* tear down start */
2292 srwlock_stop
= TRUE
;
2294 WaitForSingleObject(h1
, 1000);
2295 WaitForSingleObject(h2
, 1000);
2296 WaitForSingleObject(h3
, 1000);
2298 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2299 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2300 srwlock_example_errors
);
2302 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2303 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2308 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2309 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2311 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
2312 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
2313 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
2314 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
2315 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
2316 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
2317 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
2318 pCreateMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "CreateMemoryResourceNotification");
2319 pQueryMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "QueryMemoryResourceNotification");
2320 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2321 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2322 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2323 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2324 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2325 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2326 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2327 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2328 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2329 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2330 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2331 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2332 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2333 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2334 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2335 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2336 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2338 test_signalandwait();
2343 test_waitable_timer();
2344 test_iocp_callback();
2346 test_WaitForSingleObject();
2347 test_WaitForMultipleObjects();
2349 test_condvars_base();
2350 test_condvars_consumer_producer();
2351 test_srwlock_base();
2352 test_srwlock_example();