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
28 #include "wine/test.h"
30 static BOOL (WINAPI
*pChangeTimerQueueTimer
)(HANDLE
, HANDLE
, ULONG
, ULONG
);
31 static HANDLE (WINAPI
*pCreateTimerQueue
)(void);
32 static BOOL (WINAPI
*pCreateTimerQueueTimer
)(PHANDLE
, HANDLE
, WAITORTIMERCALLBACK
,
33 PVOID
, DWORD
, DWORD
, ULONG
);
34 static HANDLE (WINAPI
*pCreateWaitableTimerA
)(SECURITY_ATTRIBUTES
*,BOOL
,LPCSTR
);
35 static BOOL (WINAPI
*pDeleteTimerQueueEx
)(HANDLE
, HANDLE
);
36 static BOOL (WINAPI
*pDeleteTimerQueueTimer
)(HANDLE
, HANDLE
, HANDLE
);
37 static HANDLE (WINAPI
*pOpenWaitableTimerA
)(DWORD
,BOOL
,LPCSTR
);
38 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
39 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
40 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
41 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
42 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
43 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
45 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
46 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
47 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
48 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
49 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
51 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
52 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
53 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
54 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
55 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
56 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
57 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
59 static void test_signalandwait(void)
61 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
64 HANDLE event
[2], semaphore
[2], file
;
66 kernel32
= GetModuleHandleA("kernel32.dll");
67 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
69 if (!pSignalObjectAndWait
)
72 /* invalid parameters */
73 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
74 if (r
== ERROR_INVALID_FUNCTION
)
76 win_skip("SignalObjectAndWait is not implemented\n");
77 return; /* Win98/ME */
79 ok( r
== WAIT_FAILED
, "should fail\n");
81 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
82 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
84 ok( event
[0] && event
[1], "failed to create event flags\n");
86 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
87 ok( r
== WAIT_FAILED
, "should fail\n");
89 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
90 ok( r
== WAIT_FAILED
, "should fail\n");
93 /* valid parameters */
94 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
95 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
97 /* event[0] is now signalled */
98 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
99 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
101 /* event[0] is not signalled */
102 r
= WaitForSingleObject(event
[0], 0);
103 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
105 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
106 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
108 /* clear event[1] and check for a timeout */
109 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
110 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
111 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
113 CloseHandle(event
[0]);
114 CloseHandle(event
[1]);
117 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
118 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
119 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
121 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
122 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
124 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
125 ok( r
== WAIT_FAILED
, "should fail\n");
127 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
128 ok( r
== FALSE
, "should fail\n");
130 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
131 ok( r
== TRUE
, "should succeed\n");
133 CloseHandle(semaphore
[0]);
134 CloseHandle(semaphore
[1]);
136 /* try a registry key */
137 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
138 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
139 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
140 ok( r
== WAIT_FAILED
, "should fail\n");
141 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
145 static void test_mutex(void)
154 SetLastError(0xdeadbeef);
155 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
156 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
157 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
159 SetLastError(0xdeadbeef);
160 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
161 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
163 SetLastError(0xdeadbeef);
164 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
166 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
168 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
170 SetLastError(0xdeadbeef);
171 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
172 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
173 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
174 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
175 CloseHandle(hOpened
);
177 for(i
=0; i
< 31; i
++)
179 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
180 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
183 SetLastError(0xdeadbeef);
184 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
185 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
186 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
187 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
188 CloseHandle(hOpened
);
190 for (i
= 0; i
< 32; i
++)
192 SetLastError(0xdeadbeef);
193 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
196 SetLastError(0xdeadbeef);
197 ret
= ReleaseMutex(hOpened
);
198 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
199 CloseHandle(hOpened
);
203 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
204 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
206 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
207 ReleaseMutex(hCreated
);
213 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
215 SetLastError(0xdeadbeef);
216 ret
= ReleaseMutex(hCreated
);
217 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
218 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
220 /* test case sensitivity */
222 SetLastError(0xdeadbeef);
223 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
224 ok(!hOpened
, "OpenMutex succeeded\n");
225 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
227 SetLastError(0xdeadbeef);
228 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
229 ok(!hOpened
, "OpenMutex succeeded\n");
230 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
232 SetLastError(0xdeadbeef);
233 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
234 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
235 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
236 CloseHandle(hOpened
);
238 SetLastError(0xdeadbeef);
239 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
240 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
241 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
242 CloseHandle(hOpened
);
244 CloseHandle(hCreated
);
247 static void test_slist(void)
253 } item1
, item2
, item3
, *pitem
;
255 SLIST_HEADER slist_header
;
256 PSLIST_ENTRY entry
, next
;
260 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
261 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
262 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
263 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
264 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
267 kernel32
= GetModuleHandleA("KERNEL32.DLL");
268 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
269 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
270 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
271 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
272 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
273 if (pInitializeSListHead
== NULL
||
274 pQueryDepthSList
== NULL
||
275 pInterlockedFlushSList
== NULL
||
276 pInterlockedPopEntrySList
== NULL
||
277 pInterlockedPushEntrySList
== NULL
)
279 win_skip("some required slist entrypoints were not found, skipping tests\n");
283 memset(&slist_header
, 0xFF, sizeof(slist_header
));
284 pInitializeSListHead(&slist_header
);
285 size
= pQueryDepthSList(&slist_header
);
286 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
289 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
290 "previous entry in empty slist wasn't NULL\n");
291 size
= pQueryDepthSList(&slist_header
);
292 ok(size
== 1, "slist with 1 item has size %d\n", size
);
295 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
296 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
299 pitem
= (struct item
*) entry
;
300 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
302 size
= pQueryDepthSList(&slist_header
);
303 ok(size
== 2, "slist with 2 items has size %d\n", size
);
306 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
307 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
310 pitem
= (struct item
*) entry
;
311 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
313 size
= pQueryDepthSList(&slist_header
);
314 ok(size
== 3, "slist with 3 items has size %d\n", size
);
316 entry
= pInterlockedPopEntrySList(&slist_header
);
317 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
320 pitem
= (struct item
*) entry
;
321 ok(pitem
->value
== 3, "unexpected entry removed\n");
323 size
= pQueryDepthSList(&slist_header
);
324 ok(size
== 2, "slist with 2 items has size %d\n", size
);
326 entry
= pInterlockedFlushSList(&slist_header
);
327 size
= pQueryDepthSList(&slist_header
);
328 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
331 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
332 "popping empty slist didn't return NULL\n");
334 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
335 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
337 for (i
= 0; i
< 65536; i
++)
339 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
340 pInterlockedPushEntrySList(&slist_header
, entry
);
343 entry
= pInterlockedFlushSList(&slist_header
);
344 ok(entry
!= NULL
, "not flushed\n");
348 HeapFree(GetProcessHeap(), 0, entry
);
353 static void test_event(void)
355 HANDLE handle
, handle2
;
356 SECURITY_ATTRIBUTES sa
;
357 SECURITY_DESCRIPTOR sd
;
363 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
364 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
367 sa
.nLength
= sizeof(sa
);
368 sa
.lpSecurityDescriptor
= &sd
;
369 sa
.bInheritHandle
= FALSE
;
371 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
374 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
375 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
378 /* sd with NULL dacl */
379 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
380 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
381 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
384 /* sd with empty dacl */
385 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
386 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
387 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
388 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
391 /* test case sensitivity */
393 SetLastError(0xdeadbeef);
394 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
395 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
396 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
398 SetLastError(0xdeadbeef);
399 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
400 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
401 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
402 CloseHandle( handle2
);
404 SetLastError(0xdeadbeef);
405 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
406 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
407 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
408 CloseHandle( handle2
);
410 SetLastError(0xdeadbeef);
411 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
412 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
413 CloseHandle( handle2
);
415 SetLastError(0xdeadbeef);
416 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
417 ok( !handle2
, "OpenEvent succeeded\n");
418 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
420 CloseHandle( handle
);
422 /* resource notifications are events too */
424 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
426 trace( "memory resource notifications not supported\n" );
429 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
430 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
431 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
432 ret
= pQueryMemoryResourceNotification( handle
, &val
);
433 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
434 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
436 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
437 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
438 ret
= WaitForSingleObject( handle
, 10 );
439 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
442 ret
= pQueryMemoryResourceNotification( handle
, &val
);
443 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
444 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
445 ret
= CloseHandle( handle
);
446 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
448 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
450 ret
= pQueryMemoryResourceNotification( handle
, &val
);
451 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
452 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
453 CloseHandle( handle
);
456 static void test_semaphore(void)
458 HANDLE handle
, handle2
;
460 /* test case sensitivity */
462 SetLastError(0xdeadbeef);
463 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
464 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
465 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
467 SetLastError(0xdeadbeef);
468 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
469 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
470 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
471 CloseHandle( handle2
);
473 SetLastError(0xdeadbeef);
474 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
475 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
476 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
477 CloseHandle( handle2
);
479 SetLastError(0xdeadbeef);
480 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
481 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
482 CloseHandle( handle2
);
484 SetLastError(0xdeadbeef);
485 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
486 ok( !handle2
, "OpenSemaphore succeeded\n");
487 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
489 CloseHandle( handle
);
492 static void test_waitable_timer(void)
494 HANDLE handle
, handle2
;
496 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
498 win_skip("{Create,Open}WaitableTimerA() is not available\n");
502 /* test case sensitivity */
504 SetLastError(0xdeadbeef);
505 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
506 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
507 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
509 SetLastError(0xdeadbeef);
510 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
511 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
512 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
513 CloseHandle( handle2
);
515 SetLastError(0xdeadbeef);
516 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
517 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
518 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
519 CloseHandle( handle2
);
521 SetLastError(0xdeadbeef);
522 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
523 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
524 CloseHandle( handle2
);
526 SetLastError(0xdeadbeef);
527 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
528 ok( !handle2
, "OpenWaitableTimer succeeded\n");
529 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
530 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
531 "wrong error %u\n", GetLastError());
533 CloseHandle( handle
);
536 static HANDLE sem
= 0;
538 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
540 ReleaseSemaphore(sem
, 1, NULL
);
543 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
545 static void test_iocp_callback(void)
547 char temp_path
[MAX_PATH
];
548 char filename
[MAX_PATH
];
551 static const char prefix
[] = "pfx";
553 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
555 const char *buffer
= "12345678123456781234567812345678";
556 OVERLAPPED overlapped
;
558 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
559 if(!p_BindIoCompletionCallback
) {
560 win_skip("BindIoCompletionCallback not found in this DLL\n");
564 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
565 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
567 ret
= GetTempPathA(MAX_PATH
, temp_path
);
568 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
569 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
571 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
572 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
574 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
575 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
576 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
578 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
579 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
580 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
582 ret
= CloseHandle(hFile
);
583 ok( ret
, "CloseHandle: error %d\n", GetLastError());
584 ret
= DeleteFileA(filename
);
585 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
587 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
588 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
589 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
591 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
592 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
594 memset(&overlapped
, 0, sizeof(overlapped
));
595 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
596 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
598 ret
= WaitForSingleObject(sem
, 5000);
599 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
602 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
603 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
604 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
605 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
606 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
607 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
609 ret
= CloseHandle(hFile
);
610 ok( ret
, "CloseHandle: error %d\n", GetLastError());
611 ret
= DeleteFileA(filename
);
612 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
614 /* win2k3 requires the Flags parameter to be zero */
615 SetLastError(0xdeadbeef);
616 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
617 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
618 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
619 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
621 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
622 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
624 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
625 ret
= CloseHandle(hFile
);
626 ok( ret
, "CloseHandle: error %d\n", GetLastError());
627 ret
= DeleteFileA(filename
);
628 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
630 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
631 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
632 ok(GetLastError() == ERROR_INVALID_HANDLE
||
633 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
634 "Last error is %d\n", GetLastError());
637 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
640 ok(timedOut
, "Timer callbacks should always time out\n");
644 struct timer_queue_data1
651 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
653 struct timer_queue_data1
*d
= p
;
654 ok(timedOut
, "Timer callbacks should always time out\n");
655 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
658 SetLastError(0xdeadbeef);
659 /* Note, XP SP2 does *not* do any deadlock checking, so passing
660 INVALID_HANDLE_VALUE here will just hang. */
661 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
662 ok(!ret
, "DeleteTimerQueueTimer\n");
663 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
667 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
669 struct timer_queue_data1
*d
= p
;
670 ok(timedOut
, "Timer callbacks should always time out\n");
671 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
673 /* Basically kill the timer since it won't have time to run
675 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
676 ok(ret
, "ChangeTimerQueueTimer\n");
680 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
682 struct timer_queue_data1
*d
= p
;
683 ok(timedOut
, "Timer callbacks should always time out\n");
686 /* This tests whether a timer gets flagged for deletion before
687 or after the callback runs. If we start this timer with a
688 period of zero (run once), then ChangeTimerQueueTimer will
689 fail if the timer is already flagged. Hence we really run
690 only once. Otherwise we will run multiple times. */
691 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
692 ok(ret
, "ChangeTimerQueueTimer\n");
697 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
699 DWORD_PTR delay
= (DWORD_PTR
) p
;
700 ok(timedOut
, "Timer callbacks should always time out\n");
705 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
707 struct timer_queue_data1
*d
= p
;
708 ok(timedOut
, "Timer callbacks should always time out\n");
709 /* This tests an original implementation bug where a deleted timer may get
710 to run, but it is tricky to set up. */
711 if (d
->q
&& d
->num_calls
++ == 0)
713 /* First run: delete ourselves, then insert and remove a timer
714 that goes in front of us in the sorted timeout list. Once
715 removed, we will still timeout at the faster timer's due time,
716 but this should be a no-op if we are bug-free. There should
717 not be a second run. We can test the value of num_calls later. */
721 /* The delete will pend while we are in this callback. */
722 SetLastError(0xdeadbeef);
723 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
724 ok(!ret
, "DeleteTimerQueueTimer\n");
725 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
727 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
728 ok(ret
, "CreateTimerQueueTimer\n");
729 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
731 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
732 ok(ret
, "DeleteTimerQueueTimer\n");
734 /* Now we stay alive by hanging around in the callback. */
739 static void test_timer_queue(void)
741 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
742 int n0
, n1
, n2
, n3
, n4
, n5
;
743 struct timer_queue_data1 d1
, d2
, d3
, d4
;
747 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
748 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
750 win_skip("TimerQueue API not present\n");
754 /* Test asynchronous deletion of the queue. */
755 q
= pCreateTimerQueue();
756 ok(q
!= NULL
, "CreateTimerQueue\n");
758 SetLastError(0xdeadbeef);
759 ret
= pDeleteTimerQueueEx(q
, NULL
);
760 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
761 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
764 /* Test synchronous deletion of the queue and running timers. */
765 q
= pCreateTimerQueue();
766 ok(q
!= NULL
, "CreateTimerQueue\n");
771 ret
= pCreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0,
773 ok(ret
, "CreateTimerQueueTimer\n");
774 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
775 ret0
= pDeleteTimerQueueTimer(q
, t0
, NULL
);
776 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
777 broken(ret0
), /* Win 2000 & XP & 2003 */
778 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
783 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
785 ok(ret
, "CreateTimerQueueTimer\n");
786 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
791 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
793 ok(ret
, "CreateTimerQueueTimer\n");
794 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
799 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
801 ok(ret
, "CreateTimerQueueTimer\n");
802 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
804 /* Start really late (it won't start). */
807 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
809 ok(ret
, "CreateTimerQueueTimer\n");
810 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
812 /* Start soon, but delay so long it won't run again. */
815 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
817 ok(ret
, "CreateTimerQueueTimer\n");
818 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
820 /* Give them a chance to do some work. */
823 /* Test deleting a once-only timer. */
824 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
825 ok(ret
, "DeleteTimerQueueTimer\n");
827 /* A periodic timer. */
828 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
829 ok(ret
, "DeleteTimerQueueTimer\n");
831 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
832 ok(ret
, "DeleteTimerQueueEx\n");
834 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
835 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
836 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
837 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
838 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
840 /* Test synchronous deletion of the timer/queue with event trigger. */
841 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
842 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
843 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
844 if (!e
|| !et1
|| !et2
)
846 skip("Failed to create timer queue descruction event\n");
850 q
= pCreateTimerQueue();
851 ok(q
!= NULL
, "CreateTimerQueue\n");
853 /* Run once and finish quickly (should be done when we delete it). */
855 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
856 ok(ret
, "CreateTimerQueueTimer\n");
857 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
859 /* Run once and finish slowly (shouldn't be done when we delete it). */
861 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
863 ok(ret
, "CreateTimerQueueTimer\n");
864 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
866 /* Run once and finish quickly (should be done when we delete it). */
868 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
869 ok(ret
, "CreateTimerQueueTimer\n");
870 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
872 /* Run once and finish slowly (shouldn't be done when we delete it). */
874 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
876 ok(ret
, "CreateTimerQueueTimer\n");
877 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
879 /* Give them a chance to start. */
882 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
883 even if the timer is finished. */
884 SetLastError(0xdeadbeef);
885 ret
= pDeleteTimerQueueTimer(q
, t1
, NULL
);
886 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
887 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
890 SetLastError(0xdeadbeef);
891 ret
= pDeleteTimerQueueTimer(q
, t2
, NULL
);
892 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
893 ok(GetLastError() == ERROR_IO_PENDING
,
894 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
897 SetLastError(0xdeadbeef);
898 ret
= pDeleteTimerQueueTimer(q
, t3
, et1
);
899 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
900 ok(GetLastError() == 0xdeadbeef,
901 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
903 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
904 "Timer destruction event not triggered\n");
906 SetLastError(0xdeadbeef);
907 ret
= pDeleteTimerQueueTimer(q
, t4
, et2
);
908 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
909 ok(GetLastError() == ERROR_IO_PENDING
,
910 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
912 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
913 "Timer destruction event not triggered\n");
915 SetLastError(0xdeadbeef);
916 ret
= pDeleteTimerQueueEx(q
, e
);
917 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
918 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
920 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
921 "Queue destruction event not triggered\n");
924 /* Test deleting/changing a timer in execution. */
925 q
= pCreateTimerQueue();
926 ok(q
!= NULL
, "CreateTimerQueue\n");
928 /* Test changing a once-only timer before it fires (this is allowed,
929 whereas after it fires you cannot). */
931 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
933 ok(ret
, "CreateTimerQueueTimer\n");
934 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
935 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
936 ok(ret
, "ChangeTimerQueueTimer\n");
942 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
945 ok(ret
, "CreateTimerQueueTimer\n");
946 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
952 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
955 ok(ret
, "CreateTimerQueueTimer\n");
956 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
961 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
964 ok(ret
, "CreateTimerQueueTimer\n");
965 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
969 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
970 ok(ret
, "DeleteTimerQueueEx\n");
971 ok(n1
== 1, "ChangeTimerQueueTimer\n");
972 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
973 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
974 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
976 /* Test an obscure bug that was in the original implementation. */
977 q
= pCreateTimerQueue();
978 ok(q
!= NULL
, "CreateTimerQueue\n");
980 /* All the work is done in the callback. */
984 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
985 100, WT_EXECUTELONGFUNCTION
);
987 ok(ret
, "CreateTimerQueueTimer\n");
988 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
992 SetLastError(0xdeadbeef);
993 ret
= pDeleteTimerQueueEx(q
, NULL
);
994 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
995 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
997 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
999 /* Test functions on the default timer queue. */
1002 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
1004 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1005 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1007 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1008 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1010 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1011 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1013 /* Try mixing default and non-default queues. Apparently this works. */
1014 q
= pCreateTimerQueue();
1015 ok(q
!= NULL
, "CreateTimerQueue\n");
1019 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
1021 ok(ret
, "CreateTimerQueueTimer\n");
1022 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1026 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
1028 ok(ret
, "CreateTimerQueueTimer\n");
1029 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1031 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1032 ok(ret
, "ChangeTimerQueueTimer\n");
1034 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1035 ok(ret
, "ChangeTimerQueueTimer\n");
1037 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1038 ok(ret
, "DeleteTimerQueueTimer\n");
1040 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1041 ok(ret
, "DeleteTimerQueueTimer\n");
1043 /* Try to delete the default queue? In any case: not allowed. */
1044 SetLastError(0xdeadbeef);
1045 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
1046 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1047 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1048 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1051 SetLastError(0xdeadbeef);
1052 ret
= pDeleteTimerQueueEx(q
, NULL
);
1053 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1054 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1058 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1060 DWORD tmp
= HandleToULong(handle
);
1062 return ULongToHandle(tmp
);
1065 static void test_WaitForSingleObject(void)
1067 HANDLE signaled
, nonsignaled
, invalid
;
1070 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1071 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1072 invalid
= (HANDLE
) 0xdeadbee0;
1074 /* invalid handle with different values for lower 2 bits */
1075 SetLastError(0xdeadbeef);
1076 ret
= WaitForSingleObject(invalid
, 0);
1077 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1078 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1080 SetLastError(0xdeadbeef);
1081 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1082 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1083 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1085 SetLastError(0xdeadbeef);
1086 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1087 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1088 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1090 SetLastError(0xdeadbeef);
1091 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1092 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1093 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1095 /* valid handle with different values for lower 2 bits */
1096 SetLastError(0xdeadbeef);
1097 ret
= WaitForSingleObject(nonsignaled
, 0);
1098 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1099 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1101 SetLastError(0xdeadbeef);
1102 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1103 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1104 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1106 SetLastError(0xdeadbeef);
1107 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1108 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1109 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1111 SetLastError(0xdeadbeef);
1112 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1113 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1114 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1116 /* valid handle with different values for lower 2 bits */
1117 SetLastError(0xdeadbeef);
1118 ret
= WaitForSingleObject(signaled
, 0);
1119 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1120 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1122 SetLastError(0xdeadbeef);
1123 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1124 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1125 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1127 SetLastError(0xdeadbeef);
1128 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1129 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1130 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1132 SetLastError(0xdeadbeef);
1133 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1134 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1135 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1137 CloseHandle(signaled
);
1138 CloseHandle(nonsignaled
);
1141 static void test_WaitForMultipleObjects(void)
1145 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1147 /* create the maximum number of events and make sure
1148 * we can wait on that many */
1149 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1151 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1152 ok( maxevents
[i
] != 0, "should create enough events\n");
1155 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1156 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1157 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1158 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1159 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1160 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1161 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1163 /* the lowest index is checked first and remaining events are untouched */
1164 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1165 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1168 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1169 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1172 static BOOL g_initcallback_ret
, g_initcallback_called
;
1173 static void *g_initctxt
;
1175 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1177 g_initcallback_called
= TRUE
;
1178 /* zero bit set means here that initialization is taking place - initialization locked */
1179 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1180 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1181 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1182 return g_initcallback_ret
;
1185 static void test_initonce(void)
1190 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1192 win_skip("one-time initialization API not supported\n");
1196 /* blocking initialization with callback */
1197 initonce
.Ptr
= (void*)0xdeadbeef;
1198 pInitOnceInitialize(&initonce
);
1199 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1201 /* initialisation completed successfully */
1202 g_initcallback_ret
= TRUE
;
1204 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1205 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1206 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1207 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1208 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1210 /* so it's been called already so won't be called again */
1212 g_initcallback_called
= FALSE
;
1213 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1214 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1215 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1216 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1217 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1219 pInitOnceInitialize(&initonce
);
1220 g_initcallback_called
= FALSE
;
1221 /* 2 lower order bits should never be used, you'll get a crash in result */
1222 g_initctxt
= (void*)0xFFFFFFF0;
1223 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1224 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1225 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1226 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1227 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1229 /* callback failed */
1230 g_initcallback_ret
= FALSE
;
1231 g_initcallback_called
= FALSE
;
1233 pInitOnceInitialize(&initonce
);
1234 SetLastError( 0xdeadbeef );
1235 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1236 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1237 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1238 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1239 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1241 /* blocking initialization without a callback */
1242 pInitOnceInitialize(&initonce
);
1245 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1246 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1247 ok(pending
, "got %d\n", pending
);
1248 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1249 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1250 /* another attempt to begin initialization with block a single thread */
1254 SetLastError( 0xdeadbeef );
1255 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1256 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1257 ok(pending
== 0xf, "got %d\n", pending
);
1258 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1259 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1261 g_initctxt
= (void*)0xdeadbee0;
1262 SetLastError( 0xdeadbeef );
1263 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1264 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1265 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1267 /* once failed already */
1268 g_initctxt
= (void*)0xdeadbee0;
1269 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1270 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1271 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1273 pInitOnceInitialize(&initonce
);
1274 SetLastError( 0xdeadbeef );
1275 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1276 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1277 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1279 SetLastError( 0xdeadbeef );
1280 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1281 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1282 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1284 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1285 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1286 ok(pending
, "got %d\n", pending
);
1287 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1289 SetLastError( 0xdeadbeef );
1290 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1291 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1293 SetLastError( 0xdeadbeef );
1294 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1295 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1296 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1298 SetLastError( 0xdeadbeef );
1299 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1300 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1301 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1303 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1304 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1305 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1307 pInitOnceInitialize(&initonce
);
1308 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1309 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1310 ok(pending
, "got %d\n", pending
);
1311 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1313 SetLastError( 0xdeadbeef );
1314 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1315 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1317 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1318 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1319 ok(pending
, "got %d\n", pending
);
1320 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1322 SetLastError( 0xdeadbeef );
1323 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1324 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1325 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1327 SetLastError( 0xdeadbeef );
1328 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1329 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1330 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1332 SetLastError( 0xdeadbeef );
1333 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1334 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1335 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1337 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1338 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1339 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1341 SetLastError( 0xdeadbeef );
1342 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1343 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1344 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1346 pInitOnceInitialize(&initonce
);
1347 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1348 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1349 ok(pending
, "got %d\n", pending
);
1350 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1352 /* test INIT_ONCE_CHECK_ONLY */
1354 pInitOnceInitialize(&initonce
);
1355 SetLastError( 0xdeadbeef );
1356 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1357 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1358 SetLastError( 0xdeadbeef );
1359 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1360 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1362 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1363 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1364 ok(pending
, "got %d\n", pending
);
1365 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1367 SetLastError( 0xdeadbeef );
1368 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1369 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1370 SetLastError( 0xdeadbeef );
1371 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1372 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1374 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1375 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1376 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1378 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1379 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1380 ok(!pending
, "got %d\n", pending
);
1381 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1382 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1384 SetLastError( 0xdeadbeef );
1385 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1386 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1388 pInitOnceInitialize(&initonce
);
1389 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1390 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1391 ok(pending
, "got %d\n", pending
);
1392 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1394 SetLastError( 0xdeadbeef );
1395 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1396 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1397 SetLastError( 0xdeadbeef );
1398 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1399 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1401 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1402 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1403 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1405 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1406 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1407 ok(!pending
, "got %d\n", pending
);
1408 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1409 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1411 SetLastError( 0xdeadbeef );
1412 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1413 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1416 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1417 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1418 static CRITICAL_SECTION buffercrit
;
1419 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1420 static LONG bufferlen
,totalproduced
,totalconsumed
;
1421 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1423 #define BUFFER_SIZE 5
1425 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1426 DWORD sleepinterval
= 5;
1429 Sleep(sleepinterval
);
1430 if (sleepinterval
> 1)
1433 EnterCriticalSection(&buffercrit
);
1434 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1435 condvar_producer_sleepcnt
++;
1436 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1437 if (GetLastError() != ERROR_TIMEOUT
)
1438 condvar_sleeperr
= TRUE
;
1442 LeaveCriticalSection(&buffercrit
);
1447 LeaveCriticalSection(&buffercrit
);
1448 pWakeConditionVariable(&buffernotempty
);
1453 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1454 DWORD
*cnt
= (DWORD
*)x
;
1455 DWORD sleepinterval
= 1;
1458 EnterCriticalSection(&buffercrit
);
1459 while ((bufferlen
== 0) && !condvar_stop
) {
1460 condvar_consumer_sleepcnt
++;
1461 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1462 if (GetLastError() != ERROR_TIMEOUT
)
1463 condvar_sleeperr
= TRUE
;
1466 if (condvar_stop
&& (bufferlen
== 0)) {
1467 LeaveCriticalSection(&buffercrit
);
1473 LeaveCriticalSection(&buffercrit
);
1474 pWakeConditionVariable(&buffernotfull
);
1475 Sleep(sleepinterval
);
1476 if (sleepinterval
< 5) sleepinterval
+= 1;
1481 static void test_condvars_consumer_producer(void)
1483 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1485 DWORD cnt1
,cnt2
,cnt3
;
1487 if (!pInitializeConditionVariable
) {
1488 /* function is not yet in XP, only in newer Windows */
1489 win_skip("no condition variable support.\n");
1493 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1495 /* If we have static initialized condition variables, InitializeConditionVariable
1496 * is not strictly necessary.
1497 * pInitializeConditionVariable(&buffernotfull);
1499 pInitializeConditionVariable(&buffernotempty
);
1500 InitializeCriticalSection(&buffercrit
);
1502 /* Larger Test: consumer/producer example */
1504 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1506 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1507 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1508 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1509 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1510 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1511 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1513 /* Limit run to 0.5 seconds. */
1516 /* tear down start */
1517 condvar_stop
= TRUE
;
1519 /* final wake up call */
1520 pWakeAllConditionVariable (&buffernotfull
);
1521 pWakeAllConditionVariable (&buffernotempty
);
1523 /* (mostly an implementation detail)
1524 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1527 WaitForSingleObject(hp1
, 1000);
1528 WaitForSingleObject(hp2
, 1000);
1529 WaitForSingleObject(hp3
, 1000);
1530 WaitForSingleObject(hc1
, 1000);
1531 WaitForSingleObject(hc2
, 1000);
1532 WaitForSingleObject(hc3
, 1000);
1534 ok(totalconsumed
== totalproduced
,
1535 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1536 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1538 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1539 * one consumer does not get anything to do is possible. */
1540 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1541 /* The sleeps of the producer or consumer should not go above 100* produced count,
1542 * otherwise the implementation does not sleep correctly. But yet again, this is
1543 * not hard defined. */
1544 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1547 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1548 static DWORD condvar_seq
= 0;
1549 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1550 static CRITICAL_SECTION condvar_crit
;
1551 static SRWLOCK condvar_srwlock
;
1553 /* Sequence of wake/sleep to check boundary conditions:
1555 * 1: producer emits a WakeConditionVaribale without consumer waiting.
1556 * 2: consumer sleeps without a wake expecting timeout
1557 * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
1558 * 4: consumer sleeps without a wake expecting timeout
1559 * 5: a wake is handed to a SleepConditionVariableCS
1560 * 6: a wakeall is handed to a SleepConditionVariableCS
1561 * 7: sleep after above should timeout
1562 * 8: wake with crit section locked into the sleep timeout
1564 * the following tests will only be executed if InitializeSRWLock is available
1566 * 9: producer (exclusive) wakes up consumer (exclusive)
1567 * 10: producer (exclusive) wakes up consumer (shared)
1568 * 11: producer (shared) wakes up consumer (exclusive)
1569 * 12: producer (shared) wakes up consumer (shared)
1572 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1573 while (condvar_seq
< 1) Sleep(1);
1575 pWakeConditionVariable (&condvar_base
);
1578 while (condvar_seq
< 3) Sleep(1);
1579 pWakeAllConditionVariable (&condvar_base
);
1582 while (condvar_seq
< 5) Sleep(1);
1583 EnterCriticalSection (&condvar_crit
);
1584 pWakeConditionVariable (&condvar_base
);
1585 LeaveCriticalSection (&condvar_crit
);
1586 while (condvar_seq
< 6) Sleep(1);
1587 EnterCriticalSection (&condvar_crit
);
1588 pWakeAllConditionVariable (&condvar_base
);
1589 LeaveCriticalSection (&condvar_crit
);
1591 while (condvar_seq
< 8) Sleep(1);
1592 EnterCriticalSection (&condvar_crit
);
1593 pWakeConditionVariable (&condvar_base
);
1595 LeaveCriticalSection (&condvar_crit
);
1597 /* skip over remaining tests if InitializeSRWLock is not available */
1598 if (!pInitializeSRWLock
)
1601 while (condvar_seq
< 9) Sleep(1);
1602 pAcquireSRWLockExclusive(&condvar_srwlock
);
1603 pWakeConditionVariable(&condvar_base
);
1604 pReleaseSRWLockExclusive(&condvar_srwlock
);
1606 while (condvar_seq
< 10) Sleep(1);
1607 pAcquireSRWLockExclusive(&condvar_srwlock
);
1608 pWakeConditionVariable(&condvar_base
);
1609 pReleaseSRWLockExclusive(&condvar_srwlock
);
1611 while (condvar_seq
< 11) Sleep(1);
1612 pAcquireSRWLockShared(&condvar_srwlock
);
1613 pWakeConditionVariable(&condvar_base
);
1614 pReleaseSRWLockShared(&condvar_srwlock
);
1616 while (condvar_seq
< 12) Sleep(1);
1617 Sleep(50); /* ensure that consumer waits for cond variable */
1618 pAcquireSRWLockShared(&condvar_srwlock
);
1619 pWakeConditionVariable(&condvar_base
);
1620 pReleaseSRWLockShared(&condvar_srwlock
);
1625 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1628 while (condvar_seq
< 2) Sleep(1);
1630 /* wake was emitted, but we were not sleeping */
1631 EnterCriticalSection (&condvar_crit
);
1632 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1633 LeaveCriticalSection (&condvar_crit
);
1634 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1635 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1638 while (condvar_seq
< 4) Sleep(1);
1640 /* wake all was emitted, but we were not sleeping */
1641 EnterCriticalSection (&condvar_crit
);
1642 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1643 LeaveCriticalSection (&condvar_crit
);
1644 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1645 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1647 EnterCriticalSection (&condvar_crit
);
1649 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1650 LeaveCriticalSection (&condvar_crit
);
1651 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1653 EnterCriticalSection (&condvar_crit
);
1655 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1656 LeaveCriticalSection (&condvar_crit
);
1657 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
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
, 20);
1669 LeaveCriticalSection (&condvar_crit
);
1670 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1672 /* skip over remaining tests if InitializeSRWLock is not available */
1673 if (!pInitializeSRWLock
)
1675 win_skip("no srw lock support.\n");
1676 condvar_seq
= 13; /* end */
1680 pAcquireSRWLockExclusive(&condvar_srwlock
);
1682 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1683 pReleaseSRWLockExclusive(&condvar_srwlock
);
1684 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1686 pAcquireSRWLockShared(&condvar_srwlock
);
1688 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1689 pReleaseSRWLockShared(&condvar_srwlock
);
1690 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1692 pAcquireSRWLockExclusive(&condvar_srwlock
);
1694 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1695 pReleaseSRWLockExclusive(&condvar_srwlock
);
1696 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1698 pAcquireSRWLockShared(&condvar_srwlock
);
1700 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1701 pReleaseSRWLockShared(&condvar_srwlock
);
1702 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1708 static void test_condvars_base(void) {
1714 if (!pInitializeConditionVariable
) {
1715 /* function is not yet in XP, only in newer Windows */
1716 win_skip("no condition variable support.\n");
1720 InitializeCriticalSection (&condvar_crit
);
1722 if (pInitializeSRWLock
)
1723 pInitializeSRWLock(&condvar_srwlock
);
1725 EnterCriticalSection (&condvar_crit
);
1726 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1727 LeaveCriticalSection (&condvar_crit
);
1729 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1730 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1732 if (pInitializeSRWLock
)
1734 pAcquireSRWLockExclusive(&condvar_srwlock
);
1735 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1736 pReleaseSRWLockExclusive(&condvar_srwlock
);
1738 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1739 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1741 pAcquireSRWLockShared(&condvar_srwlock
);
1742 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1743 pReleaseSRWLockShared(&condvar_srwlock
);
1745 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1746 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1750 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1751 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1753 condvar_seq
= 1; /* go */
1755 while (condvar_seq
< 9)
1757 WaitForSingleObject(hp
, 100);
1758 WaitForSingleObject(hc
, 100);
1761 static LONG srwlock_seq
= 0;
1762 static SRWLOCK srwlock_base
;
1765 LONG wrong_execution_order
;
1766 LONG samethread_excl_excl
;
1767 LONG samethread_excl_shared
;
1768 LONG samethread_shared_excl
;
1769 LONG multithread_excl_excl
;
1770 LONG excl_not_preferred
;
1772 LONG trylock_shared
;
1773 } srwlock_base_errors
;
1775 /* Sequence of acquire/release to check boundary conditions:
1778 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1779 * 2: thread1 expects a deadlock and releases the waiting lock
1780 * thread2 releases the lock again
1782 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1783 * 4: thread1 expects a deadlock and releases the waiting lock
1784 * thread2 releases the lock again
1786 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1787 * 6: thread1 expects a deadlock and releases the waiting lock
1788 * thread2 releases the lock again
1790 * 7: thread2 acquires and releases two nested shared locks
1792 * 8: thread1 acquires an exclusive lock
1793 * 9: thread2 tries to acquire the exclusive lock, too
1794 * thread1 releases the exclusive lock again
1795 * 10: thread2 enters the exclusive lock and leaves it immediately again
1797 * 11: thread1 acquires a shared lock
1798 * 12: thread2 acquires and releases a shared lock
1799 * thread1 releases the lock again
1801 * 13: thread1 acquires a shared lock
1802 * 14: thread2 tries to acquire an exclusive lock
1803 * 15: thread3 tries to acquire a shared lock
1804 * 16: thread1 releases the shared lock
1805 * 17: thread2 wakes up and releases the exclusive lock
1806 * 18: thread3 wakes up and releases the shared lock
1808 * the following tests will only be executed if TryAcquireSRWLock* is available
1810 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1811 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1812 * thread1 releases the exclusive lock
1814 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1815 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1816 * thread1 releases the shared lock
1818 * thread1 acquires an exclusive lock
1819 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1820 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1821 * 21: thread1 releases the exclusive lock
1823 * thread1 acquires an shared lock
1824 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
1825 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1826 * 23: thread1 releases the shared lock
1828 * thread1 acquires a shared lock and tries to acquire an exclusive lock
1829 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
1830 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1831 * 25: thread1 releases the exclusive lock
1833 * thread1 acquires two shared locks
1834 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
1835 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1836 * 27: thread1 releases one shared lock
1837 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
1838 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1839 * 29: thread1 releases the second shared lock
1840 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
1841 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
1846 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
1849 while (srwlock_seq
< 2) Sleep(1);
1851 if (InterlockedIncrement(&srwlock_seq
) != 3)
1852 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
1853 pReleaseSRWLockExclusive(&srwlock_base
);
1856 while (srwlock_seq
< 4) Sleep(1);
1858 if (InterlockedIncrement(&srwlock_seq
) != 5)
1859 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
1860 pReleaseSRWLockExclusive(&srwlock_base
);
1863 while (srwlock_seq
< 6) Sleep(1);
1865 if (InterlockedIncrement(&srwlock_seq
) != 7)
1866 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
1867 pReleaseSRWLockShared(&srwlock_base
);
1870 while (srwlock_seq
< 8) Sleep(1);
1871 pAcquireSRWLockExclusive(&srwlock_base
);
1872 if (InterlockedIncrement(&srwlock_seq
) != 9)
1873 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1875 if (InterlockedIncrement(&srwlock_seq
) != 10)
1876 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
1877 pReleaseSRWLockExclusive(&srwlock_base
);
1880 while (srwlock_seq
< 11) Sleep(1);
1881 pAcquireSRWLockShared(&srwlock_base
);
1882 if (InterlockedIncrement(&srwlock_seq
) != 12)
1883 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1886 while (srwlock_seq
< 13) Sleep(1);
1887 pReleaseSRWLockShared(&srwlock_base
);
1888 pAcquireSRWLockShared(&srwlock_base
);
1889 if (InterlockedIncrement(&srwlock_seq
) != 14)
1890 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1893 while (srwlock_seq
< 16) Sleep(1);
1894 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
1895 if (InterlockedIncrement(&srwlock_seq
) != 17)
1896 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1897 pReleaseSRWLockShared(&srwlock_base
);
1899 /* skip over remaining tests if TryAcquireSRWLock* is not available */
1900 if (!pTryAcquireSRWLockExclusive
)
1904 while (srwlock_seq
< 19) Sleep(1);
1905 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1907 if (pTryAcquireSRWLockShared(&srwlock_base
))
1908 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1909 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1910 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1911 pReleaseSRWLockExclusive(&srwlock_base
);
1914 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1916 if (pTryAcquireSRWLockShared(&srwlock_base
))
1918 if (pTryAcquireSRWLockShared(&srwlock_base
))
1919 pReleaseSRWLockShared(&srwlock_base
);
1921 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1922 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1923 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1924 pReleaseSRWLockShared(&srwlock_base
);
1927 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1929 pAcquireSRWLockExclusive(&srwlock_base
);
1930 if (InterlockedIncrement(&srwlock_seq
) != 20)
1931 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1934 while (srwlock_seq
< 21) Sleep(1);
1935 pReleaseSRWLockExclusive(&srwlock_base
);
1936 pAcquireSRWLockShared(&srwlock_base
);
1937 if (InterlockedIncrement(&srwlock_seq
) != 22)
1938 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1941 while (srwlock_seq
< 23) Sleep(1);
1942 pReleaseSRWLockShared(&srwlock_base
);
1943 pAcquireSRWLockShared(&srwlock_base
);
1944 if (InterlockedIncrement(&srwlock_seq
) != 24)
1945 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1948 pAcquireSRWLockExclusive(&srwlock_base
);
1949 if (srwlock_seq
!= 25)
1950 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1951 pReleaseSRWLockExclusive(&srwlock_base
);
1953 pAcquireSRWLockShared(&srwlock_base
);
1954 pAcquireSRWLockShared(&srwlock_base
);
1955 if (InterlockedIncrement(&srwlock_seq
) != 26)
1956 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1959 while (srwlock_seq
< 27) Sleep(1);
1960 pReleaseSRWLockShared(&srwlock_base
);
1961 if (InterlockedIncrement(&srwlock_seq
) != 28)
1962 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1965 while (srwlock_seq
< 29) Sleep(1);
1966 pReleaseSRWLockShared(&srwlock_base
);
1967 if (InterlockedIncrement(&srwlock_seq
) != 30)
1968 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1973 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
1976 while (srwlock_seq
< 1) Sleep(1);
1977 pAcquireSRWLockExclusive(&srwlock_base
);
1978 if (InterlockedIncrement(&srwlock_seq
) != 2)
1979 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1982 pAcquireSRWLockExclusive(&srwlock_base
);
1983 if (srwlock_seq
!= 3)
1984 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
1985 pReleaseSRWLockExclusive(&srwlock_base
);
1986 pAcquireSRWLockExclusive(&srwlock_base
);
1987 if (InterlockedIncrement(&srwlock_seq
) != 4)
1988 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1991 pAcquireSRWLockShared(&srwlock_base
);
1992 if (srwlock_seq
!= 5)
1993 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
1994 pReleaseSRWLockShared(&srwlock_base
);
1995 pAcquireSRWLockShared(&srwlock_base
);
1996 if (InterlockedIncrement(&srwlock_seq
) != 6)
1997 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2000 pAcquireSRWLockExclusive(&srwlock_base
);
2001 if (srwlock_seq
!= 7)
2002 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2003 pReleaseSRWLockExclusive(&srwlock_base
);
2004 pAcquireSRWLockShared(&srwlock_base
);
2005 pAcquireSRWLockShared(&srwlock_base
);
2006 pReleaseSRWLockShared(&srwlock_base
);
2007 pReleaseSRWLockShared(&srwlock_base
);
2008 if (InterlockedIncrement(&srwlock_seq
) != 8)
2009 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2012 while (srwlock_seq
< 9) Sleep(1);
2013 pAcquireSRWLockExclusive(&srwlock_base
);
2014 if (srwlock_seq
!= 10)
2015 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2016 pReleaseSRWLockExclusive(&srwlock_base
);
2017 if (InterlockedIncrement(&srwlock_seq
) != 11)
2018 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2021 while (srwlock_seq
< 12) Sleep(1);
2022 pAcquireSRWLockShared(&srwlock_base
);
2023 pReleaseSRWLockShared(&srwlock_base
);
2024 if (InterlockedIncrement(&srwlock_seq
) != 13)
2025 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2028 while (srwlock_seq
< 14) Sleep(1);
2029 if (InterlockedIncrement(&srwlock_seq
) != 15)
2030 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2033 pAcquireSRWLockExclusive(&srwlock_base
);
2034 if (srwlock_seq
!= 17)
2035 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2036 if (InterlockedIncrement(&srwlock_seq
) != 18)
2037 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2038 pReleaseSRWLockExclusive(&srwlock_base
);
2040 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2041 if (!pTryAcquireSRWLockExclusive
)
2045 while (srwlock_seq
< 20) Sleep(1);
2046 if (pTryAcquireSRWLockShared(&srwlock_base
))
2047 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2048 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2049 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2050 if (InterlockedIncrement(&srwlock_seq
) != 21)
2051 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2054 while (srwlock_seq
< 22) Sleep(1);
2055 if (pTryAcquireSRWLockShared(&srwlock_base
))
2056 pReleaseSRWLockShared(&srwlock_base
);
2058 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2059 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2060 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2061 if (InterlockedIncrement(&srwlock_seq
) != 23)
2062 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2065 while (srwlock_seq
< 24) Sleep(1);
2066 Sleep(50); /* ensure that exclusive access request is queued */
2067 if (pTryAcquireSRWLockShared(&srwlock_base
))
2069 pReleaseSRWLockShared(&srwlock_base
);
2070 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2072 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2073 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2074 if (InterlockedIncrement(&srwlock_seq
) != 25)
2075 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2076 pReleaseSRWLockShared(&srwlock_base
);
2079 while (srwlock_seq
< 26) Sleep(1);
2080 if (pTryAcquireSRWLockShared(&srwlock_base
))
2081 pReleaseSRWLockShared(&srwlock_base
);
2083 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2084 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2085 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2086 if (InterlockedIncrement(&srwlock_seq
) != 27)
2087 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2090 while (srwlock_seq
< 28) Sleep(1);
2091 if (pTryAcquireSRWLockShared(&srwlock_base
))
2092 pReleaseSRWLockShared(&srwlock_base
);
2094 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2095 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2096 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2097 if (InterlockedIncrement(&srwlock_seq
) != 29)
2098 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2101 while (srwlock_seq
< 30) Sleep(1);
2102 if (pTryAcquireSRWLockShared(&srwlock_base
))
2103 pReleaseSRWLockShared(&srwlock_base
);
2105 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2106 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2107 pReleaseSRWLockExclusive(&srwlock_base
);
2109 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2110 if (InterlockedIncrement(&srwlock_seq
) != 31)
2111 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2116 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2119 while (srwlock_seq
< 15) Sleep(1);
2120 Sleep(50); /* some delay, such that thread2 can try to acquire a second exclusive lock */
2121 if (InterlockedIncrement(&srwlock_seq
) != 16)
2122 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2125 pAcquireSRWLockShared(&srwlock_base
);
2126 if (srwlock_seq
!= 18)
2127 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2128 pReleaseSRWLockShared(&srwlock_base
);
2129 if (InterlockedIncrement(&srwlock_seq
) != 19)
2130 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2132 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2133 if (!pTryAcquireSRWLockExclusive
)
2135 /* function is only in Windows 7 and newer */
2136 win_skip("no srw trylock support.\n");
2137 srwlock_seq
= 31; /* end */
2144 static void test_srwlock_base(void)
2149 if (!pInitializeSRWLock
)
2151 /* function is not yet in XP, only in newer Windows */
2152 win_skip("no srw lock support.\n");
2156 pInitializeSRWLock(&srwlock_base
);
2157 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2159 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2160 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2161 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2163 srwlock_seq
= 1; /* go */
2164 while (srwlock_seq
< 31)
2167 WaitForSingleObject(h1
, 100);
2168 WaitForSingleObject(h2
, 100);
2169 WaitForSingleObject(h3
, 100);
2171 ok(!srwlock_base_errors
.wrong_execution_order
,
2172 "thread commands were executed in the wrong order (occurred %d times).\n",
2173 srwlock_base_errors
.wrong_execution_order
);
2175 ok(!srwlock_base_errors
.samethread_excl_excl
,
2176 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2177 srwlock_base_errors
.samethread_excl_excl
);
2179 ok(!srwlock_base_errors
.samethread_excl_shared
,
2180 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2181 srwlock_base_errors
.samethread_excl_shared
);
2183 ok(!srwlock_base_errors
.samethread_shared_excl
,
2184 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2185 srwlock_base_errors
.samethread_shared_excl
);
2187 ok(!srwlock_base_errors
.multithread_excl_excl
,
2188 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2189 srwlock_base_errors
.multithread_excl_excl
);
2191 ok(!srwlock_base_errors
.excl_not_preferred
,
2192 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2193 srwlock_base_errors
.excl_not_preferred
);
2195 ok(!srwlock_base_errors
.trylock_excl
,
2196 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2197 srwlock_base_errors
.trylock_excl
);
2199 ok(!srwlock_base_errors
.trylock_shared
,
2200 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2201 srwlock_base_errors
.trylock_shared
);
2205 static SRWLOCK srwlock_example
;
2206 static LONG srwlock_protected_value
= 0;
2207 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2208 static BOOL srwlock_stop
= FALSE
;
2210 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2214 while (!srwlock_stop
)
2217 /* periodically request exclusive access */
2218 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2220 pAcquireSRWLockExclusive(&srwlock_example
);
2221 if (InterlockedIncrement(&srwlock_inside
) != 1)
2222 InterlockedIncrement(&srwlock_example_errors
);
2224 InterlockedIncrement(&srwlock_protected_value
);
2227 if (InterlockedDecrement(&srwlock_inside
) != 0)
2228 InterlockedIncrement(&srwlock_example_errors
);
2229 pReleaseSRWLockExclusive(&srwlock_example
);
2232 /* request shared access */
2233 pAcquireSRWLockShared(&srwlock_example
);
2234 InterlockedIncrement(&srwlock_inside
);
2235 old
= srwlock_protected_value
;
2240 if (old
!= srwlock_protected_value
)
2241 InterlockedIncrement(&srwlock_example_errors
);
2242 InterlockedDecrement(&srwlock_inside
);
2243 pReleaseSRWLockShared(&srwlock_example
);
2249 static void test_srwlock_example(void)
2253 DWORD cnt1
, cnt2
, cnt3
;
2255 if (!pInitializeSRWLock
) {
2256 /* function is not yet in XP, only in newer Windows */
2257 win_skip("no srw lock support.\n");
2261 pInitializeSRWLock(&srwlock_example
);
2263 cnt1
= cnt2
= cnt3
= 0;
2265 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2266 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2267 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2269 /* limit run to 1 second. */
2272 /* tear down start */
2273 srwlock_stop
= TRUE
;
2275 WaitForSingleObject(h1
, 1000);
2276 WaitForSingleObject(h2
, 1000);
2277 WaitForSingleObject(h3
, 1000);
2279 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2280 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2281 srwlock_example_errors
);
2283 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2284 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2289 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2290 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
2291 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
2292 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
2293 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
2294 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
2295 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
2296 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
2297 pCreateMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "CreateMemoryResourceNotification");
2298 pQueryMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "QueryMemoryResourceNotification");
2299 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2300 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2301 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2302 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2303 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2304 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2305 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2306 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2307 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2308 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2309 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2310 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2311 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2312 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2313 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2314 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2316 test_signalandwait();
2321 test_waitable_timer();
2322 test_iocp_callback();
2324 test_WaitForSingleObject();
2325 test_WaitForMultipleObjects();
2327 test_condvars_base();
2328 test_condvars_consumer_producer();
2329 test_srwlock_base();
2330 test_srwlock_example();