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 0x600
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 VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
48 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
50 static void test_signalandwait(void)
52 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
55 HANDLE event
[2], semaphore
[2], file
;
57 kernel32
= GetModuleHandle("kernel32");
58 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
60 if (!pSignalObjectAndWait
)
63 /* invalid parameters */
64 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
65 if (r
== ERROR_INVALID_FUNCTION
)
67 win_skip("SignalObjectAndWait is not implemented\n");
68 return; /* Win98/ME */
70 ok( r
== WAIT_FAILED
, "should fail\n");
72 event
[0] = CreateEvent(NULL
, 0, 0, NULL
);
73 event
[1] = CreateEvent(NULL
, 1, 1, NULL
);
75 ok( event
[0] && event
[1], "failed to create event flags\n");
77 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
78 ok( r
== WAIT_FAILED
, "should fail\n");
80 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
81 ok( r
== WAIT_FAILED
, "should fail\n");
84 /* valid parameters */
85 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
86 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
88 /* event[0] is now signalled */
89 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
90 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
92 /* event[0] is not signalled */
93 r
= WaitForSingleObject(event
[0], 0);
94 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
96 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
97 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
99 /* clear event[1] and check for a timeout */
100 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
101 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
102 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
104 CloseHandle(event
[0]);
105 CloseHandle(event
[1]);
108 semaphore
[0] = CreateSemaphore( NULL
, 0, 1, NULL
);
109 semaphore
[1] = CreateSemaphore( NULL
, 1, 1, NULL
);
110 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
112 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
113 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
115 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
116 ok( r
== WAIT_FAILED
, "should fail\n");
118 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
119 ok( r
== FALSE
, "should fail\n");
121 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
122 ok( r
== TRUE
, "should succeed\n");
124 CloseHandle(semaphore
[0]);
125 CloseHandle(semaphore
[1]);
127 /* try a registry key */
128 file
= CreateFile("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
129 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
130 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
131 ok( r
== WAIT_FAILED
, "should fail\n");
132 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
136 static void test_mutex(void)
145 SetLastError(0xdeadbeef);
146 hOpened
= OpenMutex(0, FALSE
, "WineTestMutex");
147 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
148 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
150 SetLastError(0xdeadbeef);
151 hCreated
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
152 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
154 SetLastError(0xdeadbeef);
155 hOpened
= OpenMutex(0, FALSE
, "WineTestMutex");
157 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
159 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
161 SetLastError(0xdeadbeef);
162 hOpened
= OpenMutex(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
163 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
164 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
165 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
166 CloseHandle(hOpened
);
168 for(i
=0; i
< 31; i
++)
170 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
171 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
174 SetLastError(0xdeadbeef);
175 hOpened
= OpenMutex(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
176 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
177 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
178 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
179 CloseHandle(hOpened
);
181 for (i
= 0; i
< 32; i
++)
183 SetLastError(0xdeadbeef);
184 hOpened
= OpenMutex(0x1 << i
, FALSE
, "WineTestMutex");
187 SetLastError(0xdeadbeef);
188 ret
= ReleaseMutex(hOpened
);
189 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
190 CloseHandle(hOpened
);
194 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
195 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
197 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
198 ReleaseMutex(hCreated
);
204 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
206 SetLastError(0xdeadbeef);
207 ret
= ReleaseMutex(hCreated
);
208 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
209 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
211 /* test case sensitivity */
213 SetLastError(0xdeadbeef);
214 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
215 ok(!hOpened
, "OpenMutex succeeded\n");
216 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
218 SetLastError(0xdeadbeef);
219 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "winetestmutex");
220 ok(!hOpened
, "OpenMutex succeeded\n");
221 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
223 SetLastError(0xdeadbeef);
224 hOpened
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
225 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
226 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
227 CloseHandle(hOpened
);
229 SetLastError(0xdeadbeef);
230 hOpened
= CreateMutex(NULL
, FALSE
, "WINETESTMUTEX");
231 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
232 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
233 CloseHandle(hOpened
);
235 CloseHandle(hCreated
);
238 static void test_slist(void)
244 } item1
, item2
, item3
, *pitem
;
246 SLIST_HEADER slist_header
;
250 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
251 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
252 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
253 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
254 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
257 kernel32
= GetModuleHandle("KERNEL32.DLL");
258 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
259 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
260 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
261 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
262 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
263 if (pInitializeSListHead
== NULL
||
264 pQueryDepthSList
== NULL
||
265 pInterlockedFlushSList
== NULL
||
266 pInterlockedPopEntrySList
== NULL
||
267 pInterlockedPushEntrySList
== NULL
)
269 win_skip("some required slist entrypoints were not found, skipping tests\n");
273 memset(&slist_header
, 0xFF, sizeof(slist_header
));
274 pInitializeSListHead(&slist_header
);
275 size
= pQueryDepthSList(&slist_header
);
276 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
279 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
280 "previous entry in empty slist wasn't NULL\n");
281 size
= pQueryDepthSList(&slist_header
);
282 ok(size
== 1, "slist with 1 item has size %d\n", size
);
285 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
286 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
289 pitem
= (struct item
*) entry
;
290 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
292 size
= pQueryDepthSList(&slist_header
);
293 ok(size
== 2, "slist with 2 items has size %d\n", size
);
296 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
297 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
300 pitem
= (struct item
*) entry
;
301 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
303 size
= pQueryDepthSList(&slist_header
);
304 ok(size
== 3, "slist with 3 items has size %d\n", size
);
306 entry
= pInterlockedPopEntrySList(&slist_header
);
307 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
310 pitem
= (struct item
*) entry
;
311 ok(pitem
->value
== 3, "unexpected entry removed\n");
313 size
= pQueryDepthSList(&slist_header
);
314 ok(size
== 2, "slist with 2 items has size %d\n", size
);
316 entry
= pInterlockedFlushSList(&slist_header
);
317 size
= pQueryDepthSList(&slist_header
);
318 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
321 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
322 "popping empty slist didn't return NULL\n");
324 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
325 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
328 static void test_event(void)
330 HANDLE handle
, handle2
;
331 SECURITY_ATTRIBUTES sa
;
332 SECURITY_DESCRIPTOR sd
;
338 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
339 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
342 sa
.nLength
= sizeof(sa
);
343 sa
.lpSecurityDescriptor
= &sd
;
344 sa
.bInheritHandle
= FALSE
;
346 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
349 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
350 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
353 /* sd with NULL dacl */
354 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
355 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
356 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
359 /* sd with empty dacl */
360 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
361 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
362 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
363 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
366 /* test case sensitivity */
368 SetLastError(0xdeadbeef);
369 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
370 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
371 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
373 SetLastError(0xdeadbeef);
374 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
375 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
376 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
377 CloseHandle( handle2
);
379 SetLastError(0xdeadbeef);
380 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
381 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
382 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
383 CloseHandle( handle2
);
385 SetLastError(0xdeadbeef);
386 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
387 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
388 CloseHandle( handle2
);
390 SetLastError(0xdeadbeef);
391 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
392 ok( !handle2
, "OpenEvent succeeded\n");
393 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
395 CloseHandle( handle
);
397 /* resource notifications are events too */
399 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
401 trace( "memory resource notifications not supported\n" );
404 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
405 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
406 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
407 ret
= pQueryMemoryResourceNotification( handle
, &val
);
408 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
409 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
411 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
412 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
413 ret
= WaitForSingleObject( handle
, 10 );
414 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
417 ret
= pQueryMemoryResourceNotification( handle
, &val
);
418 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
419 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
420 ret
= CloseHandle( handle
);
421 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
423 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
425 ret
= pQueryMemoryResourceNotification( handle
, &val
);
426 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
427 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
428 CloseHandle( handle
);
431 static void test_semaphore(void)
433 HANDLE handle
, handle2
;
435 /* test case sensitivity */
437 SetLastError(0xdeadbeef);
438 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
439 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
440 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
442 SetLastError(0xdeadbeef);
443 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
444 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
445 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
446 CloseHandle( handle2
);
448 SetLastError(0xdeadbeef);
449 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
450 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
451 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
452 CloseHandle( handle2
);
454 SetLastError(0xdeadbeef);
455 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
456 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
457 CloseHandle( handle2
);
459 SetLastError(0xdeadbeef);
460 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
461 ok( !handle2
, "OpenSemaphore succeeded\n");
462 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
464 CloseHandle( handle
);
467 static void test_waitable_timer(void)
469 HANDLE handle
, handle2
;
471 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
473 win_skip("{Create,Open}WaitableTimerA() is not available\n");
477 /* test case sensitivity */
479 SetLastError(0xdeadbeef);
480 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
481 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
482 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
484 SetLastError(0xdeadbeef);
485 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
486 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
487 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
488 CloseHandle( handle2
);
490 SetLastError(0xdeadbeef);
491 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
492 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
493 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
494 CloseHandle( handle2
);
496 SetLastError(0xdeadbeef);
497 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
498 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
499 CloseHandle( handle2
);
501 SetLastError(0xdeadbeef);
502 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
503 ok( !handle2
, "OpenWaitableTimer succeeded\n");
504 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
505 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
506 "wrong error %u\n", GetLastError());
508 CloseHandle( handle
);
511 static HANDLE sem
= 0;
513 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
515 ReleaseSemaphore(sem
, 1, NULL
);
518 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
520 static void test_iocp_callback(void)
522 char temp_path
[MAX_PATH
];
523 char filename
[MAX_PATH
];
526 static const char prefix
[] = "pfx";
528 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
530 const char *buffer
= "12345678123456781234567812345678";
531 OVERLAPPED overlapped
;
533 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
534 if(!p_BindIoCompletionCallback
) {
535 win_skip("BindIoCompletionCallback not found in this DLL\n");
539 sem
= CreateSemaphore(NULL
, 0, 1, NULL
);
540 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
542 ret
= GetTempPathA(MAX_PATH
, temp_path
);
543 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
544 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
546 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
547 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
549 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
550 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
551 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
553 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
554 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
555 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
557 ret
= CloseHandle(hFile
);
558 ok( ret
, "CloseHandle: error %d\n", GetLastError());
559 ret
= DeleteFileA(filename
);
560 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
562 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
563 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
564 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
566 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
567 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
569 memset(&overlapped
, 0, sizeof(overlapped
));
570 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
571 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
573 ret
= WaitForSingleObject(sem
, 5000);
574 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
577 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
578 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
579 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
580 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
581 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\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 /* win2k3 requires the Flags parameter to be zero */
590 SetLastError(0xdeadbeef);
591 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
592 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
593 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
594 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
596 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
597 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
599 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
600 ret
= CloseHandle(hFile
);
601 ok( ret
, "CloseHandle: error %d\n", GetLastError());
602 ret
= DeleteFileA(filename
);
603 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
605 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
606 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
607 ok(GetLastError() == ERROR_INVALID_HANDLE
||
608 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
609 "Last error is %d\n", GetLastError());
612 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
615 ok(timedOut
, "Timer callbacks should always time out\n");
619 struct timer_queue_data1
626 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
628 struct timer_queue_data1
*d
= p
;
629 ok(timedOut
, "Timer callbacks should always time out\n");
630 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
633 SetLastError(0xdeadbeef);
634 /* Note, XP SP2 does *not* do any deadlock checking, so passing
635 INVALID_HANDLE_VALUE here will just hang. */
636 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
637 ok(!ret
, "DeleteTimerQueueTimer\n");
638 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
642 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
644 struct timer_queue_data1
*d
= p
;
645 ok(timedOut
, "Timer callbacks should always time out\n");
646 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
648 /* Basically kill the timer since it won't have time to run
650 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
651 ok(ret
, "ChangeTimerQueueTimer\n");
655 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
657 struct timer_queue_data1
*d
= p
;
658 ok(timedOut
, "Timer callbacks should always time out\n");
661 /* This tests whether a timer gets flagged for deletion before
662 or after the callback runs. If we start this timer with a
663 period of zero (run once), then ChangeTimerQueueTimer will
664 fail if the timer is already flagged. Hence we really run
665 only once. Otherwise we will run multiple times. */
666 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
667 ok(ret
, "ChangeTimerQueueTimer\n");
672 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
674 DWORD_PTR delay
= (DWORD_PTR
) p
;
675 ok(timedOut
, "Timer callbacks should always time out\n");
680 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
682 struct timer_queue_data1
*d
= p
;
683 ok(timedOut
, "Timer callbacks should always time out\n");
684 /* This tests an original implementation bug where a deleted timer may get
685 to run, but it is tricky to set up. */
686 if (d
->q
&& d
->num_calls
++ == 0)
688 /* First run: delete ourselves, then insert and remove a timer
689 that goes in front of us in the sorted timeout list. Once
690 removed, we will still timeout at the faster timer's due time,
691 but this should be a no-op if we are bug-free. There should
692 not be a second run. We can test the value of num_calls later. */
696 /* The delete will pend while we are in this callback. */
697 SetLastError(0xdeadbeef);
698 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
699 ok(!ret
, "DeleteTimerQueueTimer\n");
700 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
702 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
703 ok(ret
, "CreateTimerQueueTimer\n");
704 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
706 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
707 ok(ret
, "DeleteTimerQueueTimer\n");
709 /* Now we stay alive by hanging around in the callback. */
714 static void test_timer_queue(void)
716 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
717 int n0
, n1
, n2
, n3
, n4
, n5
;
718 struct timer_queue_data1 d1
, d2
, d3
, d4
;
722 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
723 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
725 win_skip("TimerQueue API not present\n");
729 /* Test asynchronous deletion of the queue. */
730 q
= pCreateTimerQueue();
731 ok(q
!= NULL
, "CreateTimerQueue\n");
733 SetLastError(0xdeadbeef);
734 ret
= pDeleteTimerQueueEx(q
, NULL
);
735 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
736 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
739 /* Test synchronous deletion of the queue and running timers. */
740 q
= pCreateTimerQueue();
741 ok(q
!= NULL
, "CreateTimerQueue\n");
746 ret
= pCreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0,
748 ok(ret
, "CreateTimerQueueTimer\n");
749 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
750 ret0
= pDeleteTimerQueueTimer(q
, t0
, NULL
);
751 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
752 broken(ret0
), /* Win 2000 & XP & 2003 */
753 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
758 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
760 ok(ret
, "CreateTimerQueueTimer\n");
761 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
766 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
768 ok(ret
, "CreateTimerQueueTimer\n");
769 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
774 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
776 ok(ret
, "CreateTimerQueueTimer\n");
777 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
779 /* Start really late (it won't start). */
782 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
784 ok(ret
, "CreateTimerQueueTimer\n");
785 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
787 /* Start soon, but delay so long it won't run again. */
790 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
792 ok(ret
, "CreateTimerQueueTimer\n");
793 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
795 /* Give them a chance to do some work. */
798 /* Test deleting a once-only timer. */
799 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
800 ok(ret
, "DeleteTimerQueueTimer\n");
802 /* A periodic timer. */
803 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
804 ok(ret
, "DeleteTimerQueueTimer\n");
806 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
807 ok(ret
, "DeleteTimerQueueEx\n");
809 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
810 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
811 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
812 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
813 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
815 /* Test synchronous deletion of the timer/queue with event trigger. */
816 e
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
817 et1
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
818 et2
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
819 if (!e
|| !et1
|| !et2
)
821 skip("Failed to create timer queue descruction event\n");
825 q
= pCreateTimerQueue();
826 ok(q
!= NULL
, "CreateTimerQueue\n");
828 /* Run once and finish quickly (should be done when we delete it). */
830 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
831 ok(ret
, "CreateTimerQueueTimer\n");
832 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
834 /* Run once and finish slowly (shouldn't be done when we delete it). */
836 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
838 ok(ret
, "CreateTimerQueueTimer\n");
839 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
841 /* Run once and finish quickly (should be done when we delete it). */
843 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
844 ok(ret
, "CreateTimerQueueTimer\n");
845 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
847 /* Run once and finish slowly (shouldn't be done when we delete it). */
849 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
851 ok(ret
, "CreateTimerQueueTimer\n");
852 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
854 /* Give them a chance to start. */
857 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
858 even if the timer is finished. */
859 SetLastError(0xdeadbeef);
860 ret
= pDeleteTimerQueueTimer(q
, t1
, NULL
);
861 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
862 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
865 SetLastError(0xdeadbeef);
866 ret
= pDeleteTimerQueueTimer(q
, t2
, NULL
);
867 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
868 ok(GetLastError() == ERROR_IO_PENDING
,
869 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
872 SetLastError(0xdeadbeef);
873 ret
= pDeleteTimerQueueTimer(q
, t3
, et1
);
874 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
875 ok(GetLastError() == 0xdeadbeef,
876 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
878 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
879 "Timer destruction event not triggered\n");
881 SetLastError(0xdeadbeef);
882 ret
= pDeleteTimerQueueTimer(q
, t4
, et2
);
883 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
884 ok(GetLastError() == ERROR_IO_PENDING
,
885 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
887 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
888 "Timer destruction event not triggered\n");
890 SetLastError(0xdeadbeef);
891 ret
= pDeleteTimerQueueEx(q
, e
);
892 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
893 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
895 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
896 "Queue destruction event not triggered\n");
899 /* Test deleting/changing a timer in execution. */
900 q
= pCreateTimerQueue();
901 ok(q
!= NULL
, "CreateTimerQueue\n");
903 /* Test changing a once-only timer before it fires (this is allowed,
904 whereas after it fires you cannot). */
906 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
908 ok(ret
, "CreateTimerQueueTimer\n");
909 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
910 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
911 ok(ret
, "ChangeTimerQueueTimer\n");
917 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
920 ok(ret
, "CreateTimerQueueTimer\n");
921 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
927 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
930 ok(ret
, "CreateTimerQueueTimer\n");
931 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
936 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
939 ok(ret
, "CreateTimerQueueTimer\n");
940 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
944 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
945 ok(ret
, "DeleteTimerQueueEx\n");
946 ok(n1
== 1, "ChangeTimerQueueTimer\n");
947 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
948 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
949 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
951 /* Test an obscure bug that was in the original implementation. */
952 q
= pCreateTimerQueue();
953 ok(q
!= NULL
, "CreateTimerQueue\n");
955 /* All the work is done in the callback. */
959 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
960 100, WT_EXECUTELONGFUNCTION
);
962 ok(ret
, "CreateTimerQueueTimer\n");
963 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
967 SetLastError(0xdeadbeef);
968 ret
= pDeleteTimerQueueEx(q
, NULL
);
969 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
970 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
972 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
974 /* Test functions on the default timer queue. */
977 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
979 ok(ret
, "CreateTimerQueueTimer, default queue\n");
980 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
982 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
983 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
985 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
986 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
988 /* Try mixing default and non-default queues. Apparently this works. */
989 q
= pCreateTimerQueue();
990 ok(q
!= NULL
, "CreateTimerQueue\n");
994 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
996 ok(ret
, "CreateTimerQueueTimer\n");
997 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1001 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
1003 ok(ret
, "CreateTimerQueueTimer\n");
1004 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1006 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1007 ok(ret
, "ChangeTimerQueueTimer\n");
1009 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1010 ok(ret
, "ChangeTimerQueueTimer\n");
1012 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1013 ok(ret
, "DeleteTimerQueueTimer\n");
1015 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1016 ok(ret
, "DeleteTimerQueueTimer\n");
1018 /* Try to delete the default queue? In any case: not allowed. */
1019 SetLastError(0xdeadbeef);
1020 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
1021 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1022 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1023 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1026 SetLastError(0xdeadbeef);
1027 ret
= pDeleteTimerQueueEx(q
, NULL
);
1028 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1029 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1033 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1035 DWORD tmp
= HandleToULong(handle
);
1037 return ULongToHandle(tmp
);
1040 static void test_WaitForSingleObject(void)
1042 HANDLE signaled
, nonsignaled
, invalid
;
1045 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1046 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1047 invalid
= (HANDLE
) 0xdeadbee0;
1049 /* invalid handle with different values for lower 2 bits */
1050 SetLastError(0xdeadbeef);
1051 ret
= WaitForSingleObject(invalid
, 0);
1052 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1053 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1055 SetLastError(0xdeadbeef);
1056 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1057 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1058 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1060 SetLastError(0xdeadbeef);
1061 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1062 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1063 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1065 SetLastError(0xdeadbeef);
1066 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1067 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1068 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1070 /* valid handle with different values for lower 2 bits */
1071 SetLastError(0xdeadbeef);
1072 ret
= WaitForSingleObject(nonsignaled
, 0);
1073 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1074 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1076 SetLastError(0xdeadbeef);
1077 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1078 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1079 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1081 SetLastError(0xdeadbeef);
1082 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1083 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1084 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1086 SetLastError(0xdeadbeef);
1087 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1088 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1089 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1091 /* valid handle with different values for lower 2 bits */
1092 SetLastError(0xdeadbeef);
1093 ret
= WaitForSingleObject(signaled
, 0);
1094 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1095 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1097 SetLastError(0xdeadbeef);
1098 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1099 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1100 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1102 SetLastError(0xdeadbeef);
1103 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1104 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1105 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1107 SetLastError(0xdeadbeef);
1108 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1109 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1110 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1112 CloseHandle(signaled
);
1113 CloseHandle(nonsignaled
);
1116 static void test_WaitForMultipleObjects(void)
1120 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1122 /* create the maximum number of events and make sure
1123 * we can wait on that many */
1124 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1126 maxevents
[i
] = CreateEvent(NULL
, i
==0, TRUE
, NULL
);
1127 ok( maxevents
[i
] != 0, "should create enough events\n");
1130 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1131 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1132 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1133 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1134 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1135 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1136 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1138 /* the lowest index is checked first and remaining events are untouched */
1139 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
1140 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1143 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1144 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1147 static BOOL g_initcallback_ret
, g_initcallback_called
;
1148 static void *g_initctxt
;
1150 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1152 g_initcallback_called
= TRUE
;
1153 /* zero bit set means here that initialization is taking place - initialization locked */
1154 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1155 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1156 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1157 return g_initcallback_ret
;
1160 static void test_initonce(void)
1165 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1167 win_skip("one-time initialization API not supported\n");
1171 /* blocking initialization with callback */
1172 initonce
.Ptr
= (void*)0xdeadbeef;
1173 pInitOnceInitialize(&initonce
);
1174 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1176 /* initialisation completed successfully */
1177 g_initcallback_ret
= TRUE
;
1179 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1180 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1181 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1182 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1183 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1185 /* so it's been called already so won't be called again */
1187 g_initcallback_called
= FALSE
;
1188 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1189 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1190 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1191 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1192 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1194 pInitOnceInitialize(&initonce
);
1195 g_initcallback_called
= FALSE
;
1196 /* 2 lower order bits should never be used, you'll get a crash in result */
1197 g_initctxt
= (void*)0xFFFFFFF0;
1198 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1199 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1200 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1201 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1202 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1204 /* callback failed */
1205 g_initcallback_ret
= FALSE
;
1206 g_initcallback_called
= FALSE
;
1208 pInitOnceInitialize(&initonce
);
1209 SetLastError( 0xdeadbeef );
1210 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1211 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1212 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1213 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1214 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1216 /* blocking initialization without a callback */
1217 pInitOnceInitialize(&initonce
);
1220 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1221 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1222 ok(pending
, "got %d\n", pending
);
1223 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1224 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1225 /* another attempt to begin initialization with block a single thread */
1229 SetLastError( 0xdeadbeef );
1230 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1231 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1232 ok(pending
== 0xf, "got %d\n", pending
);
1233 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1234 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1236 g_initctxt
= (void*)0xdeadbee0;
1237 SetLastError( 0xdeadbeef );
1238 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1239 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1240 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1242 /* once failed already */
1243 g_initctxt
= (void*)0xdeadbee0;
1244 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1245 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1246 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1248 pInitOnceInitialize(&initonce
);
1249 SetLastError( 0xdeadbeef );
1250 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1251 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1252 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1254 SetLastError( 0xdeadbeef );
1255 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1256 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1257 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1259 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1260 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1261 ok(pending
, "got %d\n", pending
);
1262 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1264 SetLastError( 0xdeadbeef );
1265 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1266 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1268 SetLastError( 0xdeadbeef );
1269 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1270 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1271 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1273 SetLastError( 0xdeadbeef );
1274 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1275 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1276 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1278 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1279 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1280 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1282 pInitOnceInitialize(&initonce
);
1283 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1284 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1285 ok(pending
, "got %d\n", pending
);
1286 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1288 SetLastError( 0xdeadbeef );
1289 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1290 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1292 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1293 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1294 ok(pending
, "got %d\n", pending
);
1295 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1297 SetLastError( 0xdeadbeef );
1298 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1299 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1300 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1302 SetLastError( 0xdeadbeef );
1303 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1304 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1305 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1307 SetLastError( 0xdeadbeef );
1308 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1309 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1310 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1312 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1313 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1314 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1316 SetLastError( 0xdeadbeef );
1317 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1318 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1319 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1321 pInitOnceInitialize(&initonce
);
1322 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1323 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1324 ok(pending
, "got %d\n", pending
);
1325 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1327 /* test INIT_ONCE_CHECK_ONLY */
1329 pInitOnceInitialize(&initonce
);
1330 SetLastError( 0xdeadbeef );
1331 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1332 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1333 SetLastError( 0xdeadbeef );
1334 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1335 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1337 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1338 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1339 ok(pending
, "got %d\n", pending
);
1340 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1342 SetLastError( 0xdeadbeef );
1343 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1344 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1345 SetLastError( 0xdeadbeef );
1346 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1347 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1349 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1350 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1351 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1353 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1354 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1355 ok(!pending
, "got %d\n", pending
);
1356 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1357 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1359 SetLastError( 0xdeadbeef );
1360 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1361 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1363 pInitOnceInitialize(&initonce
);
1364 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1365 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1366 ok(pending
, "got %d\n", pending
);
1367 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1369 SetLastError( 0xdeadbeef );
1370 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1371 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1372 SetLastError( 0xdeadbeef );
1373 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1374 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1376 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1377 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1378 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1380 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1381 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1382 ok(!pending
, "got %d\n", pending
);
1383 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1384 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1386 SetLastError( 0xdeadbeef );
1387 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1388 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1391 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1392 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1393 static CRITICAL_SECTION buffercrit
;
1394 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1395 static LONG bufferlen
,totalproduced
,totalconsumed
;
1396 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1398 #define BUFFER_SIZE 5
1400 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1401 DWORD sleepinterval
= 5;
1404 Sleep(sleepinterval
);
1405 if (sleepinterval
> 1)
1408 EnterCriticalSection(&buffercrit
);
1409 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1410 condvar_producer_sleepcnt
++;
1411 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1412 if (GetLastError() != ERROR_TIMEOUT
)
1413 condvar_sleeperr
= TRUE
;
1417 LeaveCriticalSection(&buffercrit
);
1422 LeaveCriticalSection(&buffercrit
);
1423 pWakeConditionVariable(&buffernotempty
);
1428 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1429 DWORD
*cnt
= (DWORD
*)x
;
1430 DWORD sleepinterval
= 1;
1433 EnterCriticalSection(&buffercrit
);
1434 while ((bufferlen
== 0) && !condvar_stop
) {
1435 condvar_consumer_sleepcnt
++;
1436 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1437 if (GetLastError() != ERROR_TIMEOUT
)
1438 condvar_sleeperr
= TRUE
;
1441 if (condvar_stop
&& (bufferlen
== 0)) {
1442 LeaveCriticalSection(&buffercrit
);
1448 LeaveCriticalSection(&buffercrit
);
1449 pWakeConditionVariable(&buffernotfull
);
1450 Sleep(sleepinterval
);
1451 if (sleepinterval
< 5) sleepinterval
+= 1;
1456 static void test_condvars_consumer_producer(void)
1458 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1460 DWORD cnt1
,cnt2
,cnt3
;
1462 if (!pInitializeConditionVariable
) {
1463 /* function is not yet in XP, only in newer Windows */
1464 /* and not yet implemented in Wine for some days/weeks */
1465 todo_wine
win_skip("no condition variable support.\n");
1469 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1471 /* If we have static initialized condition variables, InitializeConditionVariable
1472 * is not strictly necessary.
1473 * pInitializeConditionVariable(&buffernotfull);
1475 pInitializeConditionVariable(&buffernotempty
);
1476 InitializeCriticalSection(&buffercrit
);
1478 /* Larger Test: consumer/producer example */
1480 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1482 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1483 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1484 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1485 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1486 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1487 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1489 /* Limit run to 0.5 seconds. */
1492 /* tear down start */
1493 condvar_stop
= TRUE
;
1495 /* final wake up call */
1496 pWakeAllConditionVariable (&buffernotfull
);
1497 pWakeAllConditionVariable (&buffernotempty
);
1499 /* (mostly an implementation detail)
1500 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1503 WaitForSingleObject(hp1
, 1000);
1504 WaitForSingleObject(hp2
, 1000);
1505 WaitForSingleObject(hp3
, 1000);
1506 WaitForSingleObject(hc1
, 1000);
1507 WaitForSingleObject(hc2
, 1000);
1508 WaitForSingleObject(hc3
, 1000);
1510 ok(totalconsumed
== totalproduced
,
1511 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1512 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1514 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1515 * one consumer does not get anything to do is possible. */
1516 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1517 /* The sleeps of the producer or consumer should not go above 100* produced count,
1518 * otherwise the implementation does not sleep correctly. But yet again, this is
1519 * not hard defined. */
1520 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1523 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1524 static DWORD condvar_seq
= 0;
1525 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1526 static CRITICAL_SECTION condvar_crit
;
1528 /* Sequence of wake/sleep to check boundary conditions:
1530 * 1: producer emits a WakeConditionVaribale without consumer waiting.
1531 * 2: consumer sleeps without a wake expecting timeout
1532 * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
1533 * 4: consumer sleeps without a wake expecting timeout
1534 * 5: a wake is handed to a SleepConditionVariableCS
1535 * 6: a wakeall is handed to a SleepConditionVariableCS
1536 * 7: sleep after above should timeout
1537 * 8: wake with crit section locked into the sleep timeout
1540 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1541 while (condvar_seq
< 1) Sleep(1);
1543 pWakeConditionVariable (&condvar_base
);
1546 while (condvar_seq
< 3) Sleep(1);
1547 pWakeAllConditionVariable (&condvar_base
);
1550 while (condvar_seq
< 5) Sleep(1);
1551 EnterCriticalSection (&condvar_crit
);
1552 pWakeConditionVariable (&condvar_base
);
1553 LeaveCriticalSection (&condvar_crit
);
1554 while (condvar_seq
< 6) Sleep(1);
1555 EnterCriticalSection (&condvar_crit
);
1556 pWakeAllConditionVariable (&condvar_base
);
1557 LeaveCriticalSection (&condvar_crit
);
1559 while (condvar_seq
< 8) Sleep(1);
1560 EnterCriticalSection (&condvar_crit
);
1561 pWakeConditionVariable (&condvar_base
);
1563 LeaveCriticalSection (&condvar_crit
);
1568 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1571 while (condvar_seq
< 2) Sleep(1);
1573 /* wake was emitted, but we were not sleeping */
1574 EnterCriticalSection (&condvar_crit
);
1575 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1576 LeaveCriticalSection (&condvar_crit
);
1577 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1578 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1581 while (condvar_seq
< 4) Sleep(1);
1583 /* wake all was emitted, but we were not sleeping */
1584 EnterCriticalSection (&condvar_crit
);
1585 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1586 LeaveCriticalSection (&condvar_crit
);
1587 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1588 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1590 EnterCriticalSection (&condvar_crit
);
1592 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1593 LeaveCriticalSection (&condvar_crit
);
1594 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1596 EnterCriticalSection (&condvar_crit
);
1598 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1599 LeaveCriticalSection (&condvar_crit
);
1600 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1603 EnterCriticalSection (&condvar_crit
);
1604 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1605 LeaveCriticalSection (&condvar_crit
);
1606 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1607 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1609 EnterCriticalSection (&condvar_crit
);
1611 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1612 LeaveCriticalSection (&condvar_crit
);
1613 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1619 static void test_condvars_base(void) {
1625 if (!pInitializeConditionVariable
) {
1626 /* function is not yet in XP, only in newer Windows */
1627 /* and not yet implemented in Wine for some days/weeks */
1628 todo_wine
win_skip("no condition variable support.\n");
1632 InitializeCriticalSection (&condvar_crit
);
1634 EnterCriticalSection (&condvar_crit
);
1635 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1636 LeaveCriticalSection (&condvar_crit
);
1638 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1639 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1642 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1643 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1645 condvar_seq
= 1; /* go */
1647 while (condvar_seq
< 9)
1649 WaitForSingleObject(hp
, 100);
1650 WaitForSingleObject(hc
, 100);
1656 HMODULE hdll
= GetModuleHandle("kernel32");
1657 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
1658 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
1659 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
1660 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
1661 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
1662 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
1663 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
1664 pCreateMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "CreateMemoryResourceNotification");
1665 pQueryMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "QueryMemoryResourceNotification");
1666 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
1667 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
1668 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
1669 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
1670 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
1671 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
1672 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
1673 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
1675 test_signalandwait();
1680 test_waitable_timer();
1681 test_iocp_callback();
1683 test_WaitForSingleObject();
1684 test_WaitForMultipleObjects();
1686 test_condvars_base();
1687 test_condvars_consumer_producer();