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
27 #include <wine/winternl.h>
29 #include <wine/test.h>
31 static BOOL (WINAPI
*pChangeTimerQueueTimer
)(HANDLE
, HANDLE
, ULONG
, ULONG
);
32 static HANDLE (WINAPI
*pCreateTimerQueue
)(void);
33 static BOOL (WINAPI
*pCreateTimerQueueTimer
)(PHANDLE
, HANDLE
, WAITORTIMERCALLBACK
,
34 PVOID
, DWORD
, DWORD
, ULONG
);
35 static HANDLE (WINAPI
*pCreateWaitableTimerA
)(SECURITY_ATTRIBUTES
*,BOOL
,LPCSTR
);
36 static BOOL (WINAPI
*pDeleteTimerQueueEx
)(HANDLE
, HANDLE
);
37 static BOOL (WINAPI
*pDeleteTimerQueueTimer
)(HANDLE
, HANDLE
, HANDLE
);
38 static HANDLE (WINAPI
*pOpenWaitableTimerA
)(DWORD
,BOOL
,LPCSTR
);
39 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
40 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
41 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
42 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
43 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
44 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
46 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
47 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
48 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
49 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
50 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
52 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
53 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
54 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
55 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
56 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
57 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
58 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
60 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
61 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
62 static NTSTATUS (WINAPI
*pNtWaitForMultipleObjects
)(ULONG
,const HANDLE
*,BOOLEAN
,BOOLEAN
,const LARGE_INTEGER
*);
64 static void test_signalandwait(void)
66 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
69 HANDLE event
[2], semaphore
[2], file
;
72 kernel32
= GetModuleHandleA("kernel32.dll");
73 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
75 if (!pSignalObjectAndWait
)
78 /* invalid parameters */
79 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
80 if (r
== ERROR_INVALID_FUNCTION
)
82 win_skip("SignalObjectAndWait is not implemented\n");
83 return; /* Win98/ME */
85 ok( r
== WAIT_FAILED
, "should fail\n");
87 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
88 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
90 ok( event
[0] && event
[1], "failed to create event flags\n");
92 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
93 ok( r
== WAIT_FAILED
, "should fail\n");
95 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
96 ok( r
== WAIT_FAILED
, "should fail\n");
99 /* valid parameters */
100 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
101 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
103 /* event[0] is now signalled - we repeat this test multiple times
104 * to ensure that the wineserver handles this situation properly. */
105 for (i
= 0; i
< 10000; i
++)
107 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
108 ok(r
== WAIT_OBJECT_0
, "should succeed\n");
111 /* event[0] is not signalled */
112 r
= WaitForSingleObject(event
[0], 0);
113 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
115 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
116 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
118 /* clear event[1] and check for a timeout */
119 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
120 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
121 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
123 CloseHandle(event
[0]);
124 CloseHandle(event
[1]);
127 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
128 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
129 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
131 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
132 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
134 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
135 ok( r
== WAIT_FAILED
, "should fail\n");
137 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
138 ok( r
== FALSE
, "should fail\n");
140 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
141 ok( r
== TRUE
, "should succeed\n");
143 CloseHandle(semaphore
[0]);
144 CloseHandle(semaphore
[1]);
146 /* try a registry key */
147 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
148 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
149 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
150 ok( r
== WAIT_FAILED
, "should fail\n");
151 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
155 static void test_mutex(void)
164 SetLastError(0xdeadbeef);
165 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
166 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
167 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
169 SetLastError(0xdeadbeef);
170 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
171 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
173 SetLastError(0xdeadbeef);
174 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
176 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
178 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
180 SetLastError(0xdeadbeef);
181 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
182 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
183 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
184 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
185 CloseHandle(hOpened
);
187 for(i
=0; i
< 31; i
++)
189 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
190 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
193 SetLastError(0xdeadbeef);
194 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
195 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
196 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
197 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
198 CloseHandle(hOpened
);
200 for (i
= 0; i
< 32; i
++)
202 SetLastError(0xdeadbeef);
203 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
206 SetLastError(0xdeadbeef);
207 ret
= ReleaseMutex(hOpened
);
208 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
209 CloseHandle(hOpened
);
213 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
214 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
216 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
217 ReleaseMutex(hCreated
);
223 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
225 SetLastError(0xdeadbeef);
226 ret
= ReleaseMutex(hCreated
);
227 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
228 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
230 /* test case sensitivity */
232 SetLastError(0xdeadbeef);
233 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
234 ok(!hOpened
, "OpenMutex succeeded\n");
235 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
237 SetLastError(0xdeadbeef);
238 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
239 ok(!hOpened
, "OpenMutex succeeded\n");
240 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
242 SetLastError(0xdeadbeef);
243 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
244 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
245 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
246 CloseHandle(hOpened
);
248 SetLastError(0xdeadbeef);
249 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
250 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
251 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
252 CloseHandle(hOpened
);
254 CloseHandle(hCreated
);
257 static void test_slist(void)
263 } item1
, item2
, item3
, *pitem
;
265 SLIST_HEADER slist_header
;
266 PSLIST_ENTRY entry
, next
;
270 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
271 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
272 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
273 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
274 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
277 kernel32
= GetModuleHandleA("KERNEL32.DLL");
278 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
279 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
280 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
281 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
282 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
283 if (pInitializeSListHead
== NULL
||
284 pQueryDepthSList
== NULL
||
285 pInterlockedFlushSList
== NULL
||
286 pInterlockedPopEntrySList
== NULL
||
287 pInterlockedPushEntrySList
== NULL
)
289 win_skip("some required slist entrypoints were not found, skipping tests\n");
293 memset(&slist_header
, 0xFF, sizeof(slist_header
));
294 pInitializeSListHead(&slist_header
);
295 size
= pQueryDepthSList(&slist_header
);
296 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
299 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
300 "previous entry in empty slist wasn't NULL\n");
301 size
= pQueryDepthSList(&slist_header
);
302 ok(size
== 1, "slist with 1 item has size %d\n", size
);
305 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
306 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
309 pitem
= (struct item
*) entry
;
310 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
312 size
= pQueryDepthSList(&slist_header
);
313 ok(size
== 2, "slist with 2 items has size %d\n", size
);
316 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
317 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
320 pitem
= (struct item
*) entry
;
321 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
323 size
= pQueryDepthSList(&slist_header
);
324 ok(size
== 3, "slist with 3 items has size %d\n", size
);
326 entry
= pInterlockedPopEntrySList(&slist_header
);
327 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
330 pitem
= (struct item
*) entry
;
331 ok(pitem
->value
== 3, "unexpected entry removed\n");
333 size
= pQueryDepthSList(&slist_header
);
334 ok(size
== 2, "slist with 2 items has size %d\n", size
);
336 entry
= pInterlockedFlushSList(&slist_header
);
337 size
= pQueryDepthSList(&slist_header
);
338 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
341 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
342 "popping empty slist didn't return NULL\n");
344 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
345 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
347 for (i
= 0; i
< 65536; i
++)
349 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
350 pInterlockedPushEntrySList(&slist_header
, entry
);
353 entry
= pInterlockedFlushSList(&slist_header
);
354 ok(entry
!= NULL
, "not flushed\n");
358 HeapFree(GetProcessHeap(), 0, entry
);
363 static void test_event(void)
365 HANDLE handle
, handle2
;
366 SECURITY_ATTRIBUTES sa
;
367 SECURITY_DESCRIPTOR sd
;
373 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
374 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
377 sa
.nLength
= sizeof(sa
);
378 sa
.lpSecurityDescriptor
= &sd
;
379 sa
.bInheritHandle
= FALSE
;
381 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
384 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
385 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
388 /* sd with NULL dacl */
389 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
390 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
391 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
394 /* sd with empty dacl */
395 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
396 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
397 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
398 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
401 /* test case sensitivity */
403 SetLastError(0xdeadbeef);
404 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
405 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
406 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
408 SetLastError(0xdeadbeef);
409 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
410 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
411 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
412 CloseHandle( handle2
);
414 SetLastError(0xdeadbeef);
415 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
416 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
417 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
418 CloseHandle( handle2
);
420 SetLastError(0xdeadbeef);
421 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
422 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
423 CloseHandle( handle2
);
425 SetLastError(0xdeadbeef);
426 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
427 ok( !handle2
, "OpenEvent succeeded\n");
428 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
430 CloseHandle( handle
);
432 /* resource notifications are events too */
434 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
436 trace( "memory resource notifications not supported\n" );
439 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
440 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
441 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
442 ret
= pQueryMemoryResourceNotification( handle
, &val
);
443 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
444 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
446 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
447 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
448 ret
= WaitForSingleObject( handle
, 10 );
449 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
452 ret
= pQueryMemoryResourceNotification( handle
, &val
);
453 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
454 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
455 ret
= CloseHandle( handle
);
456 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
458 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
460 ret
= pQueryMemoryResourceNotification( handle
, &val
);
461 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
462 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
463 CloseHandle( handle
);
466 static void test_semaphore(void)
468 HANDLE handle
, handle2
;
470 /* test case sensitivity */
472 SetLastError(0xdeadbeef);
473 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
474 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
475 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
477 SetLastError(0xdeadbeef);
478 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
479 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
480 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
481 CloseHandle( handle2
);
483 SetLastError(0xdeadbeef);
484 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
485 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
486 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
487 CloseHandle( handle2
);
489 SetLastError(0xdeadbeef);
490 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
491 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
492 CloseHandle( handle2
);
494 SetLastError(0xdeadbeef);
495 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
496 ok( !handle2
, "OpenSemaphore succeeded\n");
497 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
499 CloseHandle( handle
);
502 static void test_waitable_timer(void)
504 HANDLE handle
, handle2
;
506 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
508 win_skip("{Create,Open}WaitableTimerA() is not available\n");
512 /* test case sensitivity */
514 SetLastError(0xdeadbeef);
515 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
516 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
517 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
519 SetLastError(0xdeadbeef);
520 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
521 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
522 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
523 CloseHandle( handle2
);
525 SetLastError(0xdeadbeef);
526 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
527 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
528 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
529 CloseHandle( handle2
);
531 SetLastError(0xdeadbeef);
532 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
533 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
534 CloseHandle( handle2
);
536 SetLastError(0xdeadbeef);
537 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
538 ok( !handle2
, "OpenWaitableTimer succeeded\n");
539 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
540 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
541 "wrong error %u\n", GetLastError());
543 CloseHandle( handle
);
546 static HANDLE sem
= 0;
548 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
550 ReleaseSemaphore(sem
, 1, NULL
);
553 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
555 static void test_iocp_callback(void)
557 char temp_path
[MAX_PATH
];
558 char filename
[MAX_PATH
];
561 static const char prefix
[] = "pfx";
563 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
565 const char *buffer
= "12345678123456781234567812345678";
566 OVERLAPPED overlapped
;
568 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
569 if(!p_BindIoCompletionCallback
) {
570 win_skip("BindIoCompletionCallback not found in this DLL\n");
574 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
575 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
577 ret
= GetTempPathA(MAX_PATH
, temp_path
);
578 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
579 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
581 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
582 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
584 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
585 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
586 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
588 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
589 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
590 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
592 ret
= CloseHandle(hFile
);
593 ok( ret
, "CloseHandle: error %d\n", GetLastError());
594 ret
= DeleteFileA(filename
);
595 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
597 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
598 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
599 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
601 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
602 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
604 memset(&overlapped
, 0, sizeof(overlapped
));
605 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
606 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
608 ret
= WaitForSingleObject(sem
, 5000);
609 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
612 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
613 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
614 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
615 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
616 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
617 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
619 ret
= CloseHandle(hFile
);
620 ok( ret
, "CloseHandle: error %d\n", GetLastError());
621 ret
= DeleteFileA(filename
);
622 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
624 /* win2k3 requires the Flags parameter to be zero */
625 SetLastError(0xdeadbeef);
626 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
627 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
628 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
629 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
631 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
632 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
634 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
635 ret
= CloseHandle(hFile
);
636 ok( ret
, "CloseHandle: error %d\n", GetLastError());
637 ret
= DeleteFileA(filename
);
638 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
640 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
641 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
642 ok(GetLastError() == ERROR_INVALID_HANDLE
||
643 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
644 "Last error is %d\n", GetLastError());
647 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
650 ok(timedOut
, "Timer callbacks should always time out\n");
654 struct timer_queue_data1
661 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
663 struct timer_queue_data1
*d
= p
;
664 ok(timedOut
, "Timer callbacks should always time out\n");
665 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
668 SetLastError(0xdeadbeef);
669 /* Note, XP SP2 does *not* do any deadlock checking, so passing
670 INVALID_HANDLE_VALUE here will just hang. */
671 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
672 ok(!ret
, "DeleteTimerQueueTimer\n");
673 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
677 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
679 struct timer_queue_data1
*d
= p
;
680 ok(timedOut
, "Timer callbacks should always time out\n");
681 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
683 /* Basically kill the timer since it won't have time to run
685 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
686 ok(ret
, "ChangeTimerQueueTimer\n");
690 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
692 struct timer_queue_data1
*d
= p
;
693 ok(timedOut
, "Timer callbacks should always time out\n");
696 /* This tests whether a timer gets flagged for deletion before
697 or after the callback runs. If we start this timer with a
698 period of zero (run once), then ChangeTimerQueueTimer will
699 fail if the timer is already flagged. Hence we really run
700 only once. Otherwise we will run multiple times. */
701 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
702 ok(ret
, "ChangeTimerQueueTimer\n");
707 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
709 DWORD_PTR delay
= (DWORD_PTR
) p
;
710 ok(timedOut
, "Timer callbacks should always time out\n");
715 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
717 struct timer_queue_data1
*d
= p
;
718 ok(timedOut
, "Timer callbacks should always time out\n");
719 /* This tests an original implementation bug where a deleted timer may get
720 to run, but it is tricky to set up. */
721 if (d
->q
&& d
->num_calls
++ == 0)
723 /* First run: delete ourselves, then insert and remove a timer
724 that goes in front of us in the sorted timeout list. Once
725 removed, we will still timeout at the faster timer's due time,
726 but this should be a no-op if we are bug-free. There should
727 not be a second run. We can test the value of num_calls later. */
731 /* The delete will pend while we are in this callback. */
732 SetLastError(0xdeadbeef);
733 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
734 ok(!ret
, "DeleteTimerQueueTimer\n");
735 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
737 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
738 ok(ret
, "CreateTimerQueueTimer\n");
739 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
741 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
742 ok(ret
, "DeleteTimerQueueTimer\n");
744 /* Now we stay alive by hanging around in the callback. */
749 static void test_timer_queue(void)
751 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
752 int n0
, n1
, n2
, n3
, n4
, n5
;
753 struct timer_queue_data1 d1
, d2
, d3
, d4
;
757 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
758 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
760 win_skip("TimerQueue API not present\n");
764 /* Test asynchronous deletion of the queue. */
765 q
= pCreateTimerQueue();
766 ok(q
!= NULL
, "CreateTimerQueue\n");
768 SetLastError(0xdeadbeef);
769 ret
= pDeleteTimerQueueEx(q
, NULL
);
770 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
771 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
774 /* Test synchronous deletion of the queue and running timers. */
775 q
= pCreateTimerQueue();
776 ok(q
!= NULL
, "CreateTimerQueue\n");
781 ret
= pCreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0,
783 ok(ret
, "CreateTimerQueueTimer\n");
784 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
785 ret0
= pDeleteTimerQueueTimer(q
, t0
, NULL
);
786 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
787 broken(ret0
), /* Win 2000 & XP & 2003 */
788 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
793 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
795 ok(ret
, "CreateTimerQueueTimer\n");
796 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
801 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
803 ok(ret
, "CreateTimerQueueTimer\n");
804 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
809 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
811 ok(ret
, "CreateTimerQueueTimer\n");
812 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
814 /* Start really late (it won't start). */
817 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
819 ok(ret
, "CreateTimerQueueTimer\n");
820 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
822 /* Start soon, but delay so long it won't run again. */
825 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
827 ok(ret
, "CreateTimerQueueTimer\n");
828 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
830 /* Give them a chance to do some work. */
833 /* Test deleting a once-only timer. */
834 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
835 ok(ret
, "DeleteTimerQueueTimer\n");
837 /* A periodic timer. */
838 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
839 ok(ret
, "DeleteTimerQueueTimer\n");
841 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
842 ok(ret
, "DeleteTimerQueueEx\n");
844 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
845 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
846 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
847 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
848 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
850 /* Test synchronous deletion of the timer/queue with event trigger. */
851 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
852 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
853 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
854 if (!e
|| !et1
|| !et2
)
856 skip("Failed to create timer queue descruction event\n");
860 q
= pCreateTimerQueue();
861 ok(q
!= NULL
, "CreateTimerQueue\n");
863 /* Run once and finish quickly (should be done when we delete it). */
865 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
866 ok(ret
, "CreateTimerQueueTimer\n");
867 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
869 /* Run once and finish slowly (shouldn't be done when we delete it). */
871 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
873 ok(ret
, "CreateTimerQueueTimer\n");
874 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
876 /* Run once and finish quickly (should be done when we delete it). */
878 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
879 ok(ret
, "CreateTimerQueueTimer\n");
880 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
882 /* Run once and finish slowly (shouldn't be done when we delete it). */
884 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
886 ok(ret
, "CreateTimerQueueTimer\n");
887 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
889 /* Give them a chance to start. */
892 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
893 even if the timer is finished. */
894 SetLastError(0xdeadbeef);
895 ret
= pDeleteTimerQueueTimer(q
, t1
, NULL
);
896 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
897 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
900 SetLastError(0xdeadbeef);
901 ret
= pDeleteTimerQueueTimer(q
, t2
, NULL
);
902 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
903 ok(GetLastError() == ERROR_IO_PENDING
,
904 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
907 SetLastError(0xdeadbeef);
908 ret
= pDeleteTimerQueueTimer(q
, t3
, et1
);
909 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
910 ok(GetLastError() == 0xdeadbeef,
911 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
913 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
914 "Timer destruction event not triggered\n");
916 SetLastError(0xdeadbeef);
917 ret
= pDeleteTimerQueueTimer(q
, t4
, et2
);
918 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
919 ok(GetLastError() == ERROR_IO_PENDING
,
920 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
922 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
923 "Timer destruction event not triggered\n");
925 SetLastError(0xdeadbeef);
926 ret
= pDeleteTimerQueueEx(q
, e
);
927 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
928 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
930 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
931 "Queue destruction event not triggered\n");
934 /* Test deleting/changing a timer in execution. */
935 q
= pCreateTimerQueue();
936 ok(q
!= NULL
, "CreateTimerQueue\n");
938 /* Test changing a once-only timer before it fires (this is allowed,
939 whereas after it fires you cannot). */
941 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
943 ok(ret
, "CreateTimerQueueTimer\n");
944 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
945 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
946 ok(ret
, "ChangeTimerQueueTimer\n");
952 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
955 ok(ret
, "CreateTimerQueueTimer\n");
956 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
962 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
965 ok(ret
, "CreateTimerQueueTimer\n");
966 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
971 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
974 ok(ret
, "CreateTimerQueueTimer\n");
975 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
979 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
980 ok(ret
, "DeleteTimerQueueEx\n");
981 ok(n1
== 1, "ChangeTimerQueueTimer\n");
982 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
983 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
984 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
986 /* Test an obscure bug that was in the original implementation. */
987 q
= pCreateTimerQueue();
988 ok(q
!= NULL
, "CreateTimerQueue\n");
990 /* All the work is done in the callback. */
994 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
995 100, WT_EXECUTELONGFUNCTION
);
997 ok(ret
, "CreateTimerQueueTimer\n");
998 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1002 SetLastError(0xdeadbeef);
1003 ret
= pDeleteTimerQueueEx(q
, NULL
);
1004 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1005 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1007 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1009 /* Test functions on the default timer queue. */
1012 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
1014 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1015 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1017 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1018 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1020 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1021 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1023 /* Try mixing default and non-default queues. Apparently this works. */
1024 q
= pCreateTimerQueue();
1025 ok(q
!= NULL
, "CreateTimerQueue\n");
1029 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
1031 ok(ret
, "CreateTimerQueueTimer\n");
1032 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1036 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
1038 ok(ret
, "CreateTimerQueueTimer\n");
1039 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1041 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1042 ok(ret
, "ChangeTimerQueueTimer\n");
1044 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1045 ok(ret
, "ChangeTimerQueueTimer\n");
1047 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1048 ok(ret
, "DeleteTimerQueueTimer\n");
1050 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1051 ok(ret
, "DeleteTimerQueueTimer\n");
1053 /* Try to delete the default queue? In any case: not allowed. */
1054 SetLastError(0xdeadbeef);
1055 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
1056 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1057 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1058 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1061 SetLastError(0xdeadbeef);
1062 ret
= pDeleteTimerQueueEx(q
, NULL
);
1063 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1064 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1068 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1070 DWORD tmp
= HandleToULong(handle
);
1072 return ULongToHandle(tmp
);
1075 static void test_WaitForSingleObject(void)
1077 HANDLE signaled
, nonsignaled
, invalid
;
1080 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1081 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1082 invalid
= (HANDLE
) 0xdeadbee0;
1084 /* invalid handle with different values for lower 2 bits */
1085 SetLastError(0xdeadbeef);
1086 ret
= WaitForSingleObject(invalid
, 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
, 1), 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 SetLastError(0xdeadbeef);
1096 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1097 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1098 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1100 SetLastError(0xdeadbeef);
1101 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1102 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1103 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1105 /* valid handle with different values for lower 2 bits */
1106 SetLastError(0xdeadbeef);
1107 ret
= WaitForSingleObject(nonsignaled
, 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
, 1), 0);
1113 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1114 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1116 SetLastError(0xdeadbeef);
1117 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1118 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1119 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1121 SetLastError(0xdeadbeef);
1122 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1123 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1124 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1126 /* valid handle with different values for lower 2 bits */
1127 SetLastError(0xdeadbeef);
1128 ret
= WaitForSingleObject(signaled
, 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
, 1), 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 SetLastError(0xdeadbeef);
1138 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1139 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1140 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1142 SetLastError(0xdeadbeef);
1143 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1144 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1145 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1147 CloseHandle(signaled
);
1148 CloseHandle(nonsignaled
);
1151 static void test_WaitForMultipleObjects(void)
1155 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1157 /* create the maximum number of events and make sure
1158 * we can wait on that many */
1159 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1161 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1162 ok( maxevents
[i
] != 0, "should create enough events\n");
1165 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1166 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1167 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1168 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1169 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1170 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1171 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1173 /* the lowest index is checked first and remaining events are untouched */
1174 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1175 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1178 /* run same test with Nt* call */
1179 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1180 SetEvent(maxevents
[i
]);
1182 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1183 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1184 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1185 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1186 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1187 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1188 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1190 /* the lowest index is checked first and remaining events are untouched */
1191 r
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1192 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1195 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1196 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1199 static BOOL g_initcallback_ret
, g_initcallback_called
;
1200 static void *g_initctxt
;
1202 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1204 g_initcallback_called
= TRUE
;
1205 /* zero bit set means here that initialization is taking place - initialization locked */
1206 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1207 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1208 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1209 return g_initcallback_ret
;
1212 static void test_initonce(void)
1217 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1219 win_skip("one-time initialization API not supported\n");
1223 /* blocking initialization with callback */
1224 initonce
.Ptr
= (void*)0xdeadbeef;
1225 pInitOnceInitialize(&initonce
);
1226 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1228 /* initialisation completed successfully */
1229 g_initcallback_ret
= TRUE
;
1231 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1232 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1233 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1234 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1235 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1237 /* so it's been called already so won't be called again */
1239 g_initcallback_called
= FALSE
;
1240 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1241 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1242 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1243 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1244 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1246 pInitOnceInitialize(&initonce
);
1247 g_initcallback_called
= FALSE
;
1248 /* 2 lower order bits should never be used, you'll get a crash in result */
1249 g_initctxt
= (void*)0xFFFFFFF0;
1250 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1251 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1252 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1253 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1254 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1256 /* callback failed */
1257 g_initcallback_ret
= FALSE
;
1258 g_initcallback_called
= FALSE
;
1260 pInitOnceInitialize(&initonce
);
1261 SetLastError( 0xdeadbeef );
1262 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1263 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1264 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1265 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1266 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1268 /* blocking initialization without a callback */
1269 pInitOnceInitialize(&initonce
);
1272 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1273 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1274 ok(pending
, "got %d\n", pending
);
1275 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1276 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1277 /* another attempt to begin initialization with block a single thread */
1281 SetLastError( 0xdeadbeef );
1282 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1283 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1284 ok(pending
== 0xf, "got %d\n", pending
);
1285 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1286 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1288 g_initctxt
= (void*)0xdeadbee0;
1289 SetLastError( 0xdeadbeef );
1290 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1291 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1292 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1294 /* once failed already */
1295 g_initctxt
= (void*)0xdeadbee0;
1296 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1297 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1298 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1300 pInitOnceInitialize(&initonce
);
1301 SetLastError( 0xdeadbeef );
1302 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1303 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1304 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1306 SetLastError( 0xdeadbeef );
1307 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1308 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1309 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1311 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1312 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1313 ok(pending
, "got %d\n", pending
);
1314 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1316 SetLastError( 0xdeadbeef );
1317 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1318 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1320 SetLastError( 0xdeadbeef );
1321 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1322 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1323 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1325 SetLastError( 0xdeadbeef );
1326 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1327 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1328 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1330 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1331 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1332 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1334 pInitOnceInitialize(&initonce
);
1335 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1336 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1337 ok(pending
, "got %d\n", pending
);
1338 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1340 SetLastError( 0xdeadbeef );
1341 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1342 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1344 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1345 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1346 ok(pending
, "got %d\n", pending
);
1347 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1349 SetLastError( 0xdeadbeef );
1350 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1351 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1352 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1354 SetLastError( 0xdeadbeef );
1355 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1356 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1357 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1359 SetLastError( 0xdeadbeef );
1360 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1361 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1362 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1364 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1365 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1366 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1368 SetLastError( 0xdeadbeef );
1369 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1370 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1371 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1373 pInitOnceInitialize(&initonce
);
1374 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1375 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1376 ok(pending
, "got %d\n", pending
);
1377 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1379 /* test INIT_ONCE_CHECK_ONLY */
1381 pInitOnceInitialize(&initonce
);
1382 SetLastError( 0xdeadbeef );
1383 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1384 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1385 SetLastError( 0xdeadbeef );
1386 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1387 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1389 ret
= pInitOnceBeginInitialize(&initonce
, 0, &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*)1, "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
, 0, (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());
1415 pInitOnceInitialize(&initonce
);
1416 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1417 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1418 ok(pending
, "got %d\n", pending
);
1419 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1421 SetLastError( 0xdeadbeef );
1422 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1423 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1424 SetLastError( 0xdeadbeef );
1425 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1426 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1428 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1429 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1430 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1432 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1433 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1434 ok(!pending
, "got %d\n", pending
);
1435 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1436 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1438 SetLastError( 0xdeadbeef );
1439 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1440 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1443 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1444 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1445 static CRITICAL_SECTION buffercrit
;
1446 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1447 static LONG bufferlen
,totalproduced
,totalconsumed
;
1448 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1450 #define BUFFER_SIZE 5
1452 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1453 DWORD sleepinterval
= 5;
1456 Sleep(sleepinterval
);
1457 if (sleepinterval
> 1)
1460 EnterCriticalSection(&buffercrit
);
1461 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1462 condvar_producer_sleepcnt
++;
1463 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1464 if (GetLastError() != ERROR_TIMEOUT
)
1465 condvar_sleeperr
= TRUE
;
1469 LeaveCriticalSection(&buffercrit
);
1474 LeaveCriticalSection(&buffercrit
);
1475 pWakeConditionVariable(&buffernotempty
);
1480 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1481 DWORD
*cnt
= (DWORD
*)x
;
1482 DWORD sleepinterval
= 1;
1485 EnterCriticalSection(&buffercrit
);
1486 while ((bufferlen
== 0) && !condvar_stop
) {
1487 condvar_consumer_sleepcnt
++;
1488 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1489 if (GetLastError() != ERROR_TIMEOUT
)
1490 condvar_sleeperr
= TRUE
;
1493 if (condvar_stop
&& (bufferlen
== 0)) {
1494 LeaveCriticalSection(&buffercrit
);
1500 LeaveCriticalSection(&buffercrit
);
1501 pWakeConditionVariable(&buffernotfull
);
1502 Sleep(sleepinterval
);
1503 if (sleepinterval
< 5) sleepinterval
+= 1;
1508 static void test_condvars_consumer_producer(void)
1510 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1512 DWORD cnt1
,cnt2
,cnt3
;
1514 if (!pInitializeConditionVariable
) {
1515 /* function is not yet in XP, only in newer Windows */
1516 win_skip("no condition variable support.\n");
1520 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1522 /* If we have static initialized condition variables, InitializeConditionVariable
1523 * is not strictly necessary.
1524 * pInitializeConditionVariable(&buffernotfull);
1526 pInitializeConditionVariable(&buffernotempty
);
1527 InitializeCriticalSection(&buffercrit
);
1529 /* Larger Test: consumer/producer example */
1531 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1533 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1534 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1535 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1536 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1537 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1538 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1540 /* Limit run to 0.5 seconds. */
1543 /* tear down start */
1544 condvar_stop
= TRUE
;
1546 /* final wake up call */
1547 pWakeAllConditionVariable (&buffernotfull
);
1548 pWakeAllConditionVariable (&buffernotempty
);
1550 /* (mostly an implementation detail)
1551 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1554 WaitForSingleObject(hp1
, 1000);
1555 WaitForSingleObject(hp2
, 1000);
1556 WaitForSingleObject(hp3
, 1000);
1557 WaitForSingleObject(hc1
, 1000);
1558 WaitForSingleObject(hc2
, 1000);
1559 WaitForSingleObject(hc3
, 1000);
1561 ok(totalconsumed
== totalproduced
,
1562 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1563 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1565 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1566 * one consumer does not get anything to do is possible. */
1567 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1568 /* The sleeps of the producer or consumer should not go above 100* produced count,
1569 * otherwise the implementation does not sleep correctly. But yet again, this is
1570 * not hard defined. */
1571 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1574 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1575 static DWORD condvar_seq
= 0;
1576 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1577 static CRITICAL_SECTION condvar_crit
;
1578 static SRWLOCK condvar_srwlock
;
1580 /* Sequence of wake/sleep to check boundary conditions:
1582 * 1: producer emits a WakeConditionVaribale without consumer waiting.
1583 * 2: consumer sleeps without a wake expecting timeout
1584 * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
1585 * 4: consumer sleeps without a wake expecting timeout
1586 * 5: a wake is handed to a SleepConditionVariableCS
1587 * 6: a wakeall is handed to a SleepConditionVariableCS
1588 * 7: sleep after above should timeout
1589 * 8: wake with crit section locked into the sleep timeout
1591 * the following tests will only be executed if InitializeSRWLock is available
1593 * 9: producer (exclusive) wakes up consumer (exclusive)
1594 * 10: producer (exclusive) wakes up consumer (shared)
1595 * 11: producer (shared) wakes up consumer (exclusive)
1596 * 12: producer (shared) wakes up consumer (shared)
1599 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1600 while (condvar_seq
< 1) Sleep(1);
1602 pWakeConditionVariable (&condvar_base
);
1605 while (condvar_seq
< 3) Sleep(1);
1606 pWakeAllConditionVariable (&condvar_base
);
1609 while (condvar_seq
< 5) Sleep(1);
1610 EnterCriticalSection (&condvar_crit
);
1611 pWakeConditionVariable (&condvar_base
);
1612 LeaveCriticalSection (&condvar_crit
);
1613 while (condvar_seq
< 6) Sleep(1);
1614 EnterCriticalSection (&condvar_crit
);
1615 pWakeAllConditionVariable (&condvar_base
);
1616 LeaveCriticalSection (&condvar_crit
);
1618 while (condvar_seq
< 8) Sleep(1);
1619 EnterCriticalSection (&condvar_crit
);
1620 pWakeConditionVariable (&condvar_base
);
1622 LeaveCriticalSection (&condvar_crit
);
1624 /* skip over remaining tests if InitializeSRWLock is not available */
1625 if (!pInitializeSRWLock
)
1628 while (condvar_seq
< 9) Sleep(1);
1629 pAcquireSRWLockExclusive(&condvar_srwlock
);
1630 pWakeConditionVariable(&condvar_base
);
1631 pReleaseSRWLockExclusive(&condvar_srwlock
);
1633 while (condvar_seq
< 10) Sleep(1);
1634 pAcquireSRWLockExclusive(&condvar_srwlock
);
1635 pWakeConditionVariable(&condvar_base
);
1636 pReleaseSRWLockExclusive(&condvar_srwlock
);
1638 while (condvar_seq
< 11) Sleep(1);
1639 pAcquireSRWLockShared(&condvar_srwlock
);
1640 pWakeConditionVariable(&condvar_base
);
1641 pReleaseSRWLockShared(&condvar_srwlock
);
1643 while (condvar_seq
< 12) Sleep(1);
1644 Sleep(50); /* ensure that consumer waits for cond variable */
1645 pAcquireSRWLockShared(&condvar_srwlock
);
1646 pWakeConditionVariable(&condvar_base
);
1647 pReleaseSRWLockShared(&condvar_srwlock
);
1652 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1655 while (condvar_seq
< 2) Sleep(1);
1657 /* wake was emitted, but we were not sleeping */
1658 EnterCriticalSection (&condvar_crit
);
1659 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1660 LeaveCriticalSection (&condvar_crit
);
1661 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1662 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1665 while (condvar_seq
< 4) Sleep(1);
1667 /* wake all was emitted, but we were not sleeping */
1668 EnterCriticalSection (&condvar_crit
);
1669 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1670 LeaveCriticalSection (&condvar_crit
);
1671 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1672 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1674 EnterCriticalSection (&condvar_crit
);
1676 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1677 LeaveCriticalSection (&condvar_crit
);
1678 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1680 EnterCriticalSection (&condvar_crit
);
1682 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1683 LeaveCriticalSection (&condvar_crit
);
1684 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1687 EnterCriticalSection (&condvar_crit
);
1688 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1689 LeaveCriticalSection (&condvar_crit
);
1690 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1691 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1693 EnterCriticalSection (&condvar_crit
);
1695 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1696 LeaveCriticalSection (&condvar_crit
);
1697 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1699 /* skip over remaining tests if InitializeSRWLock is not available */
1700 if (!pInitializeSRWLock
)
1702 win_skip("no srw lock support.\n");
1703 condvar_seq
= 13; /* end */
1707 pAcquireSRWLockExclusive(&condvar_srwlock
);
1709 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1710 pReleaseSRWLockExclusive(&condvar_srwlock
);
1711 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1713 pAcquireSRWLockShared(&condvar_srwlock
);
1715 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1716 pReleaseSRWLockShared(&condvar_srwlock
);
1717 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1719 pAcquireSRWLockExclusive(&condvar_srwlock
);
1721 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1722 pReleaseSRWLockExclusive(&condvar_srwlock
);
1723 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1725 pAcquireSRWLockShared(&condvar_srwlock
);
1727 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1728 pReleaseSRWLockShared(&condvar_srwlock
);
1729 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1735 static void test_condvars_base(void) {
1741 if (!pInitializeConditionVariable
) {
1742 /* function is not yet in XP, only in newer Windows */
1743 win_skip("no condition variable support.\n");
1747 InitializeCriticalSection (&condvar_crit
);
1749 if (pInitializeSRWLock
)
1750 pInitializeSRWLock(&condvar_srwlock
);
1752 EnterCriticalSection (&condvar_crit
);
1753 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1754 LeaveCriticalSection (&condvar_crit
);
1756 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1757 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1759 if (pInitializeSRWLock
)
1761 pAcquireSRWLockExclusive(&condvar_srwlock
);
1762 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1763 pReleaseSRWLockExclusive(&condvar_srwlock
);
1765 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1766 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1768 pAcquireSRWLockShared(&condvar_srwlock
);
1769 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1770 pReleaseSRWLockShared(&condvar_srwlock
);
1772 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1773 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1777 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1778 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1780 condvar_seq
= 1; /* go */
1782 while (condvar_seq
< 9)
1784 WaitForSingleObject(hp
, 100);
1785 WaitForSingleObject(hc
, 100);
1788 static LONG srwlock_seq
= 0;
1789 static SRWLOCK srwlock_base
;
1792 LONG wrong_execution_order
;
1793 LONG samethread_excl_excl
;
1794 LONG samethread_excl_shared
;
1795 LONG samethread_shared_excl
;
1796 LONG multithread_excl_excl
;
1797 LONG excl_not_preferred
;
1799 LONG trylock_shared
;
1800 } srwlock_base_errors
;
1802 /* Sequence of acquire/release to check boundary conditions:
1805 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1806 * 2: thread1 expects a deadlock and releases the waiting lock
1807 * thread2 releases the lock again
1809 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1810 * 4: thread1 expects a deadlock and releases the waiting lock
1811 * thread2 releases the lock again
1813 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1814 * 6: thread1 expects a deadlock and releases the waiting lock
1815 * thread2 releases the lock again
1817 * 7: thread2 acquires and releases two nested shared locks
1819 * 8: thread1 acquires an exclusive lock
1820 * 9: thread2 tries to acquire the exclusive lock, too
1821 * thread1 releases the exclusive lock again
1822 * 10: thread2 enters the exclusive lock and leaves it immediately again
1824 * 11: thread1 acquires a shared lock
1825 * 12: thread2 acquires and releases a shared lock
1826 * thread1 releases the lock again
1828 * 13: thread1 acquires a shared lock
1829 * 14: thread2 tries to acquire an exclusive lock
1830 * 15: thread3 tries to acquire a shared lock
1831 * 16: thread1 releases the shared lock
1832 * 17: thread2 wakes up and releases the exclusive lock
1833 * 18: thread3 wakes up and releases the shared lock
1835 * the following tests will only be executed if TryAcquireSRWLock* is available
1837 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1838 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1839 * thread1 releases the exclusive lock
1841 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1842 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1843 * thread1 releases the shared lock
1845 * thread1 acquires an exclusive lock
1846 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1847 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1848 * 21: thread1 releases the exclusive lock
1850 * thread1 acquires an shared lock
1851 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
1852 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1853 * 23: thread1 releases the shared lock
1855 * thread1 acquires a shared lock and tries to acquire an exclusive lock
1856 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
1857 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1858 * 25: thread1 releases the exclusive lock
1860 * thread1 acquires two shared locks
1861 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
1862 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1863 * 27: thread1 releases one shared lock
1864 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
1865 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1866 * 29: thread1 releases the second shared lock
1867 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
1868 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
1873 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
1876 while (srwlock_seq
< 2) Sleep(1);
1878 if (InterlockedIncrement(&srwlock_seq
) != 3)
1879 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
1880 pReleaseSRWLockExclusive(&srwlock_base
);
1883 while (srwlock_seq
< 4) Sleep(1);
1885 if (InterlockedIncrement(&srwlock_seq
) != 5)
1886 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
1887 pReleaseSRWLockExclusive(&srwlock_base
);
1890 while (srwlock_seq
< 6) Sleep(1);
1892 if (InterlockedIncrement(&srwlock_seq
) != 7)
1893 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
1894 pReleaseSRWLockShared(&srwlock_base
);
1897 while (srwlock_seq
< 8) Sleep(1);
1898 pAcquireSRWLockExclusive(&srwlock_base
);
1899 if (InterlockedIncrement(&srwlock_seq
) != 9)
1900 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1902 if (InterlockedIncrement(&srwlock_seq
) != 10)
1903 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
1904 pReleaseSRWLockExclusive(&srwlock_base
);
1907 while (srwlock_seq
< 11) Sleep(1);
1908 pAcquireSRWLockShared(&srwlock_base
);
1909 if (InterlockedIncrement(&srwlock_seq
) != 12)
1910 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1913 while (srwlock_seq
< 13) Sleep(1);
1914 pReleaseSRWLockShared(&srwlock_base
);
1915 pAcquireSRWLockShared(&srwlock_base
);
1916 if (InterlockedIncrement(&srwlock_seq
) != 14)
1917 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1920 while (srwlock_seq
< 16) Sleep(1);
1921 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
1922 if (InterlockedIncrement(&srwlock_seq
) != 17)
1923 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1924 pReleaseSRWLockShared(&srwlock_base
);
1926 /* skip over remaining tests if TryAcquireSRWLock* is not available */
1927 if (!pTryAcquireSRWLockExclusive
)
1931 while (srwlock_seq
< 19) Sleep(1);
1932 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1934 if (pTryAcquireSRWLockShared(&srwlock_base
))
1935 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1936 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1937 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1938 pReleaseSRWLockExclusive(&srwlock_base
);
1941 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1943 if (pTryAcquireSRWLockShared(&srwlock_base
))
1945 if (pTryAcquireSRWLockShared(&srwlock_base
))
1946 pReleaseSRWLockShared(&srwlock_base
);
1948 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1949 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
1950 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
1951 pReleaseSRWLockShared(&srwlock_base
);
1954 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
1956 pAcquireSRWLockExclusive(&srwlock_base
);
1957 if (InterlockedIncrement(&srwlock_seq
) != 20)
1958 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1961 while (srwlock_seq
< 21) Sleep(1);
1962 pReleaseSRWLockExclusive(&srwlock_base
);
1963 pAcquireSRWLockShared(&srwlock_base
);
1964 if (InterlockedIncrement(&srwlock_seq
) != 22)
1965 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1968 while (srwlock_seq
< 23) Sleep(1);
1969 pReleaseSRWLockShared(&srwlock_base
);
1970 pAcquireSRWLockShared(&srwlock_base
);
1971 if (InterlockedIncrement(&srwlock_seq
) != 24)
1972 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1975 pAcquireSRWLockExclusive(&srwlock_base
);
1976 if (srwlock_seq
!= 25)
1977 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1978 pReleaseSRWLockExclusive(&srwlock_base
);
1980 pAcquireSRWLockShared(&srwlock_base
);
1981 pAcquireSRWLockShared(&srwlock_base
);
1982 if (InterlockedIncrement(&srwlock_seq
) != 26)
1983 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1986 while (srwlock_seq
< 27) Sleep(1);
1987 pReleaseSRWLockShared(&srwlock_base
);
1988 if (InterlockedIncrement(&srwlock_seq
) != 28)
1989 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
1992 while (srwlock_seq
< 29) Sleep(1);
1993 pReleaseSRWLockShared(&srwlock_base
);
1994 if (InterlockedIncrement(&srwlock_seq
) != 30)
1995 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2000 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
2003 while (srwlock_seq
< 1) Sleep(1);
2004 pAcquireSRWLockExclusive(&srwlock_base
);
2005 if (InterlockedIncrement(&srwlock_seq
) != 2)
2006 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2009 pAcquireSRWLockExclusive(&srwlock_base
);
2010 if (srwlock_seq
!= 3)
2011 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2012 pReleaseSRWLockExclusive(&srwlock_base
);
2013 pAcquireSRWLockExclusive(&srwlock_base
);
2014 if (InterlockedIncrement(&srwlock_seq
) != 4)
2015 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2018 pAcquireSRWLockShared(&srwlock_base
);
2019 if (srwlock_seq
!= 5)
2020 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2021 pReleaseSRWLockShared(&srwlock_base
);
2022 pAcquireSRWLockShared(&srwlock_base
);
2023 if (InterlockedIncrement(&srwlock_seq
) != 6)
2024 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2027 pAcquireSRWLockExclusive(&srwlock_base
);
2028 if (srwlock_seq
!= 7)
2029 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2030 pReleaseSRWLockExclusive(&srwlock_base
);
2031 pAcquireSRWLockShared(&srwlock_base
);
2032 pAcquireSRWLockShared(&srwlock_base
);
2033 pReleaseSRWLockShared(&srwlock_base
);
2034 pReleaseSRWLockShared(&srwlock_base
);
2035 if (InterlockedIncrement(&srwlock_seq
) != 8)
2036 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2039 while (srwlock_seq
< 9) Sleep(1);
2040 pAcquireSRWLockExclusive(&srwlock_base
);
2041 if (srwlock_seq
!= 10)
2042 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2043 pReleaseSRWLockExclusive(&srwlock_base
);
2044 if (InterlockedIncrement(&srwlock_seq
) != 11)
2045 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2048 while (srwlock_seq
< 12) Sleep(1);
2049 pAcquireSRWLockShared(&srwlock_base
);
2050 pReleaseSRWLockShared(&srwlock_base
);
2051 if (InterlockedIncrement(&srwlock_seq
) != 13)
2052 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2055 while (srwlock_seq
< 14) Sleep(1);
2056 if (InterlockedIncrement(&srwlock_seq
) != 15)
2057 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2060 pAcquireSRWLockExclusive(&srwlock_base
);
2061 if (srwlock_seq
!= 17)
2062 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2063 if (InterlockedIncrement(&srwlock_seq
) != 18)
2064 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2065 pReleaseSRWLockExclusive(&srwlock_base
);
2067 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2068 if (!pTryAcquireSRWLockExclusive
)
2072 while (srwlock_seq
< 20) Sleep(1);
2073 if (pTryAcquireSRWLockShared(&srwlock_base
))
2074 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2075 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2076 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2077 if (InterlockedIncrement(&srwlock_seq
) != 21)
2078 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2081 while (srwlock_seq
< 22) Sleep(1);
2082 if (pTryAcquireSRWLockShared(&srwlock_base
))
2083 pReleaseSRWLockShared(&srwlock_base
);
2085 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2086 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2087 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2088 if (InterlockedIncrement(&srwlock_seq
) != 23)
2089 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2092 while (srwlock_seq
< 24) Sleep(1);
2093 Sleep(50); /* ensure that exclusive access request is queued */
2094 if (pTryAcquireSRWLockShared(&srwlock_base
))
2096 pReleaseSRWLockShared(&srwlock_base
);
2097 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2099 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2100 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2101 if (InterlockedIncrement(&srwlock_seq
) != 25)
2102 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2103 pReleaseSRWLockShared(&srwlock_base
);
2106 while (srwlock_seq
< 26) Sleep(1);
2107 if (pTryAcquireSRWLockShared(&srwlock_base
))
2108 pReleaseSRWLockShared(&srwlock_base
);
2110 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2111 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2112 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2113 if (InterlockedIncrement(&srwlock_seq
) != 27)
2114 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2117 while (srwlock_seq
< 28) Sleep(1);
2118 if (pTryAcquireSRWLockShared(&srwlock_base
))
2119 pReleaseSRWLockShared(&srwlock_base
);
2121 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2122 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2123 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2124 if (InterlockedIncrement(&srwlock_seq
) != 29)
2125 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2128 while (srwlock_seq
< 30) Sleep(1);
2129 if (pTryAcquireSRWLockShared(&srwlock_base
))
2130 pReleaseSRWLockShared(&srwlock_base
);
2132 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2133 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2134 pReleaseSRWLockExclusive(&srwlock_base
);
2136 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2137 if (InterlockedIncrement(&srwlock_seq
) != 31)
2138 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2143 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2146 while (srwlock_seq
< 15) Sleep(1);
2147 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2148 if (InterlockedIncrement(&srwlock_seq
) != 16)
2149 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2152 pAcquireSRWLockShared(&srwlock_base
);
2153 if (srwlock_seq
!= 18)
2154 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2155 pReleaseSRWLockShared(&srwlock_base
);
2156 if (InterlockedIncrement(&srwlock_seq
) != 19)
2157 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2159 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2160 if (!pTryAcquireSRWLockExclusive
)
2162 /* function is only in Windows 7 and newer */
2163 win_skip("no srw trylock support.\n");
2164 srwlock_seq
= 31; /* end */
2171 static void test_srwlock_base(void)
2176 if (!pInitializeSRWLock
)
2178 /* function is not yet in XP, only in newer Windows */
2179 win_skip("no srw lock support.\n");
2183 pInitializeSRWLock(&srwlock_base
);
2184 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2186 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2187 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2188 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2190 srwlock_seq
= 1; /* go */
2191 while (srwlock_seq
< 31)
2194 WaitForSingleObject(h1
, 100);
2195 WaitForSingleObject(h2
, 100);
2196 WaitForSingleObject(h3
, 100);
2198 ok(!srwlock_base_errors
.wrong_execution_order
,
2199 "thread commands were executed in the wrong order (occurred %d times).\n",
2200 srwlock_base_errors
.wrong_execution_order
);
2202 ok(!srwlock_base_errors
.samethread_excl_excl
,
2203 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2204 srwlock_base_errors
.samethread_excl_excl
);
2206 ok(!srwlock_base_errors
.samethread_excl_shared
,
2207 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2208 srwlock_base_errors
.samethread_excl_shared
);
2210 ok(!srwlock_base_errors
.samethread_shared_excl
,
2211 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2212 srwlock_base_errors
.samethread_shared_excl
);
2214 ok(!srwlock_base_errors
.multithread_excl_excl
,
2215 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2216 srwlock_base_errors
.multithread_excl_excl
);
2218 ok(!srwlock_base_errors
.excl_not_preferred
,
2219 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2220 srwlock_base_errors
.excl_not_preferred
);
2222 ok(!srwlock_base_errors
.trylock_excl
,
2223 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2224 srwlock_base_errors
.trylock_excl
);
2226 ok(!srwlock_base_errors
.trylock_shared
,
2227 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2228 srwlock_base_errors
.trylock_shared
);
2232 static SRWLOCK srwlock_example
;
2233 static LONG srwlock_protected_value
= 0;
2234 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2235 static BOOL srwlock_stop
= FALSE
;
2237 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2241 while (!srwlock_stop
)
2244 /* periodically request exclusive access */
2245 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2247 pAcquireSRWLockExclusive(&srwlock_example
);
2248 if (InterlockedIncrement(&srwlock_inside
) != 1)
2249 InterlockedIncrement(&srwlock_example_errors
);
2251 InterlockedIncrement(&srwlock_protected_value
);
2254 if (InterlockedDecrement(&srwlock_inside
) != 0)
2255 InterlockedIncrement(&srwlock_example_errors
);
2256 pReleaseSRWLockExclusive(&srwlock_example
);
2259 /* request shared access */
2260 pAcquireSRWLockShared(&srwlock_example
);
2261 InterlockedIncrement(&srwlock_inside
);
2262 old
= srwlock_protected_value
;
2267 if (old
!= srwlock_protected_value
)
2268 InterlockedIncrement(&srwlock_example_errors
);
2269 InterlockedDecrement(&srwlock_inside
);
2270 pReleaseSRWLockShared(&srwlock_example
);
2276 static void test_srwlock_example(void)
2280 DWORD cnt1
, cnt2
, cnt3
;
2282 if (!pInitializeSRWLock
) {
2283 /* function is not yet in XP, only in newer Windows */
2284 win_skip("no srw lock support.\n");
2288 pInitializeSRWLock(&srwlock_example
);
2290 cnt1
= cnt2
= cnt3
= 0;
2292 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2293 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2294 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2296 /* limit run to 1 second. */
2299 /* tear down start */
2300 srwlock_stop
= TRUE
;
2302 WaitForSingleObject(h1
, 1000);
2303 WaitForSingleObject(h2
, 1000);
2304 WaitForSingleObject(h3
, 1000);
2306 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2307 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2308 srwlock_example_errors
);
2310 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2311 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2314 static DWORD WINAPI
alertable_wait_thread(void *param
)
2316 HANDLE
*semaphores
= param
;
2317 LARGE_INTEGER timeout
;
2321 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2322 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 1000, TRUE
);
2323 ok(result
== WAIT_IO_COMPLETION
, "expected WAIT_IO_COMPLETION, got %u\n", result
);
2324 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 200, TRUE
);
2325 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2327 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2328 timeout
.QuadPart
= -10000000;
2329 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2330 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2331 timeout
.QuadPart
= -2000000;
2332 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2333 ok(status
== STATUS_WAIT_0
, "expected STATUS_WAIT_0, got %08x\n", status
);
2335 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2336 timeout
.QuadPart
= -10000000;
2337 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2338 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2339 result
= WaitForSingleObject(semaphores
[0], 0);
2340 ok(result
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", result
);
2345 static void CALLBACK
alertable_wait_apc(ULONG_PTR userdata
)
2347 HANDLE
*semaphores
= (void *)userdata
;
2348 ReleaseSemaphore(semaphores
[1], 1, NULL
);
2351 static void CALLBACK
alertable_wait_apc2(ULONG_PTR userdata
)
2353 HANDLE
*semaphores
= (void *)userdata
;
2356 result
= WaitForSingleObject(semaphores
[0], 1000);
2357 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2360 static void test_alertable_wait(void)
2362 HANDLE thread
, semaphores
[2];
2365 semaphores
[0] = CreateSemaphoreW(NULL
, 0, 2, NULL
);
2366 ok(semaphores
[0] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2367 semaphores
[1] = CreateSemaphoreW(NULL
, 0, 1, NULL
);
2368 ok(semaphores
[1] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2369 thread
= CreateThread(NULL
, 0, alertable_wait_thread
, semaphores
, 0, NULL
);
2370 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2372 result
= WaitForSingleObject(semaphores
[0], 1000);
2373 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2374 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2375 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2376 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2378 result
= WaitForSingleObject(semaphores
[0], 1000);
2379 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2380 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2381 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2382 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2384 result
= WaitForSingleObject(semaphores
[0], 1000);
2385 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2386 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2387 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2388 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2389 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2390 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2391 ReleaseSemaphore(semaphores
[0], 2, NULL
);
2393 result
= WaitForSingleObject(thread
, 1000);
2394 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2395 CloseHandle(thread
);
2396 CloseHandle(semaphores
[0]);
2397 CloseHandle(semaphores
[1]);
2400 struct apc_deadlock_info
2402 PROCESS_INFORMATION
*pi
;
2407 static DWORD WINAPI
apc_deadlock_thread(void *param
)
2409 struct apc_deadlock_info
*info
= param
;
2410 PROCESS_INFORMATION
*pi
= info
->pi
;
2415 while (info
->running
)
2419 status
= pNtAllocateVirtualMemory(pi
->hProcess
, &base
, 0, &size
,
2420 MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2421 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2422 ok(base
!= NULL
, "expected base != NULL, got %p\n", base
);
2423 SetEvent(info
->event
);
2426 status
= pNtFreeVirtualMemory(pi
->hProcess
, &base
, &size
, MEM_RELEASE
);
2427 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2428 SetEvent(info
->event
);
2434 static void test_apc_deadlock(void)
2436 struct apc_deadlock_info info
;
2437 PROCESS_INFORMATION pi
;
2438 STARTUPINFOA si
= { sizeof(si
) };
2439 char cmdline
[MAX_PATH
];
2440 HANDLE event
, thread
;
2446 winetest_get_mainargs(&argv
);
2447 sprintf(cmdline
, "\"%s\" sync apc_deadlock", argv
[0]);
2448 success
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2449 ok(success
, "CreateProcess failed with %u\n", GetLastError());
2451 event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2452 ok(event
!= NULL
, "CreateEvent failed with %u\n", GetLastError());
2456 info
.running
= TRUE
;
2458 thread
= CreateThread(NULL
, 0, apc_deadlock_thread
, &info
, 0, NULL
);
2459 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2460 result
= WaitForSingleObject(event
, 1000);
2461 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2463 for (i
= 0; i
< 1000; i
++)
2465 result
= SuspendThread(pi
.hThread
);
2466 ok(result
== 0, "expected 0, got %u\n", result
);
2468 WaitForSingleObject(event
, 0); /* reset event */
2469 result
= WaitForSingleObject(event
, 1000);
2470 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2472 result
= ResumeThread(pi
.hThread
);
2473 ok(result
== 1, "expected 1, got %u\n", result
);
2477 info
.running
= FALSE
;
2478 result
= WaitForSingleObject(thread
, 1000);
2479 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2480 CloseHandle(thread
);
2483 TerminateProcess(pi
.hProcess
, 0);
2484 CloseHandle(pi
.hThread
);
2485 CloseHandle(pi
.hProcess
);
2492 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2493 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2495 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
2496 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
2497 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
2498 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
2499 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
2500 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
2501 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
2502 pCreateMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "CreateMemoryResourceNotification");
2503 pQueryMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "QueryMemoryResourceNotification");
2504 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2505 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2506 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2507 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2508 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2509 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2510 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2511 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2512 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2513 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2514 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2515 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2516 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2517 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2518 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2519 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2520 pNtAllocateVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtAllocateVirtualMemory");
2521 pNtFreeVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtFreeVirtualMemory");
2522 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2524 argc
= winetest_get_mainargs( &argv
);
2527 if (!strcmp(argv
[2], "apc_deadlock"))
2529 for (;;) SleepEx(INFINITE
, TRUE
);
2534 test_signalandwait();
2539 test_waitable_timer();
2540 test_iocp_callback();
2542 test_WaitForSingleObject();
2543 test_WaitForMultipleObjects();
2545 test_condvars_base();
2546 test_condvars_consumer_producer();
2547 test_srwlock_base();
2548 test_srwlock_example();
2549 test_alertable_wait();
2550 test_apc_deadlock();