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
22 #define _WIN32_WINNT 0x500
31 #include "wine/test.h"
34 #define QueryDepthSList(x) RtlQueryDepthSList(x)
35 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y)
36 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x)
37 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x)
41 #define __fastcall __stdcall
43 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
44 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
45 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
46 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
47 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
48 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
50 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
51 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
52 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
53 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
54 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
56 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
57 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
58 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
59 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
60 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
61 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
62 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
64 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
65 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
66 static NTSTATUS (WINAPI
*pNtWaitForSingleObject
)(HANDLE
, BOOLEAN
, const LARGE_INTEGER
*);
67 static NTSTATUS (WINAPI
*pNtWaitForMultipleObjects
)(ULONG
,const HANDLE
*,BOOLEAN
,BOOLEAN
,const LARGE_INTEGER
*);
68 static PSLIST_ENTRY (__fastcall
*pRtlInterlockedPushListSList
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
69 PSLIST_ENTRY last
, ULONG count
);
70 static PSLIST_ENTRY (WINAPI
*pRtlInterlockedPushListSListEx
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
71 PSLIST_ENTRY last
, ULONG count
);
78 BYTE pop_edx
; /* popl %edx (ret addr) */
79 BYTE pop_eax
; /* popl %eax (func) */
80 BYTE pop_ecx
; /* popl %ecx (param 1) */
81 BYTE xchg
[3]; /* xchgl (%esp),%edx (param 2) */
82 WORD jmp_eax
; /* jmp *%eax */
86 static void * (WINAPI
*call_fastcall_func4
)(void *func
, const void *a
, const void *b
, const void *c
, const void *d
);
88 static void init_fastcall_thunk(void)
90 struct fastcall_thunk
*thunk
= VirtualAlloc(NULL
, sizeof(*thunk
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
91 thunk
->pop_edx
= 0x5a; /* popl %edx */
92 thunk
->pop_eax
= 0x58; /* popl %eax */
93 thunk
->pop_ecx
= 0x59; /* popl %ecx */
94 thunk
->xchg
[0] = 0x87; /* xchgl (%esp),%edx */
95 thunk
->xchg
[1] = 0x14;
96 thunk
->xchg
[2] = 0x24;
97 thunk
->jmp_eax
= 0xe0ff; /* jmp *%eax */
98 call_fastcall_func4
= (void *)thunk
;
101 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
102 (const void *)(b), (const void *)(c), (const void *)(d))
106 #define init_fastcall_thunk() do { } while(0)
107 #define call_func4(func, a, b, c, d) func(a, b, c, d)
109 #endif /* __i386__ */
111 static void test_signalandwait(void)
114 HANDLE event
[2], semaphore
[2], file
;
117 /* invalid parameters */
118 r
= SignalObjectAndWait(NULL
, NULL
, 0, 0);
119 ok( r
== WAIT_FAILED
, "should fail\n");
121 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
122 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
124 ok( event
[0] && event
[1], "failed to create event flags\n");
126 r
= SignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
127 ok( r
== WAIT_FAILED
, "should fail\n");
129 r
= SignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
130 ok( r
== WAIT_FAILED
, "should fail\n");
133 /* valid parameters */
134 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
135 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
137 /* event[0] is now signalled - we repeat this test multiple times
138 * to ensure that the wineserver handles this situation properly. */
139 for (i
= 0; i
< 10000; i
++)
141 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
142 ok(r
== WAIT_OBJECT_0
, "should succeed\n");
145 /* event[0] is not signalled */
146 r
= WaitForSingleObject(event
[0], 0);
147 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
149 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
150 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
152 /* clear event[1] and check for a timeout */
153 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
154 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
155 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
157 CloseHandle(event
[0]);
158 CloseHandle(event
[1]);
161 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
162 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
163 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
165 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
166 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
168 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
169 ok( r
== WAIT_FAILED
, "should fail\n");
171 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
172 ok( r
== FALSE
, "should fail\n");
174 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
175 ok( r
== TRUE
, "should succeed\n");
177 CloseHandle(semaphore
[0]);
178 CloseHandle(semaphore
[1]);
180 /* try a registry key */
181 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
182 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
183 r
= SignalObjectAndWait(file
, file
, 0, FALSE
);
184 ok( r
== WAIT_FAILED
, "should fail\n");
185 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
189 static void test_mutex(void)
198 SetLastError(0xdeadbeef);
199 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
200 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
201 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
203 SetLastError(0xdeadbeef);
204 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
205 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
207 SetLastError(0xdeadbeef);
208 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
210 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
212 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
214 SetLastError(0xdeadbeef);
215 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
216 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
217 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
218 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
219 CloseHandle(hOpened
);
221 for(i
=0; i
< 31; i
++)
223 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
224 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
227 SetLastError(0xdeadbeef);
228 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
229 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
230 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
231 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
232 CloseHandle(hOpened
);
234 for (i
= 0; i
< 32; i
++)
236 SetLastError(0xdeadbeef);
237 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
240 SetLastError(0xdeadbeef);
241 ret
= ReleaseMutex(hOpened
);
242 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
243 CloseHandle(hOpened
);
247 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
248 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
250 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
251 ReleaseMutex(hCreated
);
257 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
259 SetLastError(0xdeadbeef);
260 ret
= ReleaseMutex(hCreated
);
261 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
262 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
264 /* test case sensitivity */
266 SetLastError(0xdeadbeef);
267 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
268 ok(!hOpened
, "OpenMutex succeeded\n");
269 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
271 SetLastError(0xdeadbeef);
272 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
273 ok(!hOpened
, "OpenMutex succeeded\n");
274 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
276 SetLastError(0xdeadbeef);
277 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, NULL
);
278 ok(!hOpened
, "OpenMutex succeeded\n");
279 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
281 SetLastError(0xdeadbeef);
282 hOpened
= OpenMutexW(READ_CONTROL
, FALSE
, NULL
);
283 ok(!hOpened
, "OpenMutex succeeded\n");
284 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
286 SetLastError(0xdeadbeef);
287 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
288 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
289 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
290 CloseHandle(hOpened
);
292 SetLastError(0xdeadbeef);
293 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
294 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
295 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
296 CloseHandle(hOpened
);
298 CloseHandle(hCreated
);
301 static void test_slist(void)
307 } item1
, item2
, item3
, *item
;
308 SLIST_HEADER slist_header
;
317 memset(&slist_header
, 0xff, sizeof(slist_header
));
318 InitializeSListHead(&slist_header
);
319 size
= QueryDepthSList(&slist_header
);
320 ok(size
== 0, "Expected size == 0, got %u\n", size
);
322 /* test PushEntry, PopEntry and Flush */
323 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
324 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
325 size
= QueryDepthSList(&slist_header
);
326 ok(size
== 1, "Expected size == 1, got %u\n", size
);
328 entry
= InterlockedPushEntrySList(&slist_header
, &item2
.entry
);
329 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
330 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
331 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
332 size
= QueryDepthSList(&slist_header
);
333 ok(size
== 2, "Expected size == 2, got %u\n", size
);
335 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
336 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
337 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
338 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
339 size
= QueryDepthSList(&slist_header
);
340 ok(size
== 3, "Expected size == 3, got %u\n", size
);
342 entry
= InterlockedPopEntrySList(&slist_header
);
343 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
344 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
345 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
346 size
= QueryDepthSList(&slist_header
);
347 ok(size
== 2, "Expected size == 2, got %u\n", size
);
349 entry
= InterlockedFlushSList(&slist_header
);
350 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
351 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
352 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
353 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
354 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
355 size
= QueryDepthSList(&slist_header
);
356 ok(size
== 0, "Expected size == 0, got %u\n", size
);
357 entry
= InterlockedPopEntrySList(&slist_header
);
358 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
360 /* test RtlInterlockedPushListSList */
361 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
362 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
363 entry
= call_func4(pRtlInterlockedPushListSList
, &slist_header
, &item2
.entry
, &item1
.entry
, 42);
364 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
365 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
366 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
367 size
= QueryDepthSList(&slist_header
);
368 ok(size
== 43, "Expected size == 43, got %u\n", size
);
370 entry
= InterlockedPopEntrySList(&slist_header
);
371 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
372 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
373 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
374 size
= QueryDepthSList(&slist_header
);
375 ok(size
== 42, "Expected size == 42, got %u\n", size
);
377 entry
= InterlockedPopEntrySList(&slist_header
);
378 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
379 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
380 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
381 size
= QueryDepthSList(&slist_header
);
382 ok(size
== 41, "Expected size == 41, got %u\n", size
);
384 entry
= InterlockedPopEntrySList(&slist_header
);
385 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
386 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
387 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
388 size
= QueryDepthSList(&slist_header
);
389 ok(size
== 40, "Expected size == 40, got %u\n", size
);
391 entry
= InterlockedPopEntrySList(&slist_header
);
392 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
393 size
= QueryDepthSList(&slist_header
);
394 ok(size
== 40, "Expected size == 40, got %u\n", size
);
396 entry
= InterlockedFlushSList(&slist_header
);
397 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
398 size
= QueryDepthSList(&slist_header
);
399 ok(size
== 40 || broken(size
== 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size
);
401 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
402 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
403 entry
= InterlockedFlushSList(&slist_header
);
404 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
405 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
406 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
407 size
= QueryDepthSList(&slist_header
);
408 ok(size
== 0, "Expected size == 0, got %u\n", size
);
410 /* test RtlInterlockedPushListSListEx */
411 if (pRtlInterlockedPushListSListEx
)
413 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
414 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
415 entry
= pRtlInterlockedPushListSListEx(&slist_header
, &item2
.entry
, &item1
.entry
, 42);
416 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
417 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
418 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
419 size
= QueryDepthSList(&slist_header
);
420 ok(size
== 43, "Expected size == 43, got %u\n", size
);
422 entry
= InterlockedFlushSList(&slist_header
);
423 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
424 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
425 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
426 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
427 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
428 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
429 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
430 size
= QueryDepthSList(&slist_header
);
431 ok(size
== 0, "Expected size == 0, got %u\n", size
);
434 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
436 /* test with a lot of items */
437 for (i
= 0; i
< 65536; i
++)
439 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
441 entry
= InterlockedPushEntrySList(&slist_header
, &item
->entry
);
444 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
445 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
446 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
450 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
452 size
= QueryDepthSList(&slist_header
);
453 ok(size
== ((i
+ 1) & 0xffff), "Expected size == %u, got %u\n", (i
+ 1) & 0xffff, size
);
456 entry
= InterlockedFlushSList(&slist_header
);
457 for (i
= 65536; i
> 0; i
--)
459 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
460 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
461 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
462 entry
= item
->entry
.Next
;
463 HeapFree(GetProcessHeap(), 0, item
);
465 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
466 size
= QueryDepthSList(&slist_header
);
467 ok(size
== 0, "Expected size == 0, got %u\n", size
);
468 entry
= InterlockedPopEntrySList(&slist_header
);
469 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
472 static void test_event(void)
474 HANDLE handle
, handle2
;
475 SECURITY_ATTRIBUTES sa
;
476 SECURITY_DESCRIPTOR sd
;
482 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
483 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
486 sa
.nLength
= sizeof(sa
);
487 sa
.lpSecurityDescriptor
= &sd
;
488 sa
.bInheritHandle
= FALSE
;
490 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
493 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
494 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
497 /* sd with NULL dacl */
498 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
499 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
500 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
503 /* sd with empty dacl */
504 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
505 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
506 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
507 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
510 /* test case sensitivity */
512 SetLastError(0xdeadbeef);
513 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
514 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
515 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
517 SetLastError(0xdeadbeef);
518 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
519 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
520 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
521 CloseHandle( handle2
);
523 SetLastError(0xdeadbeef);
524 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
525 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
526 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
527 CloseHandle( handle2
);
529 SetLastError(0xdeadbeef);
530 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
531 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
532 CloseHandle( handle2
);
534 SetLastError(0xdeadbeef);
535 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
536 ok( !handle2
, "OpenEvent succeeded\n");
537 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
539 SetLastError(0xdeadbeef);
540 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, NULL
);
541 ok( !handle2
, "OpenEvent succeeded\n");
542 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
544 SetLastError(0xdeadbeef);
545 handle2
= OpenEventW( EVENT_ALL_ACCESS
, FALSE
, NULL
);
546 ok( !handle2
, "OpenEvent succeeded\n");
547 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
549 CloseHandle( handle
);
551 /* resource notifications are events too */
553 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
555 trace( "memory resource notifications not supported\n" );
558 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
559 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
560 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
561 ret
= pQueryMemoryResourceNotification( handle
, &val
);
562 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
563 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
565 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
566 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
567 ret
= WaitForSingleObject( handle
, 10 );
568 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
571 ret
= pQueryMemoryResourceNotification( handle
, &val
);
572 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
573 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
574 ret
= CloseHandle( handle
);
575 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
577 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
579 ret
= pQueryMemoryResourceNotification( handle
, &val
);
580 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
581 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
582 CloseHandle( handle
);
585 static void test_semaphore(void)
587 HANDLE handle
, handle2
;
589 /* test case sensitivity */
591 SetLastError(0xdeadbeef);
592 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
593 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
594 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
596 SetLastError(0xdeadbeef);
597 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
598 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
599 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
600 CloseHandle( handle2
);
602 SetLastError(0xdeadbeef);
603 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
604 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
605 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
606 CloseHandle( handle2
);
608 SetLastError(0xdeadbeef);
609 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
610 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
611 CloseHandle( handle2
);
613 SetLastError(0xdeadbeef);
614 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
615 ok( !handle2
, "OpenSemaphore succeeded\n");
616 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
618 SetLastError(0xdeadbeef);
619 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
620 ok( !handle2
, "OpenSemaphore succeeded\n");
621 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
623 SetLastError(0xdeadbeef);
624 handle2
= OpenSemaphoreW( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
625 ok( !handle2
, "OpenSemaphore succeeded\n");
626 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
628 CloseHandle( handle
);
631 static void test_waitable_timer(void)
633 HANDLE handle
, handle2
;
635 /* test case sensitivity */
637 SetLastError(0xdeadbeef);
638 handle
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
639 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
640 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
642 SetLastError(0xdeadbeef);
643 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
644 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
645 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
646 CloseHandle( handle2
);
648 SetLastError(0xdeadbeef);
649 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
650 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
651 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
652 CloseHandle( handle2
);
654 SetLastError(0xdeadbeef);
655 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
656 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
657 CloseHandle( handle2
);
659 SetLastError(0xdeadbeef);
660 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
661 ok( !handle2
, "OpenWaitableTimer succeeded\n");
662 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
664 SetLastError(0xdeadbeef);
665 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, NULL
);
666 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
667 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
669 SetLastError(0xdeadbeef);
670 handle2
= OpenWaitableTimerW( TIMER_ALL_ACCESS
, FALSE
, NULL
);
671 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
672 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
674 CloseHandle( handle
);
677 static HANDLE sem
= 0;
679 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
681 ReleaseSemaphore(sem
, 1, NULL
);
684 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
686 static void test_iocp_callback(void)
688 char temp_path
[MAX_PATH
];
689 char filename
[MAX_PATH
];
692 static const char prefix
[] = "pfx";
694 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
696 const char *buffer
= "12345678123456781234567812345678";
697 OVERLAPPED overlapped
;
699 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
700 if(!p_BindIoCompletionCallback
) {
701 win_skip("BindIoCompletionCallback not found in this DLL\n");
705 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
706 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
708 ret
= GetTempPathA(MAX_PATH
, temp_path
);
709 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
710 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
712 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
713 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
715 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
716 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
717 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
719 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
720 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
721 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
723 ret
= CloseHandle(hFile
);
724 ok( ret
, "CloseHandle: error %d\n", GetLastError());
725 ret
= DeleteFileA(filename
);
726 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
728 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
729 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
730 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
732 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
733 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
735 memset(&overlapped
, 0, sizeof(overlapped
));
736 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
737 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
739 ret
= WaitForSingleObject(sem
, 5000);
740 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
743 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
744 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
745 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
746 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
747 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
748 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
750 ret
= CloseHandle(hFile
);
751 ok( ret
, "CloseHandle: error %d\n", GetLastError());
752 ret
= DeleteFileA(filename
);
753 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
755 /* win2k3 requires the Flags parameter to be zero */
756 SetLastError(0xdeadbeef);
757 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
758 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
759 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
760 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
762 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
763 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
765 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
766 ret
= CloseHandle(hFile
);
767 ok( ret
, "CloseHandle: error %d\n", GetLastError());
768 ret
= DeleteFileA(filename
);
769 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
771 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
772 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
773 ok(GetLastError() == ERROR_INVALID_HANDLE
||
774 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
775 "Last error is %d\n", GetLastError());
778 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
781 ok(timedOut
, "Timer callbacks should always time out\n");
785 struct timer_queue_data1
792 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
794 struct timer_queue_data1
*d
= p
;
795 ok(timedOut
, "Timer callbacks should always time out\n");
796 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
799 SetLastError(0xdeadbeef);
800 /* Note, XP SP2 does *not* do any deadlock checking, so passing
801 INVALID_HANDLE_VALUE here will just hang. */
802 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
803 ok(!ret
, "DeleteTimerQueueTimer\n");
804 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
808 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
810 struct timer_queue_data1
*d
= p
;
811 ok(timedOut
, "Timer callbacks should always time out\n");
812 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
814 /* Basically kill the timer since it won't have time to run
816 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
817 ok(ret
, "ChangeTimerQueueTimer\n");
821 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
823 struct timer_queue_data1
*d
= p
;
824 ok(timedOut
, "Timer callbacks should always time out\n");
827 /* This tests whether a timer gets flagged for deletion before
828 or after the callback runs. If we start this timer with a
829 period of zero (run once), then ChangeTimerQueueTimer will
830 fail if the timer is already flagged. Hence we really run
831 only once. Otherwise we will run multiple times. */
832 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
833 ok(ret
, "ChangeTimerQueueTimer\n");
838 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
840 DWORD_PTR delay
= (DWORD_PTR
) p
;
841 ok(timedOut
, "Timer callbacks should always time out\n");
846 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
848 struct timer_queue_data1
*d
= p
;
849 ok(timedOut
, "Timer callbacks should always time out\n");
850 /* This tests an original implementation bug where a deleted timer may get
851 to run, but it is tricky to set up. */
852 if (d
->q
&& d
->num_calls
++ == 0)
854 /* First run: delete ourselves, then insert and remove a timer
855 that goes in front of us in the sorted timeout list. Once
856 removed, we will still timeout at the faster timer's due time,
857 but this should be a no-op if we are bug-free. There should
858 not be a second run. We can test the value of num_calls later. */
862 /* The delete will pend while we are in this callback. */
863 SetLastError(0xdeadbeef);
864 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
865 ok(!ret
, "DeleteTimerQueueTimer\n");
866 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
868 ret
= CreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
869 ok(ret
, "CreateTimerQueueTimer\n");
870 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
872 ret
= DeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
873 ok(ret
, "DeleteTimerQueueTimer\n");
875 /* Now we stay alive by hanging around in the callback. */
880 static void test_timer_queue(void)
882 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
883 int n0
, n1
, n2
, n3
, n4
, n5
;
884 struct timer_queue_data1 d1
, d2
, d3
, d4
;
888 /* Test asynchronous deletion of the queue. */
889 q
= CreateTimerQueue();
890 ok(q
!= NULL
, "CreateTimerQueue\n");
892 SetLastError(0xdeadbeef);
893 ret
= DeleteTimerQueueEx(q
, NULL
);
894 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
895 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
898 /* Test synchronous deletion of the queue and running timers. */
899 q
= CreateTimerQueue();
900 ok(q
!= NULL
, "CreateTimerQueue\n");
905 ret
= CreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0, 300, 0);
906 ok(ret
, "CreateTimerQueueTimer\n");
907 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
908 ret0
= DeleteTimerQueueTimer(q
, t0
, NULL
);
909 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
910 broken(ret0
), /* Win 2000 & XP & 2003 */
911 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
916 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0, 0, 0);
917 ok(ret
, "CreateTimerQueueTimer\n");
918 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
923 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0, 100, 0);
924 ok(ret
, "CreateTimerQueueTimer\n");
925 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
930 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0, 10, 0);
931 ok(ret
, "CreateTimerQueueTimer\n");
932 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
934 /* Start really late (it won't start). */
937 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000, 10, 0);
938 ok(ret
, "CreateTimerQueueTimer\n");
939 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
941 /* Start soon, but delay so long it won't run again. */
944 ret
= CreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0, 10000, 0);
945 ok(ret
, "CreateTimerQueueTimer\n");
946 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
948 /* Give them a chance to do some work. */
951 /* Test deleting a once-only timer. */
952 ret
= DeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
953 ok(ret
, "DeleteTimerQueueTimer\n");
955 /* A periodic timer. */
956 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
957 ok(ret
, "DeleteTimerQueueTimer\n");
959 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
960 ok(ret
, "DeleteTimerQueueEx\n");
962 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
963 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
964 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
965 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
966 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
968 /* Test synchronous deletion of the timer/queue with event trigger. */
969 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
970 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
971 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
972 if (!e
|| !et1
|| !et2
)
974 skip("Failed to create timer queue descruction event\n");
978 q
= CreateTimerQueue();
979 ok(q
!= NULL
, "CreateTimerQueue\n");
981 /* Run once and finish quickly (should be done when we delete it). */
983 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
984 ok(ret
, "CreateTimerQueueTimer\n");
985 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
987 /* Run once and finish slowly (shouldn't be done when we delete it). */
989 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
990 ok(ret
, "CreateTimerQueueTimer\n");
991 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
993 /* Run once and finish quickly (should be done when we delete it). */
995 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
996 ok(ret
, "CreateTimerQueueTimer\n");
997 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
999 /* Run once and finish slowly (shouldn't be done when we delete it). */
1001 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
1002 ok(ret
, "CreateTimerQueueTimer\n");
1003 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1005 /* Give them a chance to start. */
1008 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1009 even if the timer is finished. */
1010 SetLastError(0xdeadbeef);
1011 ret
= DeleteTimerQueueTimer(q
, t1
, NULL
);
1012 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1013 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1016 SetLastError(0xdeadbeef);
1017 ret
= DeleteTimerQueueTimer(q
, t2
, NULL
);
1018 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1019 ok(GetLastError() == ERROR_IO_PENDING
,
1020 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1023 SetLastError(0xdeadbeef);
1024 ret
= DeleteTimerQueueTimer(q
, t3
, et1
);
1025 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1026 ok(GetLastError() == 0xdeadbeef,
1027 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
1029 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
1030 "Timer destruction event not triggered\n");
1032 SetLastError(0xdeadbeef);
1033 ret
= DeleteTimerQueueTimer(q
, t4
, et2
);
1034 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1035 ok(GetLastError() == ERROR_IO_PENDING
,
1036 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1038 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
1039 "Timer destruction event not triggered\n");
1041 SetLastError(0xdeadbeef);
1042 ret
= DeleteTimerQueueEx(q
, e
);
1043 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1044 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1046 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
1047 "Queue destruction event not triggered\n");
1050 /* Test deleting/changing a timer in execution. */
1051 q
= CreateTimerQueue();
1052 ok(q
!= NULL
, "CreateTimerQueue\n");
1054 /* Test changing a once-only timer before it fires (this is allowed,
1055 whereas after it fires you cannot). */
1057 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000, 0, 0);
1058 ok(ret
, "CreateTimerQueueTimer\n");
1059 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1060 ret
= ChangeTimerQueueTimer(q
, t1
, 0, 0);
1061 ok(ret
, "ChangeTimerQueueTimer\n");
1067 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10, 10, 0);
1069 ok(ret
, "CreateTimerQueueTimer\n");
1070 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1076 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10, 10, 0);
1078 ok(ret
, "CreateTimerQueueTimer\n");
1079 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
1084 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10, 0, 0);
1086 ok(ret
, "CreateTimerQueueTimer\n");
1087 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1091 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
1092 ok(ret
, "DeleteTimerQueueEx\n");
1093 ok(n1
== 1, "ChangeTimerQueueTimer\n");
1094 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
1095 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
1096 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
1098 /* Test an obscure bug that was in the original implementation. */
1099 q
= CreateTimerQueue();
1100 ok(q
!= NULL
, "CreateTimerQueue\n");
1102 /* All the work is done in the callback. */
1106 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100, 100, WT_EXECUTELONGFUNCTION
);
1108 ok(ret
, "CreateTimerQueueTimer\n");
1109 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1113 SetLastError(0xdeadbeef);
1114 ret
= DeleteTimerQueueEx(q
, NULL
);
1115 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1116 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1118 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1120 /* Test functions on the default timer queue. */
1123 ret
= CreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1124 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1125 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1127 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1128 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1130 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1131 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1133 /* Try mixing default and non-default queues. Apparently this works. */
1134 q
= CreateTimerQueue();
1135 ok(q
!= NULL
, "CreateTimerQueue\n");
1139 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1140 ok(ret
, "CreateTimerQueueTimer\n");
1141 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1145 ret
= CreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000, 1000, 0);
1146 ok(ret
, "CreateTimerQueueTimer\n");
1147 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1149 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1150 ok(ret
, "ChangeTimerQueueTimer\n");
1152 ret
= ChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1153 ok(ret
, "ChangeTimerQueueTimer\n");
1155 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1156 ok(ret
, "DeleteTimerQueueTimer\n");
1158 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1159 ok(ret
, "DeleteTimerQueueTimer\n");
1161 /* Try to delete the default queue? In any case: not allowed. */
1162 SetLastError(0xdeadbeef);
1163 ret
= DeleteTimerQueueEx(NULL
, NULL
);
1164 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1165 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1166 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1169 SetLastError(0xdeadbeef);
1170 ret
= DeleteTimerQueueEx(q
, NULL
);
1171 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1172 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1176 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1178 DWORD tmp
= HandleToULong(handle
);
1180 return ULongToHandle(tmp
);
1183 static void test_WaitForSingleObject(void)
1185 HANDLE signaled
, nonsignaled
, invalid
;
1186 LARGE_INTEGER timeout
;
1190 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1191 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1192 invalid
= (HANDLE
) 0xdeadbee0;
1194 /* invalid handle with different values for lower 2 bits */
1195 SetLastError(0xdeadbeef);
1196 ret
= WaitForSingleObject(invalid
, 0);
1197 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1198 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1200 SetLastError(0xdeadbeef);
1201 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1202 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1203 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1205 SetLastError(0xdeadbeef);
1206 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1207 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1208 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1210 SetLastError(0xdeadbeef);
1211 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1212 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1213 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1215 /* valid handle with different values for lower 2 bits */
1216 SetLastError(0xdeadbeef);
1217 ret
= WaitForSingleObject(nonsignaled
, 0);
1218 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1219 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1221 SetLastError(0xdeadbeef);
1222 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1223 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1224 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1226 SetLastError(0xdeadbeef);
1227 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1228 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1229 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1231 SetLastError(0xdeadbeef);
1232 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1233 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1234 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1236 /* valid handle with different values for lower 2 bits */
1237 SetLastError(0xdeadbeef);
1238 ret
= WaitForSingleObject(signaled
, 0);
1239 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1240 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1242 SetLastError(0xdeadbeef);
1243 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1244 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1245 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1247 SetLastError(0xdeadbeef);
1248 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1249 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1250 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1252 SetLastError(0xdeadbeef);
1253 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1254 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1255 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1257 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1258 ret
= WaitForSingleObject(GetCurrentProcess(), 100);
1259 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1261 ret
= WaitForSingleObject(GetCurrentThread(), 100);
1262 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1264 timeout
.QuadPart
= -1000000;
1265 status
= pNtWaitForSingleObject(GetCurrentProcess(), FALSE
, &timeout
);
1266 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1268 timeout
.QuadPart
= -1000000;
1269 status
= pNtWaitForSingleObject(GetCurrentThread(), FALSE
, &timeout
);
1270 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1272 CloseHandle(signaled
);
1273 CloseHandle(nonsignaled
);
1276 static void test_WaitForMultipleObjects(void)
1278 LARGE_INTEGER timeout
;
1282 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1284 /* create the maximum number of events and make sure
1285 * we can wait on that many */
1286 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1288 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1289 ok( maxevents
[i
] != 0, "should create enough events\n");
1292 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1293 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1294 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1295 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1296 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1297 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1298 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1300 /* the lowest index is checked first and remaining events are untouched */
1301 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1302 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1305 /* run same test with Nt* call */
1306 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1307 SetEvent(maxevents
[i
]);
1309 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1310 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1311 ok(status
== STATUS_WAIT_0
, "should signal lowest handle first, got %08x\n", status
);
1312 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1313 ok(status
== STATUS_WAIT_0
, "should signal handle #0 first, got %08x\n", status
);
1314 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1315 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1317 /* the lowest index is checked first and remaining events are untouched */
1318 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1319 ok(status
== STATUS_WAIT_0
+ i
, "should signal handle #%d first, got %08x\n", i
, status
);
1322 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1323 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1325 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1326 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1327 maxevents
[0] = GetCurrentProcess();
1328 SetLastError(0xdeadbeef);
1329 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1330 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1331 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1332 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1334 maxevents
[0] = GetCurrentThread();
1335 SetLastError(0xdeadbeef);
1336 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1337 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1338 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1339 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1341 timeout
.QuadPart
= -1000000;
1342 maxevents
[0] = GetCurrentProcess();
1343 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1344 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1346 timeout
.QuadPart
= -1000000;
1347 maxevents
[0] = GetCurrentThread();
1348 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1349 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1352 static BOOL g_initcallback_ret
, g_initcallback_called
;
1353 static void *g_initctxt
;
1355 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1357 g_initcallback_called
= TRUE
;
1358 /* zero bit set means here that initialization is taking place - initialization locked */
1359 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1360 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1361 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1362 return g_initcallback_ret
;
1365 static void test_initonce(void)
1370 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1372 win_skip("one-time initialization API not supported\n");
1376 /* blocking initialization with callback */
1377 initonce
.Ptr
= (void*)0xdeadbeef;
1378 pInitOnceInitialize(&initonce
);
1379 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1381 /* initialisation completed successfully */
1382 g_initcallback_ret
= TRUE
;
1384 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1385 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1386 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1387 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1388 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1390 /* so it's been called already so won't be called again */
1392 g_initcallback_called
= FALSE
;
1393 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1394 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1395 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1396 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1397 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1399 pInitOnceInitialize(&initonce
);
1400 g_initcallback_called
= FALSE
;
1401 /* 2 lower order bits should never be used, you'll get a crash in result */
1402 g_initctxt
= (void*)0xFFFFFFF0;
1403 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1404 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1405 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1406 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1407 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1409 /* callback failed */
1410 g_initcallback_ret
= FALSE
;
1411 g_initcallback_called
= FALSE
;
1413 pInitOnceInitialize(&initonce
);
1414 SetLastError( 0xdeadbeef );
1415 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1416 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1417 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1418 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1419 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1421 /* blocking initialization without a callback */
1422 pInitOnceInitialize(&initonce
);
1425 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1426 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1427 ok(pending
, "got %d\n", pending
);
1428 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1429 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1430 /* another attempt to begin initialization with block a single thread */
1434 SetLastError( 0xdeadbeef );
1435 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1436 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1437 ok(pending
== 0xf, "got %d\n", pending
);
1438 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1439 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1441 g_initctxt
= (void*)0xdeadbee0;
1442 SetLastError( 0xdeadbeef );
1443 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1444 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1445 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1447 /* once failed already */
1448 g_initctxt
= (void*)0xdeadbee0;
1449 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1450 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1451 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1453 pInitOnceInitialize(&initonce
);
1454 SetLastError( 0xdeadbeef );
1455 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1456 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1457 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1459 SetLastError( 0xdeadbeef );
1460 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1461 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1462 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1464 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1465 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1466 ok(pending
, "got %d\n", pending
);
1467 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1469 SetLastError( 0xdeadbeef );
1470 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1471 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1473 SetLastError( 0xdeadbeef );
1474 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1475 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1476 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1478 SetLastError( 0xdeadbeef );
1479 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1480 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1481 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1483 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1484 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1485 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1487 pInitOnceInitialize(&initonce
);
1488 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1489 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1490 ok(pending
, "got %d\n", pending
);
1491 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1493 SetLastError( 0xdeadbeef );
1494 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1495 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1497 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1498 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1499 ok(pending
, "got %d\n", pending
);
1500 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1502 SetLastError( 0xdeadbeef );
1503 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1504 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1505 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1507 SetLastError( 0xdeadbeef );
1508 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1509 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1510 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1512 SetLastError( 0xdeadbeef );
1513 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1514 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1515 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1517 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1518 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1519 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1521 SetLastError( 0xdeadbeef );
1522 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1523 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1524 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1526 pInitOnceInitialize(&initonce
);
1527 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1528 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1529 ok(pending
, "got %d\n", pending
);
1530 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1532 /* test INIT_ONCE_CHECK_ONLY */
1534 pInitOnceInitialize(&initonce
);
1535 SetLastError( 0xdeadbeef );
1536 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1537 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1538 SetLastError( 0xdeadbeef );
1539 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1540 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1542 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1543 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1544 ok(pending
, "got %d\n", pending
);
1545 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1547 SetLastError( 0xdeadbeef );
1548 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1549 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1550 SetLastError( 0xdeadbeef );
1551 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1552 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1554 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1555 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1556 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1558 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1559 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1560 ok(!pending
, "got %d\n", pending
);
1561 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1562 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1564 SetLastError( 0xdeadbeef );
1565 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1566 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1568 pInitOnceInitialize(&initonce
);
1569 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1570 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1571 ok(pending
, "got %d\n", pending
);
1572 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1574 SetLastError( 0xdeadbeef );
1575 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1576 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1577 SetLastError( 0xdeadbeef );
1578 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1579 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1581 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1582 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1583 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1585 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1586 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1587 ok(!pending
, "got %d\n", pending
);
1588 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1589 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1591 SetLastError( 0xdeadbeef );
1592 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1593 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1596 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1597 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1598 static CRITICAL_SECTION buffercrit
;
1599 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1600 static LONG bufferlen
,totalproduced
,totalconsumed
;
1601 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1603 #define BUFFER_SIZE 5
1605 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1606 DWORD sleepinterval
= 5;
1609 Sleep(sleepinterval
);
1610 if (sleepinterval
> 1)
1613 EnterCriticalSection(&buffercrit
);
1614 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1615 condvar_producer_sleepcnt
++;
1616 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1617 if (GetLastError() != ERROR_TIMEOUT
)
1618 condvar_sleeperr
= TRUE
;
1622 LeaveCriticalSection(&buffercrit
);
1627 LeaveCriticalSection(&buffercrit
);
1628 pWakeConditionVariable(&buffernotempty
);
1633 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1634 DWORD
*cnt
= (DWORD
*)x
;
1635 DWORD sleepinterval
= 1;
1638 EnterCriticalSection(&buffercrit
);
1639 while ((bufferlen
== 0) && !condvar_stop
) {
1640 condvar_consumer_sleepcnt
++;
1641 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1642 if (GetLastError() != ERROR_TIMEOUT
)
1643 condvar_sleeperr
= TRUE
;
1646 if (condvar_stop
&& (bufferlen
== 0)) {
1647 LeaveCriticalSection(&buffercrit
);
1653 LeaveCriticalSection(&buffercrit
);
1654 pWakeConditionVariable(&buffernotfull
);
1655 Sleep(sleepinterval
);
1656 if (sleepinterval
< 5) sleepinterval
+= 1;
1661 static void test_condvars_consumer_producer(void)
1663 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1665 DWORD cnt1
,cnt2
,cnt3
;
1667 if (!pInitializeConditionVariable
) {
1668 /* function is not yet in XP, only in newer Windows */
1669 win_skip("no condition variable support.\n");
1673 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1675 /* If we have static initialized condition variables, InitializeConditionVariable
1676 * is not strictly necessary.
1677 * pInitializeConditionVariable(&buffernotfull);
1679 pInitializeConditionVariable(&buffernotempty
);
1680 InitializeCriticalSection(&buffercrit
);
1682 /* Larger Test: consumer/producer example */
1684 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1686 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1687 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1688 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1689 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1690 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1691 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1693 /* Limit run to 0.5 seconds. */
1696 /* tear down start */
1697 condvar_stop
= TRUE
;
1699 /* final wake up call */
1700 pWakeAllConditionVariable (&buffernotfull
);
1701 pWakeAllConditionVariable (&buffernotempty
);
1703 /* (mostly an implementation detail)
1704 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1707 WaitForSingleObject(hp1
, 1000);
1708 WaitForSingleObject(hp2
, 1000);
1709 WaitForSingleObject(hp3
, 1000);
1710 WaitForSingleObject(hc1
, 1000);
1711 WaitForSingleObject(hc2
, 1000);
1712 WaitForSingleObject(hc3
, 1000);
1714 ok(totalconsumed
== totalproduced
,
1715 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1716 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1718 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1719 * one consumer does not get anything to do is possible. */
1720 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1721 /* The sleeps of the producer or consumer should not go above 100* produced count,
1722 * otherwise the implementation does not sleep correctly. But yet again, this is
1723 * not hard defined. */
1724 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1727 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1728 static DWORD condvar_seq
= 0;
1729 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1730 static CRITICAL_SECTION condvar_crit
;
1731 static SRWLOCK condvar_srwlock
;
1733 /* Sequence of wake/sleep to check boundary conditions:
1735 * 1: producer emits a WakeConditionVariable without consumer waiting.
1736 * 2: consumer sleeps without a wake expecting timeout
1737 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1738 * 4: consumer sleeps without a wake expecting timeout
1739 * 5: a wake is handed to a SleepConditionVariableCS
1740 * 6: a wakeall is handed to a SleepConditionVariableCS
1741 * 7: sleep after above should timeout
1742 * 8: wake with crit section locked into the sleep timeout
1744 * the following tests will only be executed if InitializeSRWLock is available
1746 * 9: producer (exclusive) wakes up consumer (exclusive)
1747 * 10: producer (exclusive) wakes up consumer (shared)
1748 * 11: producer (shared) wakes up consumer (exclusive)
1749 * 12: producer (shared) wakes up consumer (shared)
1752 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1753 while (condvar_seq
< 1) Sleep(1);
1755 pWakeConditionVariable (&condvar_base
);
1758 while (condvar_seq
< 3) Sleep(1);
1759 pWakeAllConditionVariable (&condvar_base
);
1762 while (condvar_seq
< 5) Sleep(1);
1763 EnterCriticalSection (&condvar_crit
);
1764 pWakeConditionVariable (&condvar_base
);
1765 LeaveCriticalSection (&condvar_crit
);
1766 while (condvar_seq
< 6) Sleep(1);
1767 EnterCriticalSection (&condvar_crit
);
1768 pWakeAllConditionVariable (&condvar_base
);
1769 LeaveCriticalSection (&condvar_crit
);
1771 while (condvar_seq
< 8) Sleep(1);
1772 EnterCriticalSection (&condvar_crit
);
1773 pWakeConditionVariable (&condvar_base
);
1775 LeaveCriticalSection (&condvar_crit
);
1777 /* skip over remaining tests if InitializeSRWLock is not available */
1778 if (!pInitializeSRWLock
)
1781 while (condvar_seq
< 9) Sleep(1);
1782 pAcquireSRWLockExclusive(&condvar_srwlock
);
1783 pWakeConditionVariable(&condvar_base
);
1784 pReleaseSRWLockExclusive(&condvar_srwlock
);
1786 while (condvar_seq
< 10) Sleep(1);
1787 pAcquireSRWLockExclusive(&condvar_srwlock
);
1788 pWakeConditionVariable(&condvar_base
);
1789 pReleaseSRWLockExclusive(&condvar_srwlock
);
1791 while (condvar_seq
< 11) Sleep(1);
1792 pAcquireSRWLockShared(&condvar_srwlock
);
1793 pWakeConditionVariable(&condvar_base
);
1794 pReleaseSRWLockShared(&condvar_srwlock
);
1796 while (condvar_seq
< 12) Sleep(1);
1797 Sleep(50); /* ensure that consumer waits for cond variable */
1798 pAcquireSRWLockShared(&condvar_srwlock
);
1799 pWakeConditionVariable(&condvar_base
);
1800 pReleaseSRWLockShared(&condvar_srwlock
);
1805 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1808 while (condvar_seq
< 2) Sleep(1);
1810 /* wake was emitted, but we were not sleeping */
1811 EnterCriticalSection (&condvar_crit
);
1812 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1813 LeaveCriticalSection (&condvar_crit
);
1814 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1815 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1818 while (condvar_seq
< 4) Sleep(1);
1820 /* wake all was emitted, but we were not sleeping */
1821 EnterCriticalSection (&condvar_crit
);
1822 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1823 LeaveCriticalSection (&condvar_crit
);
1824 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1825 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1827 EnterCriticalSection (&condvar_crit
);
1829 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1830 LeaveCriticalSection (&condvar_crit
);
1831 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1833 EnterCriticalSection (&condvar_crit
);
1835 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1836 LeaveCriticalSection (&condvar_crit
);
1837 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1840 EnterCriticalSection (&condvar_crit
);
1841 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1842 LeaveCriticalSection (&condvar_crit
);
1843 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1844 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1846 EnterCriticalSection (&condvar_crit
);
1848 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1849 LeaveCriticalSection (&condvar_crit
);
1850 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1852 /* skip over remaining tests if InitializeSRWLock is not available */
1853 if (!pInitializeSRWLock
)
1855 win_skip("no srw lock support.\n");
1856 condvar_seq
= 13; /* end */
1860 pAcquireSRWLockExclusive(&condvar_srwlock
);
1862 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1863 pReleaseSRWLockExclusive(&condvar_srwlock
);
1864 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1866 pAcquireSRWLockShared(&condvar_srwlock
);
1868 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1869 pReleaseSRWLockShared(&condvar_srwlock
);
1870 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1872 pAcquireSRWLockExclusive(&condvar_srwlock
);
1874 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1875 pReleaseSRWLockExclusive(&condvar_srwlock
);
1876 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1878 pAcquireSRWLockShared(&condvar_srwlock
);
1880 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1881 pReleaseSRWLockShared(&condvar_srwlock
);
1882 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1888 static void test_condvars_base(void) {
1894 if (!pInitializeConditionVariable
) {
1895 /* function is not yet in XP, only in newer Windows */
1896 win_skip("no condition variable support.\n");
1900 InitializeCriticalSection (&condvar_crit
);
1902 if (pInitializeSRWLock
)
1903 pInitializeSRWLock(&condvar_srwlock
);
1905 EnterCriticalSection (&condvar_crit
);
1906 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1907 LeaveCriticalSection (&condvar_crit
);
1909 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1910 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1912 if (pInitializeSRWLock
)
1914 pAcquireSRWLockExclusive(&condvar_srwlock
);
1915 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1916 pReleaseSRWLockExclusive(&condvar_srwlock
);
1918 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1919 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1921 pAcquireSRWLockShared(&condvar_srwlock
);
1922 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1923 pReleaseSRWLockShared(&condvar_srwlock
);
1925 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1926 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1930 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1931 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1933 condvar_seq
= 1; /* go */
1935 while (condvar_seq
< 9)
1937 WaitForSingleObject(hp
, 100);
1938 WaitForSingleObject(hc
, 100);
1941 static LONG srwlock_seq
= 0;
1942 static SRWLOCK srwlock_base
;
1945 LONG wrong_execution_order
;
1946 LONG samethread_excl_excl
;
1947 LONG samethread_excl_shared
;
1948 LONG samethread_shared_excl
;
1949 LONG multithread_excl_excl
;
1950 LONG excl_not_preferred
;
1952 LONG trylock_shared
;
1953 } srwlock_base_errors
;
1955 /* Sequence of acquire/release to check boundary conditions:
1958 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1959 * 2: thread1 expects a deadlock and releases the waiting lock
1960 * thread2 releases the lock again
1962 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1963 * 4: thread1 expects a deadlock and releases the waiting lock
1964 * thread2 releases the lock again
1966 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1967 * 6: thread1 expects a deadlock and releases the waiting lock
1968 * thread2 releases the lock again
1970 * 7: thread2 acquires and releases two nested shared locks
1972 * 8: thread1 acquires an exclusive lock
1973 * 9: thread2 tries to acquire the exclusive lock, too
1974 * thread1 releases the exclusive lock again
1975 * 10: thread2 enters the exclusive lock and leaves it immediately again
1977 * 11: thread1 acquires a shared lock
1978 * 12: thread2 acquires and releases a shared lock
1979 * thread1 releases the lock again
1981 * 13: thread1 acquires a shared lock
1982 * 14: thread2 tries to acquire an exclusive lock
1983 * 15: thread3 tries to acquire a shared lock
1984 * 16: thread1 releases the shared lock
1985 * 17: thread2 wakes up and releases the exclusive lock
1986 * 18: thread3 wakes up and releases the shared lock
1988 * the following tests will only be executed if TryAcquireSRWLock* is available
1990 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1991 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1992 * thread1 releases the exclusive lock
1994 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1995 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1996 * thread1 releases the shared lock
1998 * thread1 acquires an exclusive lock
1999 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
2000 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2001 * 21: thread1 releases the exclusive lock
2003 * thread1 acquires an shared lock
2004 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2005 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2006 * 23: thread1 releases the shared lock
2008 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2009 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2010 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2011 * 25: thread1 releases the exclusive lock
2013 * thread1 acquires two shared locks
2014 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2015 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2016 * 27: thread1 releases one shared lock
2017 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2018 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2019 * 29: thread1 releases the second shared lock
2020 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2021 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2026 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
2029 while (srwlock_seq
< 2) Sleep(1);
2031 if (InterlockedIncrement(&srwlock_seq
) != 3)
2032 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2033 pReleaseSRWLockExclusive(&srwlock_base
);
2036 while (srwlock_seq
< 4) Sleep(1);
2038 if (InterlockedIncrement(&srwlock_seq
) != 5)
2039 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2040 pReleaseSRWLockExclusive(&srwlock_base
);
2043 while (srwlock_seq
< 6) Sleep(1);
2045 if (InterlockedIncrement(&srwlock_seq
) != 7)
2046 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2047 pReleaseSRWLockShared(&srwlock_base
);
2050 while (srwlock_seq
< 8) Sleep(1);
2051 pAcquireSRWLockExclusive(&srwlock_base
);
2052 if (InterlockedIncrement(&srwlock_seq
) != 9)
2053 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2055 if (InterlockedIncrement(&srwlock_seq
) != 10)
2056 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2057 pReleaseSRWLockExclusive(&srwlock_base
);
2060 while (srwlock_seq
< 11) Sleep(1);
2061 pAcquireSRWLockShared(&srwlock_base
);
2062 if (InterlockedIncrement(&srwlock_seq
) != 12)
2063 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2066 while (srwlock_seq
< 13) Sleep(1);
2067 pReleaseSRWLockShared(&srwlock_base
);
2068 pAcquireSRWLockShared(&srwlock_base
);
2069 if (InterlockedIncrement(&srwlock_seq
) != 14)
2070 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2073 while (srwlock_seq
< 16) Sleep(1);
2074 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2075 if (InterlockedIncrement(&srwlock_seq
) != 17)
2076 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2077 pReleaseSRWLockShared(&srwlock_base
);
2079 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2080 if (!pTryAcquireSRWLockExclusive
)
2084 while (srwlock_seq
< 19) Sleep(1);
2085 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2087 if (pTryAcquireSRWLockShared(&srwlock_base
))
2088 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2089 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2090 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2091 pReleaseSRWLockExclusive(&srwlock_base
);
2094 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2096 if (pTryAcquireSRWLockShared(&srwlock_base
))
2098 if (pTryAcquireSRWLockShared(&srwlock_base
))
2099 pReleaseSRWLockShared(&srwlock_base
);
2101 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2102 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2103 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2104 pReleaseSRWLockShared(&srwlock_base
);
2107 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2109 pAcquireSRWLockExclusive(&srwlock_base
);
2110 if (InterlockedIncrement(&srwlock_seq
) != 20)
2111 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2114 while (srwlock_seq
< 21) Sleep(1);
2115 pReleaseSRWLockExclusive(&srwlock_base
);
2116 pAcquireSRWLockShared(&srwlock_base
);
2117 if (InterlockedIncrement(&srwlock_seq
) != 22)
2118 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2121 while (srwlock_seq
< 23) Sleep(1);
2122 pReleaseSRWLockShared(&srwlock_base
);
2123 pAcquireSRWLockShared(&srwlock_base
);
2124 if (InterlockedIncrement(&srwlock_seq
) != 24)
2125 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2128 pAcquireSRWLockExclusive(&srwlock_base
);
2129 if (srwlock_seq
!= 25)
2130 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2131 pReleaseSRWLockExclusive(&srwlock_base
);
2133 pAcquireSRWLockShared(&srwlock_base
);
2134 pAcquireSRWLockShared(&srwlock_base
);
2135 if (InterlockedIncrement(&srwlock_seq
) != 26)
2136 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2139 while (srwlock_seq
< 27) Sleep(1);
2140 pReleaseSRWLockShared(&srwlock_base
);
2141 if (InterlockedIncrement(&srwlock_seq
) != 28)
2142 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2145 while (srwlock_seq
< 29) Sleep(1);
2146 pReleaseSRWLockShared(&srwlock_base
);
2147 if (InterlockedIncrement(&srwlock_seq
) != 30)
2148 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2153 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
2156 while (srwlock_seq
< 1) Sleep(1);
2157 pAcquireSRWLockExclusive(&srwlock_base
);
2158 if (InterlockedIncrement(&srwlock_seq
) != 2)
2159 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2162 pAcquireSRWLockExclusive(&srwlock_base
);
2163 if (srwlock_seq
!= 3)
2164 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2165 pReleaseSRWLockExclusive(&srwlock_base
);
2166 pAcquireSRWLockExclusive(&srwlock_base
);
2167 if (InterlockedIncrement(&srwlock_seq
) != 4)
2168 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2171 pAcquireSRWLockShared(&srwlock_base
);
2172 if (srwlock_seq
!= 5)
2173 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2174 pReleaseSRWLockShared(&srwlock_base
);
2175 pAcquireSRWLockShared(&srwlock_base
);
2176 if (InterlockedIncrement(&srwlock_seq
) != 6)
2177 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2180 pAcquireSRWLockExclusive(&srwlock_base
);
2181 if (srwlock_seq
!= 7)
2182 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2183 pReleaseSRWLockExclusive(&srwlock_base
);
2184 pAcquireSRWLockShared(&srwlock_base
);
2185 pAcquireSRWLockShared(&srwlock_base
);
2186 pReleaseSRWLockShared(&srwlock_base
);
2187 pReleaseSRWLockShared(&srwlock_base
);
2188 if (InterlockedIncrement(&srwlock_seq
) != 8)
2189 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2192 while (srwlock_seq
< 9) Sleep(1);
2193 pAcquireSRWLockExclusive(&srwlock_base
);
2194 if (srwlock_seq
!= 10)
2195 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2196 pReleaseSRWLockExclusive(&srwlock_base
);
2197 if (InterlockedIncrement(&srwlock_seq
) != 11)
2198 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2201 while (srwlock_seq
< 12) Sleep(1);
2202 pAcquireSRWLockShared(&srwlock_base
);
2203 pReleaseSRWLockShared(&srwlock_base
);
2204 if (InterlockedIncrement(&srwlock_seq
) != 13)
2205 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2208 while (srwlock_seq
< 14) Sleep(1);
2209 if (InterlockedIncrement(&srwlock_seq
) != 15)
2210 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2213 pAcquireSRWLockExclusive(&srwlock_base
);
2214 if (srwlock_seq
!= 17)
2215 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2216 if (InterlockedIncrement(&srwlock_seq
) != 18)
2217 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2218 pReleaseSRWLockExclusive(&srwlock_base
);
2220 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2221 if (!pTryAcquireSRWLockExclusive
)
2225 while (srwlock_seq
< 20) Sleep(1);
2226 if (pTryAcquireSRWLockShared(&srwlock_base
))
2227 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2228 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2229 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2230 if (InterlockedIncrement(&srwlock_seq
) != 21)
2231 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2234 while (srwlock_seq
< 22) Sleep(1);
2235 if (pTryAcquireSRWLockShared(&srwlock_base
))
2236 pReleaseSRWLockShared(&srwlock_base
);
2238 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2239 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2240 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2241 if (InterlockedIncrement(&srwlock_seq
) != 23)
2242 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2245 while (srwlock_seq
< 24) Sleep(1);
2246 Sleep(50); /* ensure that exclusive access request is queued */
2247 if (pTryAcquireSRWLockShared(&srwlock_base
))
2249 pReleaseSRWLockShared(&srwlock_base
);
2250 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2252 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2253 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2254 if (InterlockedIncrement(&srwlock_seq
) != 25)
2255 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2256 pReleaseSRWLockShared(&srwlock_base
);
2259 while (srwlock_seq
< 26) Sleep(1);
2260 if (pTryAcquireSRWLockShared(&srwlock_base
))
2261 pReleaseSRWLockShared(&srwlock_base
);
2263 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2264 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2265 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2266 if (InterlockedIncrement(&srwlock_seq
) != 27)
2267 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2270 while (srwlock_seq
< 28) Sleep(1);
2271 if (pTryAcquireSRWLockShared(&srwlock_base
))
2272 pReleaseSRWLockShared(&srwlock_base
);
2274 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2275 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2276 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2277 if (InterlockedIncrement(&srwlock_seq
) != 29)
2278 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2281 while (srwlock_seq
< 30) Sleep(1);
2282 if (pTryAcquireSRWLockShared(&srwlock_base
))
2283 pReleaseSRWLockShared(&srwlock_base
);
2285 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2286 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2287 pReleaseSRWLockExclusive(&srwlock_base
);
2289 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2290 if (InterlockedIncrement(&srwlock_seq
) != 31)
2291 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2296 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2299 while (srwlock_seq
< 15) Sleep(1);
2300 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2301 if (InterlockedIncrement(&srwlock_seq
) != 16)
2302 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2305 pAcquireSRWLockShared(&srwlock_base
);
2306 if (srwlock_seq
!= 18)
2307 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2308 pReleaseSRWLockShared(&srwlock_base
);
2309 if (InterlockedIncrement(&srwlock_seq
) != 19)
2310 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2312 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2313 if (!pTryAcquireSRWLockExclusive
)
2315 /* function is only in Windows 7 and newer */
2316 win_skip("no srw trylock support.\n");
2317 srwlock_seq
= 31; /* end */
2324 static void test_srwlock_base(void)
2329 if (!pInitializeSRWLock
)
2331 /* function is not yet in XP, only in newer Windows */
2332 win_skip("no srw lock support.\n");
2336 pInitializeSRWLock(&srwlock_base
);
2337 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2339 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2340 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2341 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2343 srwlock_seq
= 1; /* go */
2344 while (srwlock_seq
< 31)
2347 WaitForSingleObject(h1
, 100);
2348 WaitForSingleObject(h2
, 100);
2349 WaitForSingleObject(h3
, 100);
2351 ok(!srwlock_base_errors
.wrong_execution_order
,
2352 "thread commands were executed in the wrong order (occurred %d times).\n",
2353 srwlock_base_errors
.wrong_execution_order
);
2355 ok(!srwlock_base_errors
.samethread_excl_excl
,
2356 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2357 srwlock_base_errors
.samethread_excl_excl
);
2359 ok(!srwlock_base_errors
.samethread_excl_shared
,
2360 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2361 srwlock_base_errors
.samethread_excl_shared
);
2363 ok(!srwlock_base_errors
.samethread_shared_excl
,
2364 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2365 srwlock_base_errors
.samethread_shared_excl
);
2367 ok(!srwlock_base_errors
.multithread_excl_excl
,
2368 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2369 srwlock_base_errors
.multithread_excl_excl
);
2371 ok(!srwlock_base_errors
.excl_not_preferred
,
2372 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2373 srwlock_base_errors
.excl_not_preferred
);
2375 ok(!srwlock_base_errors
.trylock_excl
,
2376 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2377 srwlock_base_errors
.trylock_excl
);
2379 ok(!srwlock_base_errors
.trylock_shared
,
2380 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2381 srwlock_base_errors
.trylock_shared
);
2385 static SRWLOCK srwlock_example
;
2386 static LONG srwlock_protected_value
= 0;
2387 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2388 static BOOL srwlock_stop
= FALSE
;
2390 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2394 while (!srwlock_stop
)
2397 /* periodically request exclusive access */
2398 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2400 pAcquireSRWLockExclusive(&srwlock_example
);
2401 if (InterlockedIncrement(&srwlock_inside
) != 1)
2402 InterlockedIncrement(&srwlock_example_errors
);
2404 InterlockedIncrement(&srwlock_protected_value
);
2407 if (InterlockedDecrement(&srwlock_inside
) != 0)
2408 InterlockedIncrement(&srwlock_example_errors
);
2409 pReleaseSRWLockExclusive(&srwlock_example
);
2412 /* request shared access */
2413 pAcquireSRWLockShared(&srwlock_example
);
2414 InterlockedIncrement(&srwlock_inside
);
2415 old
= srwlock_protected_value
;
2420 if (old
!= srwlock_protected_value
)
2421 InterlockedIncrement(&srwlock_example_errors
);
2422 InterlockedDecrement(&srwlock_inside
);
2423 pReleaseSRWLockShared(&srwlock_example
);
2429 static void test_srwlock_example(void)
2433 DWORD cnt1
, cnt2
, cnt3
;
2435 if (!pInitializeSRWLock
) {
2436 /* function is not yet in XP, only in newer Windows */
2437 win_skip("no srw lock support.\n");
2441 pInitializeSRWLock(&srwlock_example
);
2443 cnt1
= cnt2
= cnt3
= 0;
2445 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2446 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2447 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2449 /* limit run to 1 second. */
2452 /* tear down start */
2453 srwlock_stop
= TRUE
;
2455 WaitForSingleObject(h1
, 1000);
2456 WaitForSingleObject(h2
, 1000);
2457 WaitForSingleObject(h3
, 1000);
2459 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2460 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2461 srwlock_example_errors
);
2463 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2464 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2467 static DWORD WINAPI
alertable_wait_thread(void *param
)
2469 HANDLE
*semaphores
= param
;
2470 LARGE_INTEGER timeout
;
2474 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2475 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 1000, TRUE
);
2476 ok(result
== WAIT_IO_COMPLETION
, "expected WAIT_IO_COMPLETION, got %u\n", result
);
2477 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 200, TRUE
);
2478 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2480 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2481 timeout
.QuadPart
= -10000000;
2482 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2483 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2484 timeout
.QuadPart
= -2000000;
2485 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2486 ok(status
== STATUS_WAIT_0
, "expected STATUS_WAIT_0, got %08x\n", status
);
2488 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2489 timeout
.QuadPart
= -10000000;
2490 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2491 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2492 result
= WaitForSingleObject(semaphores
[0], 0);
2493 ok(result
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", result
);
2498 static void CALLBACK
alertable_wait_apc(ULONG_PTR userdata
)
2500 HANDLE
*semaphores
= (void *)userdata
;
2501 ReleaseSemaphore(semaphores
[1], 1, NULL
);
2504 static void CALLBACK
alertable_wait_apc2(ULONG_PTR userdata
)
2506 HANDLE
*semaphores
= (void *)userdata
;
2509 result
= WaitForSingleObject(semaphores
[0], 1000);
2510 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2513 static void test_alertable_wait(void)
2515 HANDLE thread
, semaphores
[2];
2518 semaphores
[0] = CreateSemaphoreW(NULL
, 0, 2, NULL
);
2519 ok(semaphores
[0] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2520 semaphores
[1] = CreateSemaphoreW(NULL
, 0, 1, NULL
);
2521 ok(semaphores
[1] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2522 thread
= CreateThread(NULL
, 0, alertable_wait_thread
, semaphores
, 0, NULL
);
2523 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2525 result
= WaitForSingleObject(semaphores
[0], 1000);
2526 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2527 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2528 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2529 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2531 result
= WaitForSingleObject(semaphores
[0], 1000);
2532 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2533 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2534 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2535 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2537 result
= WaitForSingleObject(semaphores
[0], 1000);
2538 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2539 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2540 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2541 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2542 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2543 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2544 ReleaseSemaphore(semaphores
[0], 2, NULL
);
2546 result
= WaitForSingleObject(thread
, 1000);
2547 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2548 CloseHandle(thread
);
2549 CloseHandle(semaphores
[0]);
2550 CloseHandle(semaphores
[1]);
2553 struct apc_deadlock_info
2555 PROCESS_INFORMATION
*pi
;
2560 static DWORD WINAPI
apc_deadlock_thread(void *param
)
2562 struct apc_deadlock_info
*info
= param
;
2563 PROCESS_INFORMATION
*pi
= info
->pi
;
2568 while (info
->running
)
2572 status
= pNtAllocateVirtualMemory(pi
->hProcess
, &base
, 0, &size
,
2573 MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2574 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2575 ok(base
!= NULL
, "expected base != NULL, got %p\n", base
);
2576 SetEvent(info
->event
);
2579 status
= pNtFreeVirtualMemory(pi
->hProcess
, &base
, &size
, MEM_RELEASE
);
2580 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2581 SetEvent(info
->event
);
2587 static void test_apc_deadlock(void)
2589 struct apc_deadlock_info info
;
2590 PROCESS_INFORMATION pi
;
2591 STARTUPINFOA si
= { sizeof(si
) };
2592 char cmdline
[MAX_PATH
];
2593 HANDLE event
, thread
;
2599 winetest_get_mainargs(&argv
);
2600 sprintf(cmdline
, "\"%s\" sync apc_deadlock", argv
[0]);
2601 success
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2602 ok(success
, "CreateProcess failed with %u\n", GetLastError());
2604 event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2605 ok(event
!= NULL
, "CreateEvent failed with %u\n", GetLastError());
2609 info
.running
= TRUE
;
2611 thread
= CreateThread(NULL
, 0, apc_deadlock_thread
, &info
, 0, NULL
);
2612 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2613 result
= WaitForSingleObject(event
, 1000);
2614 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2616 for (i
= 0; i
< 1000; i
++)
2618 result
= SuspendThread(pi
.hThread
);
2619 ok(result
== 0, "expected 0, got %u\n", result
);
2621 WaitForSingleObject(event
, 0); /* reset event */
2622 result
= WaitForSingleObject(event
, 1000);
2623 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2625 result
= ResumeThread(pi
.hThread
);
2626 ok(result
== 1, "expected 1, got %u\n", result
);
2630 info
.running
= FALSE
;
2631 result
= WaitForSingleObject(thread
, 1000);
2632 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2633 CloseHandle(thread
);
2636 TerminateProcess(pi
.hProcess
, 0);
2637 CloseHandle(pi
.hThread
);
2638 CloseHandle(pi
.hProcess
);
2645 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2646 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2648 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2649 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2650 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2651 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2652 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2653 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2654 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2655 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2656 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2657 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2658 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2659 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2660 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2661 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2662 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2663 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2664 pNtAllocateVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtAllocateVirtualMemory");
2665 pNtFreeVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtFreeVirtualMemory");
2666 pNtWaitForSingleObject
= (void *)GetProcAddress(hntdll
, "NtWaitForSingleObject");
2667 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2668 pRtlInterlockedPushListSList
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSList");
2669 pRtlInterlockedPushListSListEx
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSListEx");
2671 argc
= winetest_get_mainargs( &argv
);
2674 if (!strcmp(argv
[2], "apc_deadlock"))
2676 for (;;) SleepEx(INFINITE
, TRUE
);
2681 init_fastcall_thunk();
2682 test_signalandwait();
2687 test_waitable_timer();
2688 test_iocp_callback();
2690 test_WaitForSingleObject();
2691 test_WaitForMultipleObjects();
2693 test_condvars_base();
2694 test_condvars_consumer_producer();
2695 test_srwlock_base();
2696 test_srwlock_example();
2697 test_alertable_wait();
2698 test_apc_deadlock();