2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 //#define _WIN32_WINNT 0x500
27 #include <wine/winternl.h>
29 #include <wine/test.h>
31 #define QueryDepthSList(x) RtlQueryDepthSList(x)
32 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y)
33 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x)
34 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x)
37 #define __fastcall __stdcall
39 static BOOL (WINAPI
*pChangeTimerQueueTimer
)(HANDLE
, HANDLE
, ULONG
, ULONG
);
40 static HANDLE (WINAPI
*pCreateTimerQueue
)(void);
41 static BOOL (WINAPI
*pCreateTimerQueueTimer
)(PHANDLE
, HANDLE
, WAITORTIMERCALLBACK
,
42 PVOID
, DWORD
, DWORD
, ULONG
);
43 static HANDLE (WINAPI
*pCreateWaitableTimerA
)(SECURITY_ATTRIBUTES
*,BOOL
,LPCSTR
);
44 static BOOL (WINAPI
*pDeleteTimerQueueEx
)(HANDLE
, HANDLE
);
45 static BOOL (WINAPI
*pDeleteTimerQueueTimer
)(HANDLE
, HANDLE
, HANDLE
);
46 static HANDLE (WINAPI
*pOpenWaitableTimerA
)(DWORD
,BOOL
,LPCSTR
);
47 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
48 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
49 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
50 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
51 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
52 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
54 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
55 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
56 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
57 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
58 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
60 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
61 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
62 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
63 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
64 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
65 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
66 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
68 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
69 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
70 static NTSTATUS (WINAPI
*pNtWaitForSingleObject
)(HANDLE
, BOOLEAN
, const LARGE_INTEGER
*);
71 static NTSTATUS (WINAPI
*pNtWaitForMultipleObjects
)(ULONG
,const HANDLE
*,BOOLEAN
,BOOLEAN
,const LARGE_INTEGER
*);
72 static PSLIST_ENTRY (__fastcall
*pRtlInterlockedPushListSList
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
73 PSLIST_ENTRY last
, ULONG count
);
74 static PSLIST_ENTRY (WINAPI
*pRtlInterlockedPushListSListEx
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
75 PSLIST_ENTRY last
, ULONG count
);
82 BYTE pop_edx
; /* popl %edx (ret addr) */
83 BYTE pop_eax
; /* popl %eax (func) */
84 BYTE pop_ecx
; /* popl %ecx (param 1) */
85 BYTE xchg
[3]; /* xchgl (%esp),%edx (param 2) */
86 WORD jmp_eax
; /* jmp *%eax */
90 static void * (WINAPI
*call_fastcall_func4
)(void *func
, const void *a
, const void *b
, const void *c
, const void *d
);
92 static void init_fastcall_thunk(void)
94 struct fastcall_thunk
*thunk
= VirtualAlloc(NULL
, sizeof(*thunk
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
95 thunk
->pop_edx
= 0x5a; /* popl %edx */
96 thunk
->pop_eax
= 0x58; /* popl %eax */
97 thunk
->pop_ecx
= 0x59; /* popl %ecx */
98 thunk
->xchg
[0] = 0x87; /* xchgl (%esp),%edx */
99 thunk
->xchg
[1] = 0x14;
100 thunk
->xchg
[2] = 0x24;
101 thunk
->jmp_eax
= 0xe0ff; /* jmp *%eax */
102 call_fastcall_func4
= (void *)thunk
;
105 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
106 (const void *)(b), (const void *)(c), (const void *)(d))
110 #define init_fastcall_thunk() do { } while(0)
111 #define call_func4(func, a, b, c, d) func(a, b, c, d)
113 #endif /* __i386__ */
115 static void test_signalandwait(void)
117 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
120 HANDLE event
[2], semaphore
[2], file
;
123 kernel32
= GetModuleHandleA("kernel32.dll");
124 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
126 if (!pSignalObjectAndWait
)
129 /* invalid parameters */
130 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
131 if (r
== ERROR_INVALID_FUNCTION
)
133 win_skip("SignalObjectAndWait is not implemented\n");
134 return; /* Win98/ME */
136 ok( r
== WAIT_FAILED
, "should fail\n");
138 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
139 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
141 ok( event
[0] && event
[1], "failed to create event flags\n");
143 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
144 ok( r
== WAIT_FAILED
, "should fail\n");
146 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
147 ok( r
== WAIT_FAILED
, "should fail\n");
150 /* valid parameters */
151 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
152 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
154 /* event[0] is now signalled - we repeat this test multiple times
155 * to ensure that the wineserver handles this situation properly. */
156 for (i
= 0; i
< 10000; i
++)
158 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
159 ok(r
== WAIT_OBJECT_0
, "should succeed\n");
162 /* event[0] is not signalled */
163 r
= WaitForSingleObject(event
[0], 0);
164 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
166 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
167 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
169 /* clear event[1] and check for a timeout */
170 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
171 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
172 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
174 CloseHandle(event
[0]);
175 CloseHandle(event
[1]);
178 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
179 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
180 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
182 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
183 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
185 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
186 ok( r
== WAIT_FAILED
, "should fail\n");
188 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
189 ok( r
== FALSE
, "should fail\n");
191 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
192 ok( r
== TRUE
, "should succeed\n");
194 CloseHandle(semaphore
[0]);
195 CloseHandle(semaphore
[1]);
197 /* try a registry key */
198 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
199 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
200 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
201 ok( r
== WAIT_FAILED
, "should fail\n");
202 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
206 static void test_mutex(void)
215 SetLastError(0xdeadbeef);
216 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
217 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
218 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
220 SetLastError(0xdeadbeef);
221 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
222 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
224 SetLastError(0xdeadbeef);
225 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
227 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
229 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
231 SetLastError(0xdeadbeef);
232 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
233 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
234 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
235 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
236 CloseHandle(hOpened
);
238 for(i
=0; i
< 31; i
++)
240 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
241 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
244 SetLastError(0xdeadbeef);
245 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
246 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
247 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
248 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
249 CloseHandle(hOpened
);
251 for (i
= 0; i
< 32; i
++)
253 SetLastError(0xdeadbeef);
254 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
257 SetLastError(0xdeadbeef);
258 ret
= ReleaseMutex(hOpened
);
259 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
260 CloseHandle(hOpened
);
264 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
265 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
267 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
268 ReleaseMutex(hCreated
);
274 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
276 SetLastError(0xdeadbeef);
277 ret
= ReleaseMutex(hCreated
);
278 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
279 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
281 /* test case sensitivity */
283 SetLastError(0xdeadbeef);
284 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
285 ok(!hOpened
, "OpenMutex succeeded\n");
286 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
288 SetLastError(0xdeadbeef);
289 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
290 ok(!hOpened
, "OpenMutex succeeded\n");
291 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
293 SetLastError(0xdeadbeef);
294 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
295 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
296 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
297 CloseHandle(hOpened
);
299 SetLastError(0xdeadbeef);
300 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
301 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
302 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
303 CloseHandle(hOpened
);
305 CloseHandle(hCreated
);
308 static void test_slist(void)
314 } item1
, item2
, item3
, *item
;
315 SLIST_HEADER slist_header
;
324 memset(&slist_header
, 0xff, sizeof(slist_header
));
325 InitializeSListHead(&slist_header
);
326 size
= QueryDepthSList(&slist_header
);
327 ok(size
== 0, "Expected size == 0, got %u\n", size
);
329 /* test PushEntry, PopEntry and Flush */
330 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
331 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
332 size
= QueryDepthSList(&slist_header
);
333 ok(size
== 1, "Expected size == 1, got %u\n", size
);
335 entry
= InterlockedPushEntrySList(&slist_header
, &item2
.entry
);
336 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
337 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
338 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
339 size
= QueryDepthSList(&slist_header
);
340 ok(size
== 2, "Expected size == 2, got %u\n", size
);
342 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
343 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
344 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
345 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
346 size
= QueryDepthSList(&slist_header
);
347 ok(size
== 3, "Expected size == 3, got %u\n", size
);
349 entry
= InterlockedPopEntrySList(&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
== 3, "Expected item->value == 3, got %u\n", item
->value
);
353 size
= QueryDepthSList(&slist_header
);
354 ok(size
== 2, "Expected size == 2, got %u\n", size
);
356 entry
= InterlockedFlushSList(&slist_header
);
357 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
358 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
359 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
360 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
361 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
362 size
= QueryDepthSList(&slist_header
);
363 ok(size
== 0, "Expected size == 0, got %u\n", size
);
364 entry
= InterlockedPopEntrySList(&slist_header
);
365 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
367 /* test RtlInterlockedPushListSList */
368 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
369 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
370 entry
= call_func4(pRtlInterlockedPushListSList
, &slist_header
, &item2
.entry
, &item1
.entry
, 42);
371 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
372 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
373 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
374 size
= QueryDepthSList(&slist_header
);
375 ok(size
== 43, "Expected size == 43, 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
== 2, "Expected item->value == 2, got %u\n", item
->value
);
381 size
= QueryDepthSList(&slist_header
);
382 ok(size
== 42, "Expected size == 42, 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
== 1, "Expected item->value == 1, got %u\n", item
->value
);
388 size
= QueryDepthSList(&slist_header
);
389 ok(size
== 41, "Expected size == 41, got %u\n", size
);
391 entry
= InterlockedPopEntrySList(&slist_header
);
392 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
393 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
394 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
395 size
= QueryDepthSList(&slist_header
);
396 ok(size
== 40, "Expected size == 40, got %u\n", size
);
398 entry
= InterlockedPopEntrySList(&slist_header
);
399 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
400 size
= QueryDepthSList(&slist_header
);
401 ok(size
== 40, "Expected size == 40, got %u\n", size
);
403 entry
= InterlockedFlushSList(&slist_header
);
404 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
405 size
= QueryDepthSList(&slist_header
);
406 ok(size
== 40 || broken(size
== 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size
);
408 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
409 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
410 entry
= InterlockedFlushSList(&slist_header
);
411 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
412 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
413 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
414 size
= QueryDepthSList(&slist_header
);
415 ok(size
== 0, "Expected size == 0, got %u\n", size
);
417 /* test RtlInterlockedPushListSListEx */
418 if (pRtlInterlockedPushListSListEx
)
420 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
421 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
422 entry
= pRtlInterlockedPushListSListEx(&slist_header
, &item2
.entry
, &item1
.entry
, 42);
423 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
424 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
425 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
426 size
= QueryDepthSList(&slist_header
);
427 ok(size
== 43, "Expected size == 43, got %u\n", size
);
429 entry
= InterlockedFlushSList(&slist_header
);
430 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
431 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
432 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
433 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
434 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
435 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
436 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
437 size
= QueryDepthSList(&slist_header
);
438 ok(size
== 0, "Expected size == 0, got %u\n", size
);
441 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
443 /* test with a lot of items */
444 for (i
= 0; i
< 65536; i
++)
446 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
448 entry
= InterlockedPushEntrySList(&slist_header
, &item
->entry
);
451 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
452 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
453 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
457 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
459 size
= QueryDepthSList(&slist_header
);
460 ok(size
== ((i
+ 1) & 0xffff), "Expected size == %u, got %u\n", (i
+ 1) & 0xffff, size
);
463 entry
= InterlockedFlushSList(&slist_header
);
464 for (i
= 65536; i
> 0; i
--)
466 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
467 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
468 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
469 entry
= item
->entry
.Next
;
470 HeapFree(GetProcessHeap(), 0, item
);
472 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
473 size
= QueryDepthSList(&slist_header
);
474 ok(size
== 0, "Expected size == 0, got %u\n", size
);
475 entry
= InterlockedPopEntrySList(&slist_header
);
476 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
479 static void test_event(void)
481 HANDLE handle
, handle2
;
482 SECURITY_ATTRIBUTES sa
;
483 SECURITY_DESCRIPTOR sd
;
489 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
490 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
493 sa
.nLength
= sizeof(sa
);
494 sa
.lpSecurityDescriptor
= &sd
;
495 sa
.bInheritHandle
= FALSE
;
497 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
500 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
501 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
504 /* sd with NULL dacl */
505 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, 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 /* sd with empty dacl */
511 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
512 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
513 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
514 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
517 /* test case sensitivity */
519 SetLastError(0xdeadbeef);
520 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
521 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
522 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
524 SetLastError(0xdeadbeef);
525 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
526 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
527 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
528 CloseHandle( handle2
);
530 SetLastError(0xdeadbeef);
531 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
532 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
533 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
534 CloseHandle( handle2
);
536 SetLastError(0xdeadbeef);
537 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
538 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
539 CloseHandle( handle2
);
541 SetLastError(0xdeadbeef);
542 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
543 ok( !handle2
, "OpenEvent succeeded\n");
544 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
546 CloseHandle( handle
);
548 /* resource notifications are events too */
550 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
552 trace( "memory resource notifications not supported\n" );
555 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
556 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
557 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
558 ret
= pQueryMemoryResourceNotification( handle
, &val
);
559 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
560 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
562 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
563 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
564 ret
= WaitForSingleObject( handle
, 10 );
565 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
568 ret
= pQueryMemoryResourceNotification( handle
, &val
);
569 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
570 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
571 ret
= CloseHandle( handle
);
572 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
574 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
576 ret
= pQueryMemoryResourceNotification( handle
, &val
);
577 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
578 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
579 CloseHandle( handle
);
582 static void test_semaphore(void)
584 HANDLE handle
, handle2
;
586 /* test case sensitivity */
588 SetLastError(0xdeadbeef);
589 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
590 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
591 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
593 SetLastError(0xdeadbeef);
594 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
595 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
596 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
597 CloseHandle( handle2
);
599 SetLastError(0xdeadbeef);
600 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
601 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
602 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
603 CloseHandle( handle2
);
605 SetLastError(0xdeadbeef);
606 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
607 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
608 CloseHandle( handle2
);
610 SetLastError(0xdeadbeef);
611 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
612 ok( !handle2
, "OpenSemaphore succeeded\n");
613 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
615 CloseHandle( handle
);
618 static void test_waitable_timer(void)
620 HANDLE handle
, handle2
;
622 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
624 win_skip("{Create,Open}WaitableTimerA() is not available\n");
628 /* test case sensitivity */
630 SetLastError(0xdeadbeef);
631 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
632 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
633 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
635 SetLastError(0xdeadbeef);
636 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
637 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
638 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
639 CloseHandle( handle2
);
641 SetLastError(0xdeadbeef);
642 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
643 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
644 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
645 CloseHandle( handle2
);
647 SetLastError(0xdeadbeef);
648 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
649 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
650 CloseHandle( handle2
);
652 SetLastError(0xdeadbeef);
653 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
654 ok( !handle2
, "OpenWaitableTimer succeeded\n");
655 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
656 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
657 "wrong error %u\n", GetLastError());
659 CloseHandle( handle
);
662 static HANDLE sem
= 0;
664 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
666 ReleaseSemaphore(sem
, 1, NULL
);
669 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
671 static void test_iocp_callback(void)
673 char temp_path
[MAX_PATH
];
674 char filename
[MAX_PATH
];
677 static const char prefix
[] = "pfx";
679 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
681 const char *buffer
= "12345678123456781234567812345678";
682 OVERLAPPED overlapped
;
684 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
685 if(!p_BindIoCompletionCallback
) {
686 win_skip("BindIoCompletionCallback not found in this DLL\n");
690 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
691 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
693 ret
= GetTempPathA(MAX_PATH
, temp_path
);
694 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
695 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
697 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
698 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
700 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
701 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
702 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
704 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
705 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
706 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
708 ret
= CloseHandle(hFile
);
709 ok( ret
, "CloseHandle: error %d\n", GetLastError());
710 ret
= DeleteFileA(filename
);
711 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
713 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
714 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
715 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
717 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
718 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
720 memset(&overlapped
, 0, sizeof(overlapped
));
721 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
722 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
724 ret
= WaitForSingleObject(sem
, 5000);
725 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
728 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
729 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
730 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
731 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
732 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
733 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
735 ret
= CloseHandle(hFile
);
736 ok( ret
, "CloseHandle: error %d\n", GetLastError());
737 ret
= DeleteFileA(filename
);
738 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
740 /* win2k3 requires the Flags parameter to be zero */
741 SetLastError(0xdeadbeef);
742 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
743 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
744 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
745 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
747 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
748 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
750 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
751 ret
= CloseHandle(hFile
);
752 ok( ret
, "CloseHandle: error %d\n", GetLastError());
753 ret
= DeleteFileA(filename
);
754 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
756 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
757 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
758 ok(GetLastError() == ERROR_INVALID_HANDLE
||
759 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
760 "Last error is %d\n", GetLastError());
763 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
766 ok(timedOut
, "Timer callbacks should always time out\n");
770 struct timer_queue_data1
777 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
779 struct timer_queue_data1
*d
= p
;
780 ok(timedOut
, "Timer callbacks should always time out\n");
781 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
784 SetLastError(0xdeadbeef);
785 /* Note, XP SP2 does *not* do any deadlock checking, so passing
786 INVALID_HANDLE_VALUE here will just hang. */
787 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
788 ok(!ret
, "DeleteTimerQueueTimer\n");
789 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
793 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
795 struct timer_queue_data1
*d
= p
;
796 ok(timedOut
, "Timer callbacks should always time out\n");
797 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
799 /* Basically kill the timer since it won't have time to run
801 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
802 ok(ret
, "ChangeTimerQueueTimer\n");
806 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
808 struct timer_queue_data1
*d
= p
;
809 ok(timedOut
, "Timer callbacks should always time out\n");
812 /* This tests whether a timer gets flagged for deletion before
813 or after the callback runs. If we start this timer with a
814 period of zero (run once), then ChangeTimerQueueTimer will
815 fail if the timer is already flagged. Hence we really run
816 only once. Otherwise we will run multiple times. */
817 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
818 ok(ret
, "ChangeTimerQueueTimer\n");
823 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
825 DWORD_PTR delay
= (DWORD_PTR
) p
;
826 ok(timedOut
, "Timer callbacks should always time out\n");
831 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
833 struct timer_queue_data1
*d
= p
;
834 ok(timedOut
, "Timer callbacks should always time out\n");
835 /* This tests an original implementation bug where a deleted timer may get
836 to run, but it is tricky to set up. */
837 if (d
->q
&& d
->num_calls
++ == 0)
839 /* First run: delete ourselves, then insert and remove a timer
840 that goes in front of us in the sorted timeout list. Once
841 removed, we will still timeout at the faster timer's due time,
842 but this should be a no-op if we are bug-free. There should
843 not be a second run. We can test the value of num_calls later. */
847 /* The delete will pend while we are in this callback. */
848 SetLastError(0xdeadbeef);
849 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
850 ok(!ret
, "DeleteTimerQueueTimer\n");
851 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
853 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
854 ok(ret
, "CreateTimerQueueTimer\n");
855 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
857 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
858 ok(ret
, "DeleteTimerQueueTimer\n");
860 /* Now we stay alive by hanging around in the callback. */
865 static void test_timer_queue(void)
867 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
868 int n0
, n1
, n2
, n3
, n4
, n5
;
869 struct timer_queue_data1 d1
, d2
, d3
, d4
;
873 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
874 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
876 win_skip("TimerQueue API not present\n");
880 /* Test asynchronous deletion of the queue. */
881 q
= pCreateTimerQueue();
882 ok(q
!= NULL
, "CreateTimerQueue\n");
884 SetLastError(0xdeadbeef);
885 ret
= pDeleteTimerQueueEx(q
, NULL
);
886 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
887 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
890 /* Test synchronous deletion of the queue and running timers. */
891 q
= pCreateTimerQueue();
892 ok(q
!= NULL
, "CreateTimerQueue\n");
897 ret
= pCreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0,
899 ok(ret
, "CreateTimerQueueTimer\n");
900 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
901 ret0
= pDeleteTimerQueueTimer(q
, t0
, NULL
);
902 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
903 broken(ret0
), /* Win 2000 & XP & 2003 */
904 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
909 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
911 ok(ret
, "CreateTimerQueueTimer\n");
912 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
917 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
919 ok(ret
, "CreateTimerQueueTimer\n");
920 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
925 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
927 ok(ret
, "CreateTimerQueueTimer\n");
928 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
930 /* Start really late (it won't start). */
933 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
935 ok(ret
, "CreateTimerQueueTimer\n");
936 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
938 /* Start soon, but delay so long it won't run again. */
941 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
943 ok(ret
, "CreateTimerQueueTimer\n");
944 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
946 /* Give them a chance to do some work. */
949 /* Test deleting a once-only timer. */
950 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
951 ok(ret
, "DeleteTimerQueueTimer\n");
953 /* A periodic timer. */
954 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
955 ok(ret
, "DeleteTimerQueueTimer\n");
957 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
958 ok(ret
, "DeleteTimerQueueEx\n");
960 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
961 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
962 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
963 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
964 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
966 /* Test synchronous deletion of the timer/queue with event trigger. */
967 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
968 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
969 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
970 if (!e
|| !et1
|| !et2
)
972 skip("Failed to create timer queue descruction event\n");
976 q
= pCreateTimerQueue();
977 ok(q
!= NULL
, "CreateTimerQueue\n");
979 /* Run once and finish quickly (should be done when we delete it). */
981 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
982 ok(ret
, "CreateTimerQueueTimer\n");
983 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
985 /* Run once and finish slowly (shouldn't be done when we delete it). */
987 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
989 ok(ret
, "CreateTimerQueueTimer\n");
990 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
992 /* Run once and finish quickly (should be done when we delete it). */
994 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
995 ok(ret
, "CreateTimerQueueTimer\n");
996 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
998 /* Run once and finish slowly (shouldn't be done when we delete it). */
1000 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 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
= pDeleteTimerQueueTimer(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
= pDeleteTimerQueueTimer(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
= pDeleteTimerQueueTimer(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
= pDeleteTimerQueueTimer(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
= pDeleteTimerQueueEx(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
= pCreateTimerQueue();
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
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
1059 ok(ret
, "CreateTimerQueueTimer\n");
1060 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1061 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
1062 ok(ret
, "ChangeTimerQueueTimer\n");
1068 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
1071 ok(ret
, "CreateTimerQueueTimer\n");
1072 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1078 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
1081 ok(ret
, "CreateTimerQueueTimer\n");
1082 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
1087 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
1090 ok(ret
, "CreateTimerQueueTimer\n");
1091 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1095 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
1096 ok(ret
, "DeleteTimerQueueEx\n");
1097 ok(n1
== 1, "ChangeTimerQueueTimer\n");
1098 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
1099 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
1100 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
1102 /* Test an obscure bug that was in the original implementation. */
1103 q
= pCreateTimerQueue();
1104 ok(q
!= NULL
, "CreateTimerQueue\n");
1106 /* All the work is done in the callback. */
1110 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
1111 100, WT_EXECUTELONGFUNCTION
);
1113 ok(ret
, "CreateTimerQueueTimer\n");
1114 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1118 SetLastError(0xdeadbeef);
1119 ret
= pDeleteTimerQueueEx(q
, NULL
);
1120 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1121 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1123 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1125 /* Test functions on the default timer queue. */
1128 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
1130 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1131 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1133 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1134 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1136 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1137 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1139 /* Try mixing default and non-default queues. Apparently this works. */
1140 q
= pCreateTimerQueue();
1141 ok(q
!= NULL
, "CreateTimerQueue\n");
1145 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
1147 ok(ret
, "CreateTimerQueueTimer\n");
1148 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1152 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
1154 ok(ret
, "CreateTimerQueueTimer\n");
1155 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1157 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1158 ok(ret
, "ChangeTimerQueueTimer\n");
1160 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1161 ok(ret
, "ChangeTimerQueueTimer\n");
1163 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1164 ok(ret
, "DeleteTimerQueueTimer\n");
1166 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1167 ok(ret
, "DeleteTimerQueueTimer\n");
1169 /* Try to delete the default queue? In any case: not allowed. */
1170 SetLastError(0xdeadbeef);
1171 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
1172 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1173 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1174 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1177 SetLastError(0xdeadbeef);
1178 ret
= pDeleteTimerQueueEx(q
, NULL
);
1179 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1180 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1184 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1186 DWORD tmp
= HandleToULong(handle
);
1188 return ULongToHandle(tmp
);
1191 static void test_WaitForSingleObject(void)
1193 HANDLE signaled
, nonsignaled
, invalid
;
1194 LARGE_INTEGER timeout
;
1198 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1199 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1200 invalid
= (HANDLE
) 0xdeadbee0;
1202 /* invalid handle with different values for lower 2 bits */
1203 SetLastError(0xdeadbeef);
1204 ret
= WaitForSingleObject(invalid
, 0);
1205 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1206 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1208 SetLastError(0xdeadbeef);
1209 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1210 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1211 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1213 SetLastError(0xdeadbeef);
1214 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1215 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1216 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1218 SetLastError(0xdeadbeef);
1219 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1220 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1221 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1223 /* valid handle with different values for lower 2 bits */
1224 SetLastError(0xdeadbeef);
1225 ret
= WaitForSingleObject(nonsignaled
, 0);
1226 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1227 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1229 SetLastError(0xdeadbeef);
1230 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1231 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1232 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1234 SetLastError(0xdeadbeef);
1235 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1236 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1237 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1239 SetLastError(0xdeadbeef);
1240 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1241 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1242 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1244 /* valid handle with different values for lower 2 bits */
1245 SetLastError(0xdeadbeef);
1246 ret
= WaitForSingleObject(signaled
, 0);
1247 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1248 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1250 SetLastError(0xdeadbeef);
1251 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1252 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1253 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1255 SetLastError(0xdeadbeef);
1256 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1257 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1258 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1260 SetLastError(0xdeadbeef);
1261 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1262 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1263 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1265 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1266 ret
= WaitForSingleObject(GetCurrentProcess(), 100);
1267 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1269 ret
= WaitForSingleObject(GetCurrentThread(), 100);
1270 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1272 timeout
.QuadPart
= -1000000;
1273 status
= pNtWaitForSingleObject(GetCurrentProcess(), FALSE
, &timeout
);
1274 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1276 timeout
.QuadPart
= -1000000;
1277 status
= pNtWaitForSingleObject(GetCurrentThread(), FALSE
, &timeout
);
1278 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1280 CloseHandle(signaled
);
1281 CloseHandle(nonsignaled
);
1284 static void test_WaitForMultipleObjects(void)
1286 LARGE_INTEGER timeout
;
1290 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1292 /* create the maximum number of events and make sure
1293 * we can wait on that many */
1294 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1296 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1297 ok( maxevents
[i
] != 0, "should create enough events\n");
1300 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1301 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1302 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1303 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1304 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1305 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1306 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1308 /* the lowest index is checked first and remaining events are untouched */
1309 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1310 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1313 /* run same test with Nt* call */
1314 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1315 SetEvent(maxevents
[i
]);
1317 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1318 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1319 ok(status
== STATUS_WAIT_0
, "should signal lowest handle first, got %08x\n", status
);
1320 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1321 ok(status
== STATUS_WAIT_0
, "should signal handle #0 first, got %08x\n", status
);
1322 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1323 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1325 /* the lowest index is checked first and remaining events are untouched */
1326 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1327 ok(status
== STATUS_WAIT_0
+ i
, "should signal handle #%d first, got %08x\n", i
, status
);
1330 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1331 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1333 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1334 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1335 maxevents
[0] = GetCurrentProcess();
1336 SetLastError(0xdeadbeef);
1337 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1338 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1339 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1340 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1342 maxevents
[0] = GetCurrentThread();
1343 SetLastError(0xdeadbeef);
1344 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1345 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1346 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1347 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1349 timeout
.QuadPart
= -1000000;
1350 maxevents
[0] = GetCurrentProcess();
1351 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1352 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1354 timeout
.QuadPart
= -1000000;
1355 maxevents
[0] = GetCurrentThread();
1356 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1357 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1360 static BOOL g_initcallback_ret
, g_initcallback_called
;
1361 static void *g_initctxt
;
1363 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1365 g_initcallback_called
= TRUE
;
1366 /* zero bit set means here that initialization is taking place - initialization locked */
1367 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1368 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1369 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1370 return g_initcallback_ret
;
1373 static void test_initonce(void)
1378 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1380 win_skip("one-time initialization API not supported\n");
1384 /* blocking initialization with callback */
1385 initonce
.Ptr
= (void*)0xdeadbeef;
1386 pInitOnceInitialize(&initonce
);
1387 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1389 /* initialisation completed successfully */
1390 g_initcallback_ret
= TRUE
;
1392 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1393 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1394 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1395 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1396 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1398 /* so it's been called already so won't be called again */
1400 g_initcallback_called
= FALSE
;
1401 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1402 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1403 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1404 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1405 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1407 pInitOnceInitialize(&initonce
);
1408 g_initcallback_called
= FALSE
;
1409 /* 2 lower order bits should never be used, you'll get a crash in result */
1410 g_initctxt
= (void*)0xFFFFFFF0;
1411 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1412 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1413 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1414 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1415 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1417 /* callback failed */
1418 g_initcallback_ret
= FALSE
;
1419 g_initcallback_called
= FALSE
;
1421 pInitOnceInitialize(&initonce
);
1422 SetLastError( 0xdeadbeef );
1423 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1424 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1425 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1426 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1427 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1429 /* blocking initialization without a callback */
1430 pInitOnceInitialize(&initonce
);
1433 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1434 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1435 ok(pending
, "got %d\n", pending
);
1436 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1437 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1438 /* another attempt to begin initialization with block a single thread */
1442 SetLastError( 0xdeadbeef );
1443 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1444 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1445 ok(pending
== 0xf, "got %d\n", pending
);
1446 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1447 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1449 g_initctxt
= (void*)0xdeadbee0;
1450 SetLastError( 0xdeadbeef );
1451 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1452 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1453 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1455 /* once failed already */
1456 g_initctxt
= (void*)0xdeadbee0;
1457 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1458 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1459 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1461 pInitOnceInitialize(&initonce
);
1462 SetLastError( 0xdeadbeef );
1463 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1464 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1465 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1467 SetLastError( 0xdeadbeef );
1468 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1469 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1470 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1472 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1473 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1474 ok(pending
, "got %d\n", pending
);
1475 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1477 SetLastError( 0xdeadbeef );
1478 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1479 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1481 SetLastError( 0xdeadbeef );
1482 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1483 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1484 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1486 SetLastError( 0xdeadbeef );
1487 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1488 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1489 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1491 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1492 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1493 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1495 pInitOnceInitialize(&initonce
);
1496 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1497 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1498 ok(pending
, "got %d\n", pending
);
1499 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1501 SetLastError( 0xdeadbeef );
1502 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1503 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1505 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1506 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1507 ok(pending
, "got %d\n", pending
);
1508 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1510 SetLastError( 0xdeadbeef );
1511 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1512 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1513 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1515 SetLastError( 0xdeadbeef );
1516 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1517 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1518 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1520 SetLastError( 0xdeadbeef );
1521 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1522 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1523 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1525 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1526 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1527 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1529 SetLastError( 0xdeadbeef );
1530 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1531 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1532 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1534 pInitOnceInitialize(&initonce
);
1535 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1536 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1537 ok(pending
, "got %d\n", pending
);
1538 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1540 /* test INIT_ONCE_CHECK_ONLY */
1542 pInitOnceInitialize(&initonce
);
1543 SetLastError( 0xdeadbeef );
1544 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1545 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1546 SetLastError( 0xdeadbeef );
1547 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1548 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1550 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1551 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1552 ok(pending
, "got %d\n", pending
);
1553 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1555 SetLastError( 0xdeadbeef );
1556 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1557 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1558 SetLastError( 0xdeadbeef );
1559 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1560 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1562 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1563 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1564 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1566 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1567 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1568 ok(!pending
, "got %d\n", pending
);
1569 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1570 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1572 SetLastError( 0xdeadbeef );
1573 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1574 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1576 pInitOnceInitialize(&initonce
);
1577 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1578 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1579 ok(pending
, "got %d\n", pending
);
1580 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1582 SetLastError( 0xdeadbeef );
1583 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1584 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1585 SetLastError( 0xdeadbeef );
1586 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1587 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1589 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1590 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1591 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1593 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1594 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1595 ok(!pending
, "got %d\n", pending
);
1596 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1597 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1599 SetLastError( 0xdeadbeef );
1600 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1601 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1604 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1605 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1606 static CRITICAL_SECTION buffercrit
;
1607 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1608 static LONG bufferlen
,totalproduced
,totalconsumed
;
1609 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1611 #define BUFFER_SIZE 5
1613 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1614 DWORD sleepinterval
= 5;
1617 Sleep(sleepinterval
);
1618 if (sleepinterval
> 1)
1621 EnterCriticalSection(&buffercrit
);
1622 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1623 condvar_producer_sleepcnt
++;
1624 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1625 if (GetLastError() != ERROR_TIMEOUT
)
1626 condvar_sleeperr
= TRUE
;
1630 LeaveCriticalSection(&buffercrit
);
1635 LeaveCriticalSection(&buffercrit
);
1636 pWakeConditionVariable(&buffernotempty
);
1641 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1642 DWORD
*cnt
= (DWORD
*)x
;
1643 DWORD sleepinterval
= 1;
1646 EnterCriticalSection(&buffercrit
);
1647 while ((bufferlen
== 0) && !condvar_stop
) {
1648 condvar_consumer_sleepcnt
++;
1649 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1650 if (GetLastError() != ERROR_TIMEOUT
)
1651 condvar_sleeperr
= TRUE
;
1654 if (condvar_stop
&& (bufferlen
== 0)) {
1655 LeaveCriticalSection(&buffercrit
);
1661 LeaveCriticalSection(&buffercrit
);
1662 pWakeConditionVariable(&buffernotfull
);
1663 Sleep(sleepinterval
);
1664 if (sleepinterval
< 5) sleepinterval
+= 1;
1669 static void test_condvars_consumer_producer(void)
1671 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1673 DWORD cnt1
,cnt2
,cnt3
;
1675 if (!pInitializeConditionVariable
) {
1676 /* function is not yet in XP, only in newer Windows */
1677 win_skip("no condition variable support.\n");
1681 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1683 /* If we have static initialized condition variables, InitializeConditionVariable
1684 * is not strictly necessary.
1685 * pInitializeConditionVariable(&buffernotfull);
1687 pInitializeConditionVariable(&buffernotempty
);
1688 InitializeCriticalSection(&buffercrit
);
1690 /* Larger Test: consumer/producer example */
1692 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1694 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1695 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1696 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1697 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1698 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1699 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1701 /* Limit run to 0.5 seconds. */
1704 /* tear down start */
1705 condvar_stop
= TRUE
;
1707 /* final wake up call */
1708 pWakeAllConditionVariable (&buffernotfull
);
1709 pWakeAllConditionVariable (&buffernotempty
);
1711 /* (mostly an implementation detail)
1712 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1715 WaitForSingleObject(hp1
, 1000);
1716 WaitForSingleObject(hp2
, 1000);
1717 WaitForSingleObject(hp3
, 1000);
1718 WaitForSingleObject(hc1
, 1000);
1719 WaitForSingleObject(hc2
, 1000);
1720 WaitForSingleObject(hc3
, 1000);
1722 ok(totalconsumed
== totalproduced
,
1723 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1724 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1726 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1727 * one consumer does not get anything to do is possible. */
1728 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1729 /* The sleeps of the producer or consumer should not go above 100* produced count,
1730 * otherwise the implementation does not sleep correctly. But yet again, this is
1731 * not hard defined. */
1732 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1735 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1736 static DWORD condvar_seq
= 0;
1737 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1738 static CRITICAL_SECTION condvar_crit
;
1739 static SRWLOCK condvar_srwlock
;
1741 /* Sequence of wake/sleep to check boundary conditions:
1743 * 1: producer emits a WakeConditionVariable without consumer waiting.
1744 * 2: consumer sleeps without a wake expecting timeout
1745 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1746 * 4: consumer sleeps without a wake expecting timeout
1747 * 5: a wake is handed to a SleepConditionVariableCS
1748 * 6: a wakeall is handed to a SleepConditionVariableCS
1749 * 7: sleep after above should timeout
1750 * 8: wake with crit section locked into the sleep timeout
1752 * the following tests will only be executed if InitializeSRWLock is available
1754 * 9: producer (exclusive) wakes up consumer (exclusive)
1755 * 10: producer (exclusive) wakes up consumer (shared)
1756 * 11: producer (shared) wakes up consumer (exclusive)
1757 * 12: producer (shared) wakes up consumer (shared)
1760 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1761 while (condvar_seq
< 1) Sleep(1);
1763 pWakeConditionVariable (&condvar_base
);
1766 while (condvar_seq
< 3) Sleep(1);
1767 pWakeAllConditionVariable (&condvar_base
);
1770 while (condvar_seq
< 5) Sleep(1);
1771 EnterCriticalSection (&condvar_crit
);
1772 pWakeConditionVariable (&condvar_base
);
1773 LeaveCriticalSection (&condvar_crit
);
1774 while (condvar_seq
< 6) Sleep(1);
1775 EnterCriticalSection (&condvar_crit
);
1776 pWakeAllConditionVariable (&condvar_base
);
1777 LeaveCriticalSection (&condvar_crit
);
1779 while (condvar_seq
< 8) Sleep(1);
1780 EnterCriticalSection (&condvar_crit
);
1781 pWakeConditionVariable (&condvar_base
);
1783 LeaveCriticalSection (&condvar_crit
);
1785 /* skip over remaining tests if InitializeSRWLock is not available */
1786 if (!pInitializeSRWLock
)
1789 while (condvar_seq
< 9) Sleep(1);
1790 pAcquireSRWLockExclusive(&condvar_srwlock
);
1791 pWakeConditionVariable(&condvar_base
);
1792 pReleaseSRWLockExclusive(&condvar_srwlock
);
1794 while (condvar_seq
< 10) Sleep(1);
1795 pAcquireSRWLockExclusive(&condvar_srwlock
);
1796 pWakeConditionVariable(&condvar_base
);
1797 pReleaseSRWLockExclusive(&condvar_srwlock
);
1799 while (condvar_seq
< 11) Sleep(1);
1800 pAcquireSRWLockShared(&condvar_srwlock
);
1801 pWakeConditionVariable(&condvar_base
);
1802 pReleaseSRWLockShared(&condvar_srwlock
);
1804 while (condvar_seq
< 12) Sleep(1);
1805 Sleep(50); /* ensure that consumer waits for cond variable */
1806 pAcquireSRWLockShared(&condvar_srwlock
);
1807 pWakeConditionVariable(&condvar_base
);
1808 pReleaseSRWLockShared(&condvar_srwlock
);
1813 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1816 while (condvar_seq
< 2) Sleep(1);
1818 /* wake was emitted, but we were not sleeping */
1819 EnterCriticalSection (&condvar_crit
);
1820 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1821 LeaveCriticalSection (&condvar_crit
);
1822 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1823 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1826 while (condvar_seq
< 4) Sleep(1);
1828 /* wake all was emitted, but we were not sleeping */
1829 EnterCriticalSection (&condvar_crit
);
1830 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1831 LeaveCriticalSection (&condvar_crit
);
1832 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1833 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1835 EnterCriticalSection (&condvar_crit
);
1837 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1838 LeaveCriticalSection (&condvar_crit
);
1839 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1841 EnterCriticalSection (&condvar_crit
);
1843 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1844 LeaveCriticalSection (&condvar_crit
);
1845 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1848 EnterCriticalSection (&condvar_crit
);
1849 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1850 LeaveCriticalSection (&condvar_crit
);
1851 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1852 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1854 EnterCriticalSection (&condvar_crit
);
1856 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1857 LeaveCriticalSection (&condvar_crit
);
1858 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1860 /* skip over remaining tests if InitializeSRWLock is not available */
1861 if (!pInitializeSRWLock
)
1863 win_skip("no srw lock support.\n");
1864 condvar_seq
= 13; /* end */
1868 pAcquireSRWLockExclusive(&condvar_srwlock
);
1870 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1871 pReleaseSRWLockExclusive(&condvar_srwlock
);
1872 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1874 pAcquireSRWLockShared(&condvar_srwlock
);
1876 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1877 pReleaseSRWLockShared(&condvar_srwlock
);
1878 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1880 pAcquireSRWLockExclusive(&condvar_srwlock
);
1882 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1883 pReleaseSRWLockExclusive(&condvar_srwlock
);
1884 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1886 pAcquireSRWLockShared(&condvar_srwlock
);
1888 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1889 pReleaseSRWLockShared(&condvar_srwlock
);
1890 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1896 static void test_condvars_base(void) {
1902 if (!pInitializeConditionVariable
) {
1903 /* function is not yet in XP, only in newer Windows */
1904 win_skip("no condition variable support.\n");
1908 InitializeCriticalSection (&condvar_crit
);
1910 if (pInitializeSRWLock
)
1911 pInitializeSRWLock(&condvar_srwlock
);
1913 EnterCriticalSection (&condvar_crit
);
1914 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1915 LeaveCriticalSection (&condvar_crit
);
1917 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1918 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1920 if (pInitializeSRWLock
)
1922 pAcquireSRWLockExclusive(&condvar_srwlock
);
1923 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1924 pReleaseSRWLockExclusive(&condvar_srwlock
);
1926 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1927 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1929 pAcquireSRWLockShared(&condvar_srwlock
);
1930 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1931 pReleaseSRWLockShared(&condvar_srwlock
);
1933 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1934 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1938 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1939 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1941 condvar_seq
= 1; /* go */
1943 while (condvar_seq
< 9)
1945 WaitForSingleObject(hp
, 100);
1946 WaitForSingleObject(hc
, 100);
1949 static LONG srwlock_seq
= 0;
1950 static SRWLOCK srwlock_base
;
1953 LONG wrong_execution_order
;
1954 LONG samethread_excl_excl
;
1955 LONG samethread_excl_shared
;
1956 LONG samethread_shared_excl
;
1957 LONG multithread_excl_excl
;
1958 LONG excl_not_preferred
;
1960 LONG trylock_shared
;
1961 } srwlock_base_errors
;
1963 /* Sequence of acquire/release to check boundary conditions:
1966 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1967 * 2: thread1 expects a deadlock and releases the waiting lock
1968 * thread2 releases the lock again
1970 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1971 * 4: thread1 expects a deadlock and releases the waiting lock
1972 * thread2 releases the lock again
1974 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1975 * 6: thread1 expects a deadlock and releases the waiting lock
1976 * thread2 releases the lock again
1978 * 7: thread2 acquires and releases two nested shared locks
1980 * 8: thread1 acquires an exclusive lock
1981 * 9: thread2 tries to acquire the exclusive lock, too
1982 * thread1 releases the exclusive lock again
1983 * 10: thread2 enters the exclusive lock and leaves it immediately again
1985 * 11: thread1 acquires a shared lock
1986 * 12: thread2 acquires and releases a shared lock
1987 * thread1 releases the lock again
1989 * 13: thread1 acquires a shared lock
1990 * 14: thread2 tries to acquire an exclusive lock
1991 * 15: thread3 tries to acquire a shared lock
1992 * 16: thread1 releases the shared lock
1993 * 17: thread2 wakes up and releases the exclusive lock
1994 * 18: thread3 wakes up and releases the shared lock
1996 * the following tests will only be executed if TryAcquireSRWLock* is available
1998 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1999 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2000 * thread1 releases the exclusive lock
2002 * thread1 calls TryAcquireSRWLockShared which should return TRUE
2003 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2004 * thread1 releases the shared lock
2006 * thread1 acquires an exclusive lock
2007 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
2008 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2009 * 21: thread1 releases the exclusive lock
2011 * thread1 acquires an shared lock
2012 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2013 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2014 * 23: thread1 releases the shared lock
2016 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2017 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2018 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2019 * 25: thread1 releases the exclusive lock
2021 * thread1 acquires two shared locks
2022 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2023 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2024 * 27: thread1 releases one shared lock
2025 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2026 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2027 * 29: thread1 releases the second shared lock
2028 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2029 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2034 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
2037 while (srwlock_seq
< 2) Sleep(1);
2039 if (InterlockedIncrement(&srwlock_seq
) != 3)
2040 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2041 pReleaseSRWLockExclusive(&srwlock_base
);
2044 while (srwlock_seq
< 4) Sleep(1);
2046 if (InterlockedIncrement(&srwlock_seq
) != 5)
2047 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2048 pReleaseSRWLockExclusive(&srwlock_base
);
2051 while (srwlock_seq
< 6) Sleep(1);
2053 if (InterlockedIncrement(&srwlock_seq
) != 7)
2054 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2055 pReleaseSRWLockShared(&srwlock_base
);
2058 while (srwlock_seq
< 8) Sleep(1);
2059 pAcquireSRWLockExclusive(&srwlock_base
);
2060 if (InterlockedIncrement(&srwlock_seq
) != 9)
2061 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2063 if (InterlockedIncrement(&srwlock_seq
) != 10)
2064 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2065 pReleaseSRWLockExclusive(&srwlock_base
);
2068 while (srwlock_seq
< 11) Sleep(1);
2069 pAcquireSRWLockShared(&srwlock_base
);
2070 if (InterlockedIncrement(&srwlock_seq
) != 12)
2071 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2074 while (srwlock_seq
< 13) Sleep(1);
2075 pReleaseSRWLockShared(&srwlock_base
);
2076 pAcquireSRWLockShared(&srwlock_base
);
2077 if (InterlockedIncrement(&srwlock_seq
) != 14)
2078 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2081 while (srwlock_seq
< 16) Sleep(1);
2082 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2083 if (InterlockedIncrement(&srwlock_seq
) != 17)
2084 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2085 pReleaseSRWLockShared(&srwlock_base
);
2087 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2088 if (!pTryAcquireSRWLockExclusive
)
2092 while (srwlock_seq
< 19) Sleep(1);
2093 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2095 if (pTryAcquireSRWLockShared(&srwlock_base
))
2096 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2097 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2098 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2099 pReleaseSRWLockExclusive(&srwlock_base
);
2102 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2104 if (pTryAcquireSRWLockShared(&srwlock_base
))
2106 if (pTryAcquireSRWLockShared(&srwlock_base
))
2107 pReleaseSRWLockShared(&srwlock_base
);
2109 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2110 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2111 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2112 pReleaseSRWLockShared(&srwlock_base
);
2115 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2117 pAcquireSRWLockExclusive(&srwlock_base
);
2118 if (InterlockedIncrement(&srwlock_seq
) != 20)
2119 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2122 while (srwlock_seq
< 21) Sleep(1);
2123 pReleaseSRWLockExclusive(&srwlock_base
);
2124 pAcquireSRWLockShared(&srwlock_base
);
2125 if (InterlockedIncrement(&srwlock_seq
) != 22)
2126 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2129 while (srwlock_seq
< 23) Sleep(1);
2130 pReleaseSRWLockShared(&srwlock_base
);
2131 pAcquireSRWLockShared(&srwlock_base
);
2132 if (InterlockedIncrement(&srwlock_seq
) != 24)
2133 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2136 pAcquireSRWLockExclusive(&srwlock_base
);
2137 if (srwlock_seq
!= 25)
2138 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2139 pReleaseSRWLockExclusive(&srwlock_base
);
2141 pAcquireSRWLockShared(&srwlock_base
);
2142 pAcquireSRWLockShared(&srwlock_base
);
2143 if (InterlockedIncrement(&srwlock_seq
) != 26)
2144 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2147 while (srwlock_seq
< 27) Sleep(1);
2148 pReleaseSRWLockShared(&srwlock_base
);
2149 if (InterlockedIncrement(&srwlock_seq
) != 28)
2150 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2153 while (srwlock_seq
< 29) Sleep(1);
2154 pReleaseSRWLockShared(&srwlock_base
);
2155 if (InterlockedIncrement(&srwlock_seq
) != 30)
2156 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2161 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
2164 while (srwlock_seq
< 1) Sleep(1);
2165 pAcquireSRWLockExclusive(&srwlock_base
);
2166 if (InterlockedIncrement(&srwlock_seq
) != 2)
2167 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2170 pAcquireSRWLockExclusive(&srwlock_base
);
2171 if (srwlock_seq
!= 3)
2172 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2173 pReleaseSRWLockExclusive(&srwlock_base
);
2174 pAcquireSRWLockExclusive(&srwlock_base
);
2175 if (InterlockedIncrement(&srwlock_seq
) != 4)
2176 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2179 pAcquireSRWLockShared(&srwlock_base
);
2180 if (srwlock_seq
!= 5)
2181 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2182 pReleaseSRWLockShared(&srwlock_base
);
2183 pAcquireSRWLockShared(&srwlock_base
);
2184 if (InterlockedIncrement(&srwlock_seq
) != 6)
2185 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2188 pAcquireSRWLockExclusive(&srwlock_base
);
2189 if (srwlock_seq
!= 7)
2190 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2191 pReleaseSRWLockExclusive(&srwlock_base
);
2192 pAcquireSRWLockShared(&srwlock_base
);
2193 pAcquireSRWLockShared(&srwlock_base
);
2194 pReleaseSRWLockShared(&srwlock_base
);
2195 pReleaseSRWLockShared(&srwlock_base
);
2196 if (InterlockedIncrement(&srwlock_seq
) != 8)
2197 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2200 while (srwlock_seq
< 9) Sleep(1);
2201 pAcquireSRWLockExclusive(&srwlock_base
);
2202 if (srwlock_seq
!= 10)
2203 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2204 pReleaseSRWLockExclusive(&srwlock_base
);
2205 if (InterlockedIncrement(&srwlock_seq
) != 11)
2206 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2209 while (srwlock_seq
< 12) Sleep(1);
2210 pAcquireSRWLockShared(&srwlock_base
);
2211 pReleaseSRWLockShared(&srwlock_base
);
2212 if (InterlockedIncrement(&srwlock_seq
) != 13)
2213 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2216 while (srwlock_seq
< 14) Sleep(1);
2217 if (InterlockedIncrement(&srwlock_seq
) != 15)
2218 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2221 pAcquireSRWLockExclusive(&srwlock_base
);
2222 if (srwlock_seq
!= 17)
2223 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2224 if (InterlockedIncrement(&srwlock_seq
) != 18)
2225 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2226 pReleaseSRWLockExclusive(&srwlock_base
);
2228 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2229 if (!pTryAcquireSRWLockExclusive
)
2233 while (srwlock_seq
< 20) Sleep(1);
2234 if (pTryAcquireSRWLockShared(&srwlock_base
))
2235 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2236 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2237 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2238 if (InterlockedIncrement(&srwlock_seq
) != 21)
2239 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2242 while (srwlock_seq
< 22) Sleep(1);
2243 if (pTryAcquireSRWLockShared(&srwlock_base
))
2244 pReleaseSRWLockShared(&srwlock_base
);
2246 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2247 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2248 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2249 if (InterlockedIncrement(&srwlock_seq
) != 23)
2250 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2253 while (srwlock_seq
< 24) Sleep(1);
2254 Sleep(50); /* ensure that exclusive access request is queued */
2255 if (pTryAcquireSRWLockShared(&srwlock_base
))
2257 pReleaseSRWLockShared(&srwlock_base
);
2258 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2260 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2261 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2262 if (InterlockedIncrement(&srwlock_seq
) != 25)
2263 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2264 pReleaseSRWLockShared(&srwlock_base
);
2267 while (srwlock_seq
< 26) Sleep(1);
2268 if (pTryAcquireSRWLockShared(&srwlock_base
))
2269 pReleaseSRWLockShared(&srwlock_base
);
2271 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2272 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2273 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2274 if (InterlockedIncrement(&srwlock_seq
) != 27)
2275 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2278 while (srwlock_seq
< 28) Sleep(1);
2279 if (pTryAcquireSRWLockShared(&srwlock_base
))
2280 pReleaseSRWLockShared(&srwlock_base
);
2282 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2283 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2284 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2285 if (InterlockedIncrement(&srwlock_seq
) != 29)
2286 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2289 while (srwlock_seq
< 30) Sleep(1);
2290 if (pTryAcquireSRWLockShared(&srwlock_base
))
2291 pReleaseSRWLockShared(&srwlock_base
);
2293 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2294 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2295 pReleaseSRWLockExclusive(&srwlock_base
);
2297 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2298 if (InterlockedIncrement(&srwlock_seq
) != 31)
2299 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2304 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2307 while (srwlock_seq
< 15) Sleep(1);
2308 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2309 if (InterlockedIncrement(&srwlock_seq
) != 16)
2310 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2313 pAcquireSRWLockShared(&srwlock_base
);
2314 if (srwlock_seq
!= 18)
2315 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2316 pReleaseSRWLockShared(&srwlock_base
);
2317 if (InterlockedIncrement(&srwlock_seq
) != 19)
2318 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2320 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2321 if (!pTryAcquireSRWLockExclusive
)
2323 /* function is only in Windows 7 and newer */
2324 win_skip("no srw trylock support.\n");
2325 srwlock_seq
= 31; /* end */
2332 static void test_srwlock_base(void)
2337 if (!pInitializeSRWLock
)
2339 /* function is not yet in XP, only in newer Windows */
2340 win_skip("no srw lock support.\n");
2344 pInitializeSRWLock(&srwlock_base
);
2345 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2347 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2348 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2349 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2351 srwlock_seq
= 1; /* go */
2352 while (srwlock_seq
< 31)
2355 WaitForSingleObject(h1
, 100);
2356 WaitForSingleObject(h2
, 100);
2357 WaitForSingleObject(h3
, 100);
2359 ok(!srwlock_base_errors
.wrong_execution_order
,
2360 "thread commands were executed in the wrong order (occurred %d times).\n",
2361 srwlock_base_errors
.wrong_execution_order
);
2363 ok(!srwlock_base_errors
.samethread_excl_excl
,
2364 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2365 srwlock_base_errors
.samethread_excl_excl
);
2367 ok(!srwlock_base_errors
.samethread_excl_shared
,
2368 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2369 srwlock_base_errors
.samethread_excl_shared
);
2371 ok(!srwlock_base_errors
.samethread_shared_excl
,
2372 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2373 srwlock_base_errors
.samethread_shared_excl
);
2375 ok(!srwlock_base_errors
.multithread_excl_excl
,
2376 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2377 srwlock_base_errors
.multithread_excl_excl
);
2379 ok(!srwlock_base_errors
.excl_not_preferred
,
2380 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2381 srwlock_base_errors
.excl_not_preferred
);
2383 ok(!srwlock_base_errors
.trylock_excl
,
2384 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2385 srwlock_base_errors
.trylock_excl
);
2387 ok(!srwlock_base_errors
.trylock_shared
,
2388 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2389 srwlock_base_errors
.trylock_shared
);
2393 static SRWLOCK srwlock_example
;
2394 static LONG srwlock_protected_value
= 0;
2395 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2396 static BOOL srwlock_stop
= FALSE
;
2398 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2402 while (!srwlock_stop
)
2405 /* periodically request exclusive access */
2406 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2408 pAcquireSRWLockExclusive(&srwlock_example
);
2409 if (InterlockedIncrement(&srwlock_inside
) != 1)
2410 InterlockedIncrement(&srwlock_example_errors
);
2412 InterlockedIncrement(&srwlock_protected_value
);
2415 if (InterlockedDecrement(&srwlock_inside
) != 0)
2416 InterlockedIncrement(&srwlock_example_errors
);
2417 pReleaseSRWLockExclusive(&srwlock_example
);
2420 /* request shared access */
2421 pAcquireSRWLockShared(&srwlock_example
);
2422 InterlockedIncrement(&srwlock_inside
);
2423 old
= srwlock_protected_value
;
2428 if (old
!= srwlock_protected_value
)
2429 InterlockedIncrement(&srwlock_example_errors
);
2430 InterlockedDecrement(&srwlock_inside
);
2431 pReleaseSRWLockShared(&srwlock_example
);
2437 static void test_srwlock_example(void)
2441 DWORD cnt1
, cnt2
, cnt3
;
2443 if (!pInitializeSRWLock
) {
2444 /* function is not yet in XP, only in newer Windows */
2445 win_skip("no srw lock support.\n");
2449 pInitializeSRWLock(&srwlock_example
);
2451 cnt1
= cnt2
= cnt3
= 0;
2453 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2454 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2455 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2457 /* limit run to 1 second. */
2460 /* tear down start */
2461 srwlock_stop
= TRUE
;
2463 WaitForSingleObject(h1
, 1000);
2464 WaitForSingleObject(h2
, 1000);
2465 WaitForSingleObject(h3
, 1000);
2467 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2468 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2469 srwlock_example_errors
);
2471 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2472 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2475 static DWORD WINAPI
alertable_wait_thread(void *param
)
2477 HANDLE
*semaphores
= param
;
2478 LARGE_INTEGER timeout
;
2482 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2483 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 1000, TRUE
);
2484 ok(result
== WAIT_IO_COMPLETION
, "expected WAIT_IO_COMPLETION, got %u\n", result
);
2485 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 200, TRUE
);
2486 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
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 timeout
.QuadPart
= -2000000;
2493 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2494 ok(status
== STATUS_WAIT_0
, "expected STATUS_WAIT_0, got %08x\n", status
);
2496 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2497 timeout
.QuadPart
= -10000000;
2498 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2499 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2500 result
= WaitForSingleObject(semaphores
[0], 0);
2501 ok(result
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", result
);
2506 static void CALLBACK
alertable_wait_apc(ULONG_PTR userdata
)
2508 HANDLE
*semaphores
= (void *)userdata
;
2509 ReleaseSemaphore(semaphores
[1], 1, NULL
);
2512 static void CALLBACK
alertable_wait_apc2(ULONG_PTR userdata
)
2514 HANDLE
*semaphores
= (void *)userdata
;
2517 result
= WaitForSingleObject(semaphores
[0], 1000);
2518 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2521 static void test_alertable_wait(void)
2523 HANDLE thread
, semaphores
[2];
2526 semaphores
[0] = CreateSemaphoreW(NULL
, 0, 2, NULL
);
2527 ok(semaphores
[0] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2528 semaphores
[1] = CreateSemaphoreW(NULL
, 0, 1, NULL
);
2529 ok(semaphores
[1] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2530 thread
= CreateThread(NULL
, 0, alertable_wait_thread
, semaphores
, 0, NULL
);
2531 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2533 result
= WaitForSingleObject(semaphores
[0], 1000);
2534 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2535 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2536 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2537 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2539 result
= WaitForSingleObject(semaphores
[0], 1000);
2540 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2541 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2542 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2543 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2545 result
= WaitForSingleObject(semaphores
[0], 1000);
2546 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2547 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2548 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2549 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2550 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2551 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2552 ReleaseSemaphore(semaphores
[0], 2, NULL
);
2554 result
= WaitForSingleObject(thread
, 1000);
2555 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2556 CloseHandle(thread
);
2557 CloseHandle(semaphores
[0]);
2558 CloseHandle(semaphores
[1]);
2561 struct apc_deadlock_info
2563 PROCESS_INFORMATION
*pi
;
2568 static DWORD WINAPI
apc_deadlock_thread(void *param
)
2570 struct apc_deadlock_info
*info
= param
;
2571 PROCESS_INFORMATION
*pi
= info
->pi
;
2576 while (info
->running
)
2580 status
= pNtAllocateVirtualMemory(pi
->hProcess
, &base
, 0, &size
,
2581 MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2582 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2583 ok(base
!= NULL
, "expected base != NULL, got %p\n", base
);
2584 SetEvent(info
->event
);
2587 status
= pNtFreeVirtualMemory(pi
->hProcess
, &base
, &size
, MEM_RELEASE
);
2588 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2589 SetEvent(info
->event
);
2595 static void test_apc_deadlock(void)
2597 struct apc_deadlock_info info
;
2598 PROCESS_INFORMATION pi
;
2599 STARTUPINFOA si
= { sizeof(si
) };
2600 char cmdline
[MAX_PATH
];
2601 HANDLE event
, thread
;
2607 winetest_get_mainargs(&argv
);
2608 sprintf(cmdline
, "\"%s\" sync apc_deadlock", argv
[0]);
2609 success
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2610 ok(success
, "CreateProcess failed with %u\n", GetLastError());
2612 event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2613 ok(event
!= NULL
, "CreateEvent failed with %u\n", GetLastError());
2617 info
.running
= TRUE
;
2619 thread
= CreateThread(NULL
, 0, apc_deadlock_thread
, &info
, 0, NULL
);
2620 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2621 result
= WaitForSingleObject(event
, 1000);
2622 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2624 for (i
= 0; i
< 1000; i
++)
2626 result
= SuspendThread(pi
.hThread
);
2627 ok(result
== 0, "expected 0, got %u\n", result
);
2629 WaitForSingleObject(event
, 0); /* reset event */
2630 result
= WaitForSingleObject(event
, 1000);
2631 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2633 result
= ResumeThread(pi
.hThread
);
2634 ok(result
== 1, "expected 1, got %u\n", result
);
2638 info
.running
= FALSE
;
2639 result
= WaitForSingleObject(thread
, 1000);
2640 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2641 CloseHandle(thread
);
2644 TerminateProcess(pi
.hProcess
, 0);
2645 CloseHandle(pi
.hThread
);
2646 CloseHandle(pi
.hProcess
);
2653 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2654 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2656 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
2657 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
2658 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
2659 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
2660 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
2661 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
2662 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
2663 pCreateMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "CreateMemoryResourceNotification");
2664 pQueryMemoryResourceNotification
= (void *)GetProcAddress(hdll
, "QueryMemoryResourceNotification");
2665 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2666 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2667 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2668 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2669 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2670 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2671 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2672 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2673 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2674 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2675 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2676 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2677 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2678 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2679 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2680 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2681 pNtAllocateVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtAllocateVirtualMemory");
2682 pNtFreeVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtFreeVirtualMemory");
2683 pNtWaitForSingleObject
= (void *)GetProcAddress(hntdll
, "NtWaitForSingleObject");
2684 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2685 pRtlInterlockedPushListSList
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSList");
2686 pRtlInterlockedPushListSListEx
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSListEx");
2688 argc
= winetest_get_mainargs( &argv
);
2691 if (!strcmp(argv
[2], "apc_deadlock"))
2693 for (;;) SleepEx(INFINITE
, TRUE
);
2698 init_fastcall_thunk();
2699 test_signalandwait();
2704 test_waitable_timer();
2705 test_iocp_callback();
2707 test_WaitForSingleObject();
2708 test_WaitForMultipleObjects();
2710 test_condvars_base();
2711 test_condvars_consumer_producer();
2712 test_srwlock_base();
2713 test_srwlock_example();
2714 test_alertable_wait();
2715 test_apc_deadlock();