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
29 #include "wine/test.h"
32 #define __fastcall __stdcall
34 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
35 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
36 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
37 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
38 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
39 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
41 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
42 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
43 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
44 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
45 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
47 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
48 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
49 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
50 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
51 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
52 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
53 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
55 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG
, SIZE_T
*, ULONG
, ULONG
);
56 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
57 static NTSTATUS (WINAPI
*pNtWaitForSingleObject
)(HANDLE
, BOOLEAN
, const LARGE_INTEGER
*);
58 static NTSTATUS (WINAPI
*pNtWaitForMultipleObjects
)(ULONG
,const HANDLE
*,BOOLEAN
,BOOLEAN
,const LARGE_INTEGER
*);
59 static PSLIST_ENTRY (__fastcall
*pRtlInterlockedPushListSList
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
60 PSLIST_ENTRY last
, ULONG count
);
61 static PSLIST_ENTRY (WINAPI
*pRtlInterlockedPushListSListEx
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
62 PSLIST_ENTRY last
, ULONG count
);
69 BYTE pop_edx
; /* popl %edx (ret addr) */
70 BYTE pop_eax
; /* popl %eax (func) */
71 BYTE pop_ecx
; /* popl %ecx (param 1) */
72 BYTE xchg
[3]; /* xchgl (%esp),%edx (param 2) */
73 WORD jmp_eax
; /* jmp *%eax */
77 static void * (WINAPI
*call_fastcall_func4
)(void *func
, const void *a
, const void *b
, const void *c
, const void *d
);
79 static void init_fastcall_thunk(void)
81 struct fastcall_thunk
*thunk
= VirtualAlloc(NULL
, sizeof(*thunk
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
82 thunk
->pop_edx
= 0x5a; /* popl %edx */
83 thunk
->pop_eax
= 0x58; /* popl %eax */
84 thunk
->pop_ecx
= 0x59; /* popl %ecx */
85 thunk
->xchg
[0] = 0x87; /* xchgl (%esp),%edx */
86 thunk
->xchg
[1] = 0x14;
87 thunk
->xchg
[2] = 0x24;
88 thunk
->jmp_eax
= 0xe0ff; /* jmp *%eax */
89 call_fastcall_func4
= (void *)thunk
;
92 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
93 (const void *)(b), (const void *)(c), (const void *)(d))
97 #define init_fastcall_thunk() do { } while(0)
98 #define call_func4(func, a, b, c, d) func(a, b, c, d)
100 #endif /* __i386__ */
102 static void test_signalandwait(void)
105 HANDLE event
[2], semaphore
[2], file
;
108 /* invalid parameters */
109 r
= SignalObjectAndWait(NULL
, NULL
, 0, 0);
110 ok( r
== WAIT_FAILED
, "should fail\n");
112 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
113 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
115 ok( event
[0] && event
[1], "failed to create event flags\n");
117 r
= SignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
118 ok( r
== WAIT_FAILED
, "should fail\n");
120 r
= SignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
121 ok( r
== WAIT_FAILED
, "should fail\n");
124 /* valid parameters */
125 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
126 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
128 /* event[0] is now signalled - we repeat this test multiple times
129 * to ensure that the wineserver handles this situation properly. */
130 for (i
= 0; i
< 10000; i
++)
132 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
133 ok(r
== WAIT_OBJECT_0
, "should succeed\n");
136 /* event[0] is not signalled */
137 r
= WaitForSingleObject(event
[0], 0);
138 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
140 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
141 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
143 /* clear event[1] and check for a timeout */
144 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
145 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
146 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
148 CloseHandle(event
[0]);
149 CloseHandle(event
[1]);
152 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
153 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
154 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
156 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
157 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
159 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
160 ok( r
== WAIT_FAILED
, "should fail\n");
162 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
163 ok( r
== FALSE
, "should fail\n");
165 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
166 ok( r
== TRUE
, "should succeed\n");
168 CloseHandle(semaphore
[0]);
169 CloseHandle(semaphore
[1]);
171 /* try a registry key */
172 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
173 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
174 r
= SignalObjectAndWait(file
, file
, 0, FALSE
);
175 ok( r
== WAIT_FAILED
, "should fail\n");
176 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
180 static void test_mutex(void)
189 SetLastError(0xdeadbeef);
190 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
191 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
192 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
194 SetLastError(0xdeadbeef);
195 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
196 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
198 SetLastError(0xdeadbeef);
199 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
201 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
203 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
205 SetLastError(0xdeadbeef);
206 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
207 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
208 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
209 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
210 CloseHandle(hOpened
);
212 for(i
=0; i
< 31; i
++)
214 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
215 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
218 SetLastError(0xdeadbeef);
219 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
220 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
221 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
222 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
223 CloseHandle(hOpened
);
225 for (i
= 0; i
< 32; i
++)
227 SetLastError(0xdeadbeef);
228 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
231 SetLastError(0xdeadbeef);
232 ret
= ReleaseMutex(hOpened
);
233 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
234 CloseHandle(hOpened
);
238 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
239 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
241 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
242 ReleaseMutex(hCreated
);
248 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
250 SetLastError(0xdeadbeef);
251 ret
= ReleaseMutex(hCreated
);
252 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
253 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
255 /* test case sensitivity */
257 SetLastError(0xdeadbeef);
258 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
259 ok(!hOpened
, "OpenMutex succeeded\n");
260 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
262 SetLastError(0xdeadbeef);
263 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
264 ok(!hOpened
, "OpenMutex succeeded\n");
265 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
267 SetLastError(0xdeadbeef);
268 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, NULL
);
269 ok(!hOpened
, "OpenMutex succeeded\n");
270 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
272 SetLastError(0xdeadbeef);
273 hOpened
= OpenMutexW(READ_CONTROL
, FALSE
, NULL
);
274 ok(!hOpened
, "OpenMutex succeeded\n");
275 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
277 SetLastError(0xdeadbeef);
278 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
279 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
280 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
281 CloseHandle(hOpened
);
283 SetLastError(0xdeadbeef);
284 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
285 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
286 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
287 CloseHandle(hOpened
);
289 CloseHandle(hCreated
);
292 static void test_slist(void)
298 } item1
, item2
, item3
, *item
;
299 SLIST_HEADER slist_header
;
308 memset(&slist_header
, 0xff, sizeof(slist_header
));
309 InitializeSListHead(&slist_header
);
310 size
= QueryDepthSList(&slist_header
);
311 ok(size
== 0, "Expected size == 0, got %u\n", size
);
313 /* test PushEntry, PopEntry and Flush */
314 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
315 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
316 size
= QueryDepthSList(&slist_header
);
317 ok(size
== 1, "Expected size == 1, got %u\n", size
);
319 entry
= InterlockedPushEntrySList(&slist_header
, &item2
.entry
);
320 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
321 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
322 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
323 size
= QueryDepthSList(&slist_header
);
324 ok(size
== 2, "Expected size == 2, got %u\n", size
);
326 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
327 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
328 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
329 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
330 size
= QueryDepthSList(&slist_header
);
331 ok(size
== 3, "Expected size == 3, got %u\n", size
);
333 entry
= InterlockedPopEntrySList(&slist_header
);
334 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
335 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
336 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
337 size
= QueryDepthSList(&slist_header
);
338 ok(size
== 2, "Expected size == 2, got %u\n", size
);
340 entry
= InterlockedFlushSList(&slist_header
);
341 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
342 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
343 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
344 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
345 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
346 size
= QueryDepthSList(&slist_header
);
347 ok(size
== 0, "Expected size == 0, got %u\n", size
);
348 entry
= InterlockedPopEntrySList(&slist_header
);
349 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
351 /* test RtlInterlockedPushListSList */
352 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
353 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
354 entry
= call_func4(pRtlInterlockedPushListSList
, &slist_header
, &item2
.entry
, &item1
.entry
, 42);
355 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
356 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
357 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
358 size
= QueryDepthSList(&slist_header
);
359 ok(size
== 43, "Expected size == 43, got %u\n", size
);
361 entry
= InterlockedPopEntrySList(&slist_header
);
362 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
363 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
364 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
365 size
= QueryDepthSList(&slist_header
);
366 ok(size
== 42, "Expected size == 42, got %u\n", size
);
368 entry
= InterlockedPopEntrySList(&slist_header
);
369 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
370 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
371 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
372 size
= QueryDepthSList(&slist_header
);
373 ok(size
== 41, "Expected size == 41, got %u\n", size
);
375 entry
= InterlockedPopEntrySList(&slist_header
);
376 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
377 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
378 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
379 size
= QueryDepthSList(&slist_header
);
380 ok(size
== 40, "Expected size == 40, got %u\n", size
);
382 entry
= InterlockedPopEntrySList(&slist_header
);
383 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
384 size
= QueryDepthSList(&slist_header
);
385 ok(size
== 40, "Expected size == 40, got %u\n", size
);
387 entry
= InterlockedFlushSList(&slist_header
);
388 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
389 size
= QueryDepthSList(&slist_header
);
390 ok(size
== 40 || broken(size
== 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size
);
392 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
393 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
394 entry
= InterlockedFlushSList(&slist_header
);
395 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
396 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
397 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
398 size
= QueryDepthSList(&slist_header
);
399 ok(size
== 0, "Expected size == 0, got %u\n", size
);
401 /* test RtlInterlockedPushListSListEx */
402 if (pRtlInterlockedPushListSListEx
)
404 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
405 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
406 entry
= pRtlInterlockedPushListSListEx(&slist_header
, &item2
.entry
, &item1
.entry
, 42);
407 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
408 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
409 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
410 size
= QueryDepthSList(&slist_header
);
411 ok(size
== 43, "Expected size == 43, got %u\n", size
);
413 entry
= InterlockedFlushSList(&slist_header
);
414 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
415 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
416 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
417 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
418 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
419 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
420 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
421 size
= QueryDepthSList(&slist_header
);
422 ok(size
== 0, "Expected size == 0, got %u\n", size
);
425 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
427 /* test with a lot of items */
428 for (i
= 0; i
< 65536; i
++)
430 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
432 entry
= InterlockedPushEntrySList(&slist_header
, &item
->entry
);
435 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
436 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
437 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
441 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
443 size
= QueryDepthSList(&slist_header
);
444 ok(size
== ((i
+ 1) & 0xffff), "Expected size == %u, got %u\n", (i
+ 1) & 0xffff, size
);
447 entry
= InterlockedFlushSList(&slist_header
);
448 for (i
= 65536; i
> 0; i
--)
450 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
451 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
452 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
453 entry
= item
->entry
.Next
;
454 HeapFree(GetProcessHeap(), 0, item
);
456 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
457 size
= QueryDepthSList(&slist_header
);
458 ok(size
== 0, "Expected size == 0, got %u\n", size
);
459 entry
= InterlockedPopEntrySList(&slist_header
);
460 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
463 static void test_event(void)
465 HANDLE handle
, handle2
;
466 SECURITY_ATTRIBUTES sa
;
467 SECURITY_DESCRIPTOR sd
;
473 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
474 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
477 sa
.nLength
= sizeof(sa
);
478 sa
.lpSecurityDescriptor
= &sd
;
479 sa
.bInheritHandle
= FALSE
;
481 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
484 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
485 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
488 /* sd with NULL dacl */
489 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
490 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
491 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
494 /* sd with empty dacl */
495 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
496 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
497 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
498 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
501 /* test case sensitivity */
503 SetLastError(0xdeadbeef);
504 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
505 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
506 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
508 SetLastError(0xdeadbeef);
509 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
510 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
511 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
512 CloseHandle( handle2
);
514 SetLastError(0xdeadbeef);
515 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
516 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
517 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
518 CloseHandle( handle2
);
520 SetLastError(0xdeadbeef);
521 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
522 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
523 CloseHandle( handle2
);
525 SetLastError(0xdeadbeef);
526 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
527 ok( !handle2
, "OpenEvent succeeded\n");
528 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
530 SetLastError(0xdeadbeef);
531 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, NULL
);
532 ok( !handle2
, "OpenEvent succeeded\n");
533 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
535 SetLastError(0xdeadbeef);
536 handle2
= OpenEventW( EVENT_ALL_ACCESS
, FALSE
, NULL
);
537 ok( !handle2
, "OpenEvent succeeded\n");
538 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
540 CloseHandle( handle
);
542 /* resource notifications are events too */
544 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
546 trace( "memory resource notifications not supported\n" );
549 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
550 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
551 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
552 ret
= pQueryMemoryResourceNotification( handle
, &val
);
553 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
554 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
556 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
557 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
558 ret
= WaitForSingleObject( handle
, 10 );
559 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
562 ret
= pQueryMemoryResourceNotification( handle
, &val
);
563 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
564 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
565 ret
= CloseHandle( handle
);
566 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
568 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
570 ret
= pQueryMemoryResourceNotification( handle
, &val
);
571 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
572 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
573 CloseHandle( handle
);
576 static void test_semaphore(void)
578 HANDLE handle
, handle2
;
580 /* test case sensitivity */
582 SetLastError(0xdeadbeef);
583 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
584 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
585 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
587 SetLastError(0xdeadbeef);
588 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
589 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
590 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
591 CloseHandle( handle2
);
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() == 0, "wrong error %u\n", GetLastError());
597 CloseHandle( handle2
);
599 SetLastError(0xdeadbeef);
600 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
601 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
602 CloseHandle( handle2
);
604 SetLastError(0xdeadbeef);
605 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
606 ok( !handle2
, "OpenSemaphore succeeded\n");
607 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
609 SetLastError(0xdeadbeef);
610 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
611 ok( !handle2
, "OpenSemaphore succeeded\n");
612 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
614 SetLastError(0xdeadbeef);
615 handle2
= OpenSemaphoreW( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
616 ok( !handle2
, "OpenSemaphore succeeded\n");
617 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
619 CloseHandle( handle
);
622 static void test_waitable_timer(void)
624 HANDLE handle
, handle2
;
626 /* test case sensitivity */
628 SetLastError(0xdeadbeef);
629 handle
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
630 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
631 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
633 SetLastError(0xdeadbeef);
634 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
635 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
636 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
637 CloseHandle( handle2
);
639 SetLastError(0xdeadbeef);
640 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
641 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
642 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
643 CloseHandle( handle2
);
645 SetLastError(0xdeadbeef);
646 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
647 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
648 CloseHandle( handle2
);
650 SetLastError(0xdeadbeef);
651 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
652 ok( !handle2
, "OpenWaitableTimer succeeded\n");
653 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
655 SetLastError(0xdeadbeef);
656 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, NULL
);
657 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
658 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
660 SetLastError(0xdeadbeef);
661 handle2
= OpenWaitableTimerW( TIMER_ALL_ACCESS
, FALSE
, NULL
);
662 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
663 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
665 CloseHandle( handle
);
668 static HANDLE sem
= 0;
670 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
672 ReleaseSemaphore(sem
, 1, NULL
);
675 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
677 static void test_iocp_callback(void)
679 char temp_path
[MAX_PATH
];
680 char filename
[MAX_PATH
];
683 static const char prefix
[] = "pfx";
685 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
687 const char *buffer
= "12345678123456781234567812345678";
688 OVERLAPPED overlapped
;
690 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
691 if(!p_BindIoCompletionCallback
) {
692 win_skip("BindIoCompletionCallback not found in this DLL\n");
696 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
697 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
699 ret
= GetTempPathA(MAX_PATH
, temp_path
);
700 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
701 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
703 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
704 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
706 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
707 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
708 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
710 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
711 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
712 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
714 ret
= CloseHandle(hFile
);
715 ok( ret
, "CloseHandle: error %d\n", GetLastError());
716 ret
= DeleteFileA(filename
);
717 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
719 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
720 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
721 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
723 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
724 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
726 memset(&overlapped
, 0, sizeof(overlapped
));
727 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
728 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
730 ret
= WaitForSingleObject(sem
, 5000);
731 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
734 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
735 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
736 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
737 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
738 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
739 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
741 ret
= CloseHandle(hFile
);
742 ok( ret
, "CloseHandle: error %d\n", GetLastError());
743 ret
= DeleteFileA(filename
);
744 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
746 /* win2k3 requires the Flags parameter to be zero */
747 SetLastError(0xdeadbeef);
748 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
749 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
750 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
751 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
753 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
754 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
756 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
757 ret
= CloseHandle(hFile
);
758 ok( ret
, "CloseHandle: error %d\n", GetLastError());
759 ret
= DeleteFileA(filename
);
760 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
762 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
763 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
764 ok(GetLastError() == ERROR_INVALID_HANDLE
||
765 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
766 "Last error is %d\n", GetLastError());
769 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
772 ok(timedOut
, "Timer callbacks should always time out\n");
776 struct timer_queue_data1
783 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
785 struct timer_queue_data1
*d
= p
;
786 ok(timedOut
, "Timer callbacks should always time out\n");
787 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
790 SetLastError(0xdeadbeef);
791 /* Note, XP SP2 does *not* do any deadlock checking, so passing
792 INVALID_HANDLE_VALUE here will just hang. */
793 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
794 ok(!ret
, "DeleteTimerQueueTimer\n");
795 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
799 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
801 struct timer_queue_data1
*d
= p
;
802 ok(timedOut
, "Timer callbacks should always time out\n");
803 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
805 /* Basically kill the timer since it won't have time to run
807 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
808 ok(ret
, "ChangeTimerQueueTimer\n");
812 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
814 struct timer_queue_data1
*d
= p
;
815 ok(timedOut
, "Timer callbacks should always time out\n");
818 /* This tests whether a timer gets flagged for deletion before
819 or after the callback runs. If we start this timer with a
820 period of zero (run once), then ChangeTimerQueueTimer will
821 fail if the timer is already flagged. Hence we really run
822 only once. Otherwise we will run multiple times. */
823 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
824 ok(ret
, "ChangeTimerQueueTimer\n");
829 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
831 DWORD_PTR delay
= (DWORD_PTR
) p
;
832 ok(timedOut
, "Timer callbacks should always time out\n");
837 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
839 struct timer_queue_data1
*d
= p
;
840 ok(timedOut
, "Timer callbacks should always time out\n");
841 /* This tests an original implementation bug where a deleted timer may get
842 to run, but it is tricky to set up. */
843 if (d
->q
&& d
->num_calls
++ == 0)
845 /* First run: delete ourselves, then insert and remove a timer
846 that goes in front of us in the sorted timeout list. Once
847 removed, we will still timeout at the faster timer's due time,
848 but this should be a no-op if we are bug-free. There should
849 not be a second run. We can test the value of num_calls later. */
853 /* The delete will pend while we are in this callback. */
854 SetLastError(0xdeadbeef);
855 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
856 ok(!ret
, "DeleteTimerQueueTimer\n");
857 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
859 ret
= CreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
860 ok(ret
, "CreateTimerQueueTimer\n");
861 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
863 ret
= DeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
864 ok(ret
, "DeleteTimerQueueTimer\n");
866 /* Now we stay alive by hanging around in the callback. */
871 static void test_timer_queue(void)
873 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
874 int n0
, n1
, n2
, n3
, n4
, n5
;
875 struct timer_queue_data1 d1
, d2
, d3
, d4
;
879 /* Test asynchronous deletion of the queue. */
880 q
= CreateTimerQueue();
881 ok(q
!= NULL
, "CreateTimerQueue\n");
883 SetLastError(0xdeadbeef);
884 ret
= DeleteTimerQueueEx(q
, NULL
);
885 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
886 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
889 /* Test synchronous deletion of the queue and running timers. */
890 q
= CreateTimerQueue();
891 ok(q
!= NULL
, "CreateTimerQueue\n");
896 ret
= CreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0, 300, 0);
897 ok(ret
, "CreateTimerQueueTimer\n");
898 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
899 ret0
= DeleteTimerQueueTimer(q
, t0
, NULL
);
900 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
901 broken(ret0
), /* Win 2000 & XP & 2003 */
902 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
907 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0, 0, 0);
908 ok(ret
, "CreateTimerQueueTimer\n");
909 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
914 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0, 100, 0);
915 ok(ret
, "CreateTimerQueueTimer\n");
916 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
921 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0, 10, 0);
922 ok(ret
, "CreateTimerQueueTimer\n");
923 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
925 /* Start really late (it won't start). */
928 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000, 10, 0);
929 ok(ret
, "CreateTimerQueueTimer\n");
930 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
932 /* Start soon, but delay so long it won't run again. */
935 ret
= CreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0, 10000, 0);
936 ok(ret
, "CreateTimerQueueTimer\n");
937 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
939 /* Give them a chance to do some work. */
942 /* Test deleting a once-only timer. */
943 ret
= DeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
944 ok(ret
, "DeleteTimerQueueTimer\n");
946 /* A periodic timer. */
947 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
948 ok(ret
, "DeleteTimerQueueTimer\n");
950 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
951 ok(ret
, "DeleteTimerQueueEx\n");
953 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
954 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
955 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
956 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
957 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
959 /* Test synchronous deletion of the timer/queue with event trigger. */
960 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
961 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
962 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
963 if (!e
|| !et1
|| !et2
)
965 skip("Failed to create timer queue descruction event\n");
969 q
= CreateTimerQueue();
970 ok(q
!= NULL
, "CreateTimerQueue\n");
972 /* Run once and finish quickly (should be done when we delete it). */
974 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
975 ok(ret
, "CreateTimerQueueTimer\n");
976 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
978 /* Run once and finish slowly (shouldn't be done when we delete it). */
980 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
981 ok(ret
, "CreateTimerQueueTimer\n");
982 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
984 /* Run once and finish quickly (should be done when we delete it). */
986 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
987 ok(ret
, "CreateTimerQueueTimer\n");
988 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
990 /* Run once and finish slowly (shouldn't be done when we delete it). */
992 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
993 ok(ret
, "CreateTimerQueueTimer\n");
994 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
996 /* Give them a chance to start. */
999 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1000 even if the timer is finished. */
1001 SetLastError(0xdeadbeef);
1002 ret
= DeleteTimerQueueTimer(q
, t1
, NULL
);
1003 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1004 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1007 SetLastError(0xdeadbeef);
1008 ret
= DeleteTimerQueueTimer(q
, t2
, NULL
);
1009 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1010 ok(GetLastError() == ERROR_IO_PENDING
,
1011 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1014 SetLastError(0xdeadbeef);
1015 ret
= DeleteTimerQueueTimer(q
, t3
, et1
);
1016 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1017 ok(GetLastError() == 0xdeadbeef,
1018 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
1020 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
1021 "Timer destruction event not triggered\n");
1023 SetLastError(0xdeadbeef);
1024 ret
= DeleteTimerQueueTimer(q
, t4
, et2
);
1025 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1026 ok(GetLastError() == ERROR_IO_PENDING
,
1027 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1029 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
1030 "Timer destruction event not triggered\n");
1032 SetLastError(0xdeadbeef);
1033 ret
= DeleteTimerQueueEx(q
, e
);
1034 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1035 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1037 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
1038 "Queue destruction event not triggered\n");
1041 /* Test deleting/changing a timer in execution. */
1042 q
= CreateTimerQueue();
1043 ok(q
!= NULL
, "CreateTimerQueue\n");
1045 /* Test changing a once-only timer before it fires (this is allowed,
1046 whereas after it fires you cannot). */
1048 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000, 0, 0);
1049 ok(ret
, "CreateTimerQueueTimer\n");
1050 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1051 ret
= ChangeTimerQueueTimer(q
, t1
, 0, 0);
1052 ok(ret
, "ChangeTimerQueueTimer\n");
1058 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10, 10, 0);
1060 ok(ret
, "CreateTimerQueueTimer\n");
1061 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1067 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10, 10, 0);
1069 ok(ret
, "CreateTimerQueueTimer\n");
1070 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
1075 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10, 0, 0);
1077 ok(ret
, "CreateTimerQueueTimer\n");
1078 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1082 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
1083 ok(ret
, "DeleteTimerQueueEx\n");
1084 ok(n1
== 1, "ChangeTimerQueueTimer\n");
1085 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
1086 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
1087 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
1089 /* Test an obscure bug that was in the original implementation. */
1090 q
= CreateTimerQueue();
1091 ok(q
!= NULL
, "CreateTimerQueue\n");
1093 /* All the work is done in the callback. */
1097 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100, 100, WT_EXECUTELONGFUNCTION
);
1099 ok(ret
, "CreateTimerQueueTimer\n");
1100 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1104 SetLastError(0xdeadbeef);
1105 ret
= DeleteTimerQueueEx(q
, NULL
);
1106 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1107 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1109 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1111 /* Test functions on the default timer queue. */
1114 ret
= CreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1115 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1116 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1118 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1119 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1121 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1122 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1124 /* Try mixing default and non-default queues. Apparently this works. */
1125 q
= CreateTimerQueue();
1126 ok(q
!= NULL
, "CreateTimerQueue\n");
1130 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1131 ok(ret
, "CreateTimerQueueTimer\n");
1132 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1136 ret
= CreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000, 1000, 0);
1137 ok(ret
, "CreateTimerQueueTimer\n");
1138 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1140 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1141 ok(ret
, "ChangeTimerQueueTimer\n");
1143 ret
= ChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1144 ok(ret
, "ChangeTimerQueueTimer\n");
1146 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1147 ok(ret
, "DeleteTimerQueueTimer\n");
1149 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1150 ok(ret
, "DeleteTimerQueueTimer\n");
1152 /* Try to delete the default queue? In any case: not allowed. */
1153 SetLastError(0xdeadbeef);
1154 ret
= DeleteTimerQueueEx(NULL
, NULL
);
1155 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1156 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1157 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1160 SetLastError(0xdeadbeef);
1161 ret
= DeleteTimerQueueEx(q
, NULL
);
1162 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1163 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1167 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1169 DWORD tmp
= HandleToULong(handle
);
1171 return ULongToHandle(tmp
);
1174 static void test_WaitForSingleObject(void)
1176 HANDLE signaled
, nonsignaled
, invalid
;
1177 LARGE_INTEGER timeout
;
1181 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1182 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1183 invalid
= (HANDLE
) 0xdeadbee0;
1185 /* invalid handle with different values for lower 2 bits */
1186 SetLastError(0xdeadbeef);
1187 ret
= WaitForSingleObject(invalid
, 0);
1188 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1189 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1191 SetLastError(0xdeadbeef);
1192 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1193 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1194 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1196 SetLastError(0xdeadbeef);
1197 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1198 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1199 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1201 SetLastError(0xdeadbeef);
1202 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1203 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1204 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1206 /* valid handle with different values for lower 2 bits */
1207 SetLastError(0xdeadbeef);
1208 ret
= WaitForSingleObject(nonsignaled
, 0);
1209 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1210 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1212 SetLastError(0xdeadbeef);
1213 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1214 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1215 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1217 SetLastError(0xdeadbeef);
1218 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1219 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1220 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1222 SetLastError(0xdeadbeef);
1223 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1224 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1225 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1227 /* valid handle with different values for lower 2 bits */
1228 SetLastError(0xdeadbeef);
1229 ret
= WaitForSingleObject(signaled
, 0);
1230 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1231 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1233 SetLastError(0xdeadbeef);
1234 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1235 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1236 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1238 SetLastError(0xdeadbeef);
1239 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1240 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1241 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1243 SetLastError(0xdeadbeef);
1244 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1245 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1246 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1248 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1249 ret
= WaitForSingleObject(GetCurrentProcess(), 100);
1250 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1252 ret
= WaitForSingleObject(GetCurrentThread(), 100);
1253 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1255 timeout
.QuadPart
= -1000000;
1256 status
= pNtWaitForSingleObject(GetCurrentProcess(), FALSE
, &timeout
);
1257 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1259 timeout
.QuadPart
= -1000000;
1260 status
= pNtWaitForSingleObject(GetCurrentThread(), FALSE
, &timeout
);
1261 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1263 CloseHandle(signaled
);
1264 CloseHandle(nonsignaled
);
1267 static void test_WaitForMultipleObjects(void)
1269 LARGE_INTEGER timeout
;
1273 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1275 /* create the maximum number of events and make sure
1276 * we can wait on that many */
1277 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1279 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1280 ok( maxevents
[i
] != 0, "should create enough events\n");
1283 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1284 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1285 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1286 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1287 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1288 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1289 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1291 /* the lowest index is checked first and remaining events are untouched */
1292 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1293 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1296 /* run same test with Nt* call */
1297 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1298 SetEvent(maxevents
[i
]);
1300 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1301 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1302 ok(status
== STATUS_WAIT_0
, "should signal lowest handle first, got %08x\n", status
);
1303 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1304 ok(status
== STATUS_WAIT_0
, "should signal handle #0 first, got %08x\n", status
);
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 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1310 ok(status
== STATUS_WAIT_0
+ i
, "should signal handle #%d first, got %08x\n", i
, status
);
1313 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1314 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1316 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1317 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1318 maxevents
[0] = GetCurrentProcess();
1319 SetLastError(0xdeadbeef);
1320 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1321 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1322 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1323 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1325 maxevents
[0] = GetCurrentThread();
1326 SetLastError(0xdeadbeef);
1327 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1328 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1329 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1330 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1332 timeout
.QuadPart
= -1000000;
1333 maxevents
[0] = GetCurrentProcess();
1334 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1335 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1337 timeout
.QuadPart
= -1000000;
1338 maxevents
[0] = GetCurrentThread();
1339 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1340 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1343 static BOOL g_initcallback_ret
, g_initcallback_called
;
1344 static void *g_initctxt
;
1346 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1348 g_initcallback_called
= TRUE
;
1349 /* zero bit set means here that initialization is taking place - initialization locked */
1350 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1351 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1352 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1353 return g_initcallback_ret
;
1356 static void test_initonce(void)
1361 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1363 win_skip("one-time initialization API not supported\n");
1367 /* blocking initialization with callback */
1368 initonce
.Ptr
= (void*)0xdeadbeef;
1369 pInitOnceInitialize(&initonce
);
1370 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1372 /* initialisation completed successfully */
1373 g_initcallback_ret
= TRUE
;
1375 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1376 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1377 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1378 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1379 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1381 /* so it's been called already so won't be called again */
1383 g_initcallback_called
= FALSE
;
1384 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1385 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1386 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1387 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1388 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1390 pInitOnceInitialize(&initonce
);
1391 g_initcallback_called
= FALSE
;
1392 /* 2 lower order bits should never be used, you'll get a crash in result */
1393 g_initctxt
= (void*)0xFFFFFFF0;
1394 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1395 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1396 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1397 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1398 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1400 /* callback failed */
1401 g_initcallback_ret
= FALSE
;
1402 g_initcallback_called
= FALSE
;
1404 pInitOnceInitialize(&initonce
);
1405 SetLastError( 0xdeadbeef );
1406 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1407 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1408 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1409 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1410 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1412 /* blocking initialization without a callback */
1413 pInitOnceInitialize(&initonce
);
1416 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1417 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1418 ok(pending
, "got %d\n", pending
);
1419 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1420 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1421 /* another attempt to begin initialization with block a single thread */
1425 SetLastError( 0xdeadbeef );
1426 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1427 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1428 ok(pending
== 0xf, "got %d\n", pending
);
1429 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1430 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1432 g_initctxt
= (void*)0xdeadbee0;
1433 SetLastError( 0xdeadbeef );
1434 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1435 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1436 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1438 /* once failed already */
1439 g_initctxt
= (void*)0xdeadbee0;
1440 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1441 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1442 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1444 pInitOnceInitialize(&initonce
);
1445 SetLastError( 0xdeadbeef );
1446 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1447 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1448 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1450 SetLastError( 0xdeadbeef );
1451 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1452 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1453 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1455 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1456 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1457 ok(pending
, "got %d\n", pending
);
1458 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1460 SetLastError( 0xdeadbeef );
1461 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1462 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1464 SetLastError( 0xdeadbeef );
1465 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1466 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1467 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1469 SetLastError( 0xdeadbeef );
1470 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1471 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1472 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1474 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1475 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1476 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1478 pInitOnceInitialize(&initonce
);
1479 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1480 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1481 ok(pending
, "got %d\n", pending
);
1482 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1484 SetLastError( 0xdeadbeef );
1485 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1486 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1488 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1489 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1490 ok(pending
, "got %d\n", pending
);
1491 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1493 SetLastError( 0xdeadbeef );
1494 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1495 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1496 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1498 SetLastError( 0xdeadbeef );
1499 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1500 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1501 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1503 SetLastError( 0xdeadbeef );
1504 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1505 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1506 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1508 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1509 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1510 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1512 SetLastError( 0xdeadbeef );
1513 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1514 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1515 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1517 pInitOnceInitialize(&initonce
);
1518 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1519 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1520 ok(pending
, "got %d\n", pending
);
1521 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1523 /* test INIT_ONCE_CHECK_ONLY */
1525 pInitOnceInitialize(&initonce
);
1526 SetLastError( 0xdeadbeef );
1527 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1528 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1529 SetLastError( 0xdeadbeef );
1530 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1531 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1533 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1534 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1535 ok(pending
, "got %d\n", pending
);
1536 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1538 SetLastError( 0xdeadbeef );
1539 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1540 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1541 SetLastError( 0xdeadbeef );
1542 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1543 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1545 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1546 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1547 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1549 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1550 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1551 ok(!pending
, "got %d\n", pending
);
1552 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1553 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1555 SetLastError( 0xdeadbeef );
1556 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1557 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1559 pInitOnceInitialize(&initonce
);
1560 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1561 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1562 ok(pending
, "got %d\n", pending
);
1563 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1565 SetLastError( 0xdeadbeef );
1566 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1567 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1568 SetLastError( 0xdeadbeef );
1569 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1570 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1572 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1573 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1574 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1576 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1577 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1578 ok(!pending
, "got %d\n", pending
);
1579 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1580 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1582 SetLastError( 0xdeadbeef );
1583 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1584 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1587 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1588 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1589 static CRITICAL_SECTION buffercrit
;
1590 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1591 static LONG bufferlen
,totalproduced
,totalconsumed
;
1592 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1594 #define BUFFER_SIZE 5
1596 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1597 DWORD sleepinterval
= 5;
1600 Sleep(sleepinterval
);
1601 if (sleepinterval
> 1)
1604 EnterCriticalSection(&buffercrit
);
1605 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1606 condvar_producer_sleepcnt
++;
1607 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1608 if (GetLastError() != ERROR_TIMEOUT
)
1609 condvar_sleeperr
= TRUE
;
1613 LeaveCriticalSection(&buffercrit
);
1618 LeaveCriticalSection(&buffercrit
);
1619 pWakeConditionVariable(&buffernotempty
);
1624 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1625 DWORD
*cnt
= (DWORD
*)x
;
1626 DWORD sleepinterval
= 1;
1629 EnterCriticalSection(&buffercrit
);
1630 while ((bufferlen
== 0) && !condvar_stop
) {
1631 condvar_consumer_sleepcnt
++;
1632 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1633 if (GetLastError() != ERROR_TIMEOUT
)
1634 condvar_sleeperr
= TRUE
;
1637 if (condvar_stop
&& (bufferlen
== 0)) {
1638 LeaveCriticalSection(&buffercrit
);
1644 LeaveCriticalSection(&buffercrit
);
1645 pWakeConditionVariable(&buffernotfull
);
1646 Sleep(sleepinterval
);
1647 if (sleepinterval
< 5) sleepinterval
+= 1;
1652 static void test_condvars_consumer_producer(void)
1654 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1656 DWORD cnt1
,cnt2
,cnt3
;
1658 if (!pInitializeConditionVariable
) {
1659 /* function is not yet in XP, only in newer Windows */
1660 win_skip("no condition variable support.\n");
1664 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1666 /* If we have static initialized condition variables, InitializeConditionVariable
1667 * is not strictly necessary.
1668 * pInitializeConditionVariable(&buffernotfull);
1670 pInitializeConditionVariable(&buffernotempty
);
1671 InitializeCriticalSection(&buffercrit
);
1673 /* Larger Test: consumer/producer example */
1675 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1677 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1678 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1679 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1680 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1681 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1682 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1684 /* Limit run to 0.5 seconds. */
1687 /* tear down start */
1688 condvar_stop
= TRUE
;
1690 /* final wake up call */
1691 pWakeAllConditionVariable (&buffernotfull
);
1692 pWakeAllConditionVariable (&buffernotempty
);
1694 /* (mostly an implementation detail)
1695 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1698 WaitForSingleObject(hp1
, 1000);
1699 WaitForSingleObject(hp2
, 1000);
1700 WaitForSingleObject(hp3
, 1000);
1701 WaitForSingleObject(hc1
, 1000);
1702 WaitForSingleObject(hc2
, 1000);
1703 WaitForSingleObject(hc3
, 1000);
1705 ok(totalconsumed
== totalproduced
,
1706 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1707 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1709 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1710 * one consumer does not get anything to do is possible. */
1711 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1712 /* The sleeps of the producer or consumer should not go above 100* produced count,
1713 * otherwise the implementation does not sleep correctly. But yet again, this is
1714 * not hard defined. */
1715 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1718 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1719 static DWORD condvar_seq
= 0;
1720 static CONDITION_VARIABLE condvar_base
= CONDITION_VARIABLE_INIT
;
1721 static CRITICAL_SECTION condvar_crit
;
1722 static SRWLOCK condvar_srwlock
;
1724 /* Sequence of wake/sleep to check boundary conditions:
1726 * 1: producer emits a WakeConditionVariable without consumer waiting.
1727 * 2: consumer sleeps without a wake expecting timeout
1728 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1729 * 4: consumer sleeps without a wake expecting timeout
1730 * 5: a wake is handed to a SleepConditionVariableCS
1731 * 6: a wakeall is handed to a SleepConditionVariableCS
1732 * 7: sleep after above should timeout
1733 * 8: wake with crit section locked into the sleep timeout
1735 * the following tests will only be executed if InitializeSRWLock is available
1737 * 9: producer (exclusive) wakes up consumer (exclusive)
1738 * 10: producer (exclusive) wakes up consumer (shared)
1739 * 11: producer (shared) wakes up consumer (exclusive)
1740 * 12: producer (shared) wakes up consumer (shared)
1743 static DWORD WINAPI
condvar_base_producer(LPVOID x
) {
1744 while (condvar_seq
< 1) Sleep(1);
1746 pWakeConditionVariable (&condvar_base
);
1749 while (condvar_seq
< 3) Sleep(1);
1750 pWakeAllConditionVariable (&condvar_base
);
1753 while (condvar_seq
< 5) Sleep(1);
1754 EnterCriticalSection (&condvar_crit
);
1755 pWakeConditionVariable (&condvar_base
);
1756 LeaveCriticalSection (&condvar_crit
);
1757 while (condvar_seq
< 6) Sleep(1);
1758 EnterCriticalSection (&condvar_crit
);
1759 pWakeAllConditionVariable (&condvar_base
);
1760 LeaveCriticalSection (&condvar_crit
);
1762 while (condvar_seq
< 8) Sleep(1);
1763 EnterCriticalSection (&condvar_crit
);
1764 pWakeConditionVariable (&condvar_base
);
1766 LeaveCriticalSection (&condvar_crit
);
1768 /* skip over remaining tests if InitializeSRWLock is not available */
1769 if (!pInitializeSRWLock
)
1772 while (condvar_seq
< 9) Sleep(1);
1773 pAcquireSRWLockExclusive(&condvar_srwlock
);
1774 pWakeConditionVariable(&condvar_base
);
1775 pReleaseSRWLockExclusive(&condvar_srwlock
);
1777 while (condvar_seq
< 10) Sleep(1);
1778 pAcquireSRWLockExclusive(&condvar_srwlock
);
1779 pWakeConditionVariable(&condvar_base
);
1780 pReleaseSRWLockExclusive(&condvar_srwlock
);
1782 while (condvar_seq
< 11) Sleep(1);
1783 pAcquireSRWLockShared(&condvar_srwlock
);
1784 pWakeConditionVariable(&condvar_base
);
1785 pReleaseSRWLockShared(&condvar_srwlock
);
1787 while (condvar_seq
< 12) Sleep(1);
1788 Sleep(50); /* ensure that consumer waits for cond variable */
1789 pAcquireSRWLockShared(&condvar_srwlock
);
1790 pWakeConditionVariable(&condvar_base
);
1791 pReleaseSRWLockShared(&condvar_srwlock
);
1796 static DWORD WINAPI
condvar_base_consumer(LPVOID x
) {
1799 while (condvar_seq
< 2) Sleep(1);
1801 /* wake was emitted, but we were not sleeping */
1802 EnterCriticalSection (&condvar_crit
);
1803 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1804 LeaveCriticalSection (&condvar_crit
);
1805 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1806 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1809 while (condvar_seq
< 4) Sleep(1);
1811 /* wake all was emitted, but we were not sleeping */
1812 EnterCriticalSection (&condvar_crit
);
1813 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1814 LeaveCriticalSection (&condvar_crit
);
1815 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1816 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1818 EnterCriticalSection (&condvar_crit
);
1820 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1821 LeaveCriticalSection (&condvar_crit
);
1822 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1824 EnterCriticalSection (&condvar_crit
);
1826 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 200);
1827 LeaveCriticalSection (&condvar_crit
);
1828 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1831 EnterCriticalSection (&condvar_crit
);
1832 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1833 LeaveCriticalSection (&condvar_crit
);
1834 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1835 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1837 EnterCriticalSection (&condvar_crit
);
1839 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 20);
1840 LeaveCriticalSection (&condvar_crit
);
1841 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1843 /* skip over remaining tests if InitializeSRWLock is not available */
1844 if (!pInitializeSRWLock
)
1846 win_skip("no srw lock support.\n");
1847 condvar_seq
= 13; /* end */
1851 pAcquireSRWLockExclusive(&condvar_srwlock
);
1853 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1854 pReleaseSRWLockExclusive(&condvar_srwlock
);
1855 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1857 pAcquireSRWLockShared(&condvar_srwlock
);
1859 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1860 pReleaseSRWLockShared(&condvar_srwlock
);
1861 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1863 pAcquireSRWLockExclusive(&condvar_srwlock
);
1865 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, 0);
1866 pReleaseSRWLockExclusive(&condvar_srwlock
);
1867 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1869 pAcquireSRWLockShared(&condvar_srwlock
);
1871 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1872 pReleaseSRWLockShared(&condvar_srwlock
);
1873 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1879 static void test_condvars_base(void) {
1885 if (!pInitializeConditionVariable
) {
1886 /* function is not yet in XP, only in newer Windows */
1887 win_skip("no condition variable support.\n");
1891 InitializeCriticalSection (&condvar_crit
);
1893 if (pInitializeSRWLock
)
1894 pInitializeSRWLock(&condvar_srwlock
);
1896 EnterCriticalSection (&condvar_crit
);
1897 ret
= pSleepConditionVariableCS(&condvar_base
, &condvar_crit
, 10);
1898 LeaveCriticalSection (&condvar_crit
);
1900 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1901 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1903 if (pInitializeSRWLock
)
1905 pAcquireSRWLockExclusive(&condvar_srwlock
);
1906 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, 0);
1907 pReleaseSRWLockExclusive(&condvar_srwlock
);
1909 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1910 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1912 pAcquireSRWLockShared(&condvar_srwlock
);
1913 ret
= pSleepConditionVariableSRW(&condvar_base
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1914 pReleaseSRWLockShared(&condvar_srwlock
);
1916 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1917 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1921 hp
= CreateThread(NULL
, 0, condvar_base_producer
, NULL
, 0, &dummy
);
1922 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, NULL
, 0, &dummy
);
1924 condvar_seq
= 1; /* go */
1926 while (condvar_seq
< 9)
1928 WaitForSingleObject(hp
, 100);
1929 WaitForSingleObject(hc
, 100);
1932 static LONG srwlock_seq
= 0;
1933 static SRWLOCK srwlock_base
;
1936 LONG wrong_execution_order
;
1937 LONG samethread_excl_excl
;
1938 LONG samethread_excl_shared
;
1939 LONG samethread_shared_excl
;
1940 LONG multithread_excl_excl
;
1941 LONG excl_not_preferred
;
1943 LONG trylock_shared
;
1944 } srwlock_base_errors
;
1946 /* Sequence of acquire/release to check boundary conditions:
1949 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1950 * 2: thread1 expects a deadlock and releases the waiting lock
1951 * thread2 releases the lock again
1953 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1954 * 4: thread1 expects a deadlock and releases the waiting lock
1955 * thread2 releases the lock again
1957 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1958 * 6: thread1 expects a deadlock and releases the waiting lock
1959 * thread2 releases the lock again
1961 * 7: thread2 acquires and releases two nested shared locks
1963 * 8: thread1 acquires an exclusive lock
1964 * 9: thread2 tries to acquire the exclusive lock, too
1965 * thread1 releases the exclusive lock again
1966 * 10: thread2 enters the exclusive lock and leaves it immediately again
1968 * 11: thread1 acquires a shared lock
1969 * 12: thread2 acquires and releases a shared lock
1970 * thread1 releases the lock again
1972 * 13: thread1 acquires a shared lock
1973 * 14: thread2 tries to acquire an exclusive lock
1974 * 15: thread3 tries to acquire a shared lock
1975 * 16: thread1 releases the shared lock
1976 * 17: thread2 wakes up and releases the exclusive lock
1977 * 18: thread3 wakes up and releases the shared lock
1979 * the following tests will only be executed if TryAcquireSRWLock* is available
1981 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
1982 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1983 * thread1 releases the exclusive lock
1985 * thread1 calls TryAcquireSRWLockShared which should return TRUE
1986 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
1987 * thread1 releases the shared lock
1989 * thread1 acquires an exclusive lock
1990 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
1991 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1992 * 21: thread1 releases the exclusive lock
1994 * thread1 acquires an shared lock
1995 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
1996 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
1997 * 23: thread1 releases the shared lock
1999 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2000 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2001 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2002 * 25: thread1 releases the exclusive lock
2004 * thread1 acquires two shared locks
2005 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2006 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2007 * 27: thread1 releases one shared lock
2008 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2009 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2010 * 29: thread1 releases the second shared lock
2011 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2012 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2017 static DWORD WINAPI
srwlock_base_thread1(LPVOID x
)
2020 while (srwlock_seq
< 2) Sleep(1);
2022 if (InterlockedIncrement(&srwlock_seq
) != 3)
2023 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2024 pReleaseSRWLockExclusive(&srwlock_base
);
2027 while (srwlock_seq
< 4) Sleep(1);
2029 if (InterlockedIncrement(&srwlock_seq
) != 5)
2030 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2031 pReleaseSRWLockExclusive(&srwlock_base
);
2034 while (srwlock_seq
< 6) Sleep(1);
2036 if (InterlockedIncrement(&srwlock_seq
) != 7)
2037 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2038 pReleaseSRWLockShared(&srwlock_base
);
2041 while (srwlock_seq
< 8) Sleep(1);
2042 pAcquireSRWLockExclusive(&srwlock_base
);
2043 if (InterlockedIncrement(&srwlock_seq
) != 9)
2044 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2046 if (InterlockedIncrement(&srwlock_seq
) != 10)
2047 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2048 pReleaseSRWLockExclusive(&srwlock_base
);
2051 while (srwlock_seq
< 11) Sleep(1);
2052 pAcquireSRWLockShared(&srwlock_base
);
2053 if (InterlockedIncrement(&srwlock_seq
) != 12)
2054 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2057 while (srwlock_seq
< 13) Sleep(1);
2058 pReleaseSRWLockShared(&srwlock_base
);
2059 pAcquireSRWLockShared(&srwlock_base
);
2060 if (InterlockedIncrement(&srwlock_seq
) != 14)
2061 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2064 while (srwlock_seq
< 16) Sleep(1);
2065 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2066 if (InterlockedIncrement(&srwlock_seq
) != 17)
2067 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2068 pReleaseSRWLockShared(&srwlock_base
);
2070 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2071 if (!pTryAcquireSRWLockExclusive
)
2075 while (srwlock_seq
< 19) Sleep(1);
2076 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2078 if (pTryAcquireSRWLockShared(&srwlock_base
))
2079 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2080 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2081 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2082 pReleaseSRWLockExclusive(&srwlock_base
);
2085 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2087 if (pTryAcquireSRWLockShared(&srwlock_base
))
2089 if (pTryAcquireSRWLockShared(&srwlock_base
))
2090 pReleaseSRWLockShared(&srwlock_base
);
2092 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2093 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2094 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2095 pReleaseSRWLockShared(&srwlock_base
);
2098 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2100 pAcquireSRWLockExclusive(&srwlock_base
);
2101 if (InterlockedIncrement(&srwlock_seq
) != 20)
2102 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2105 while (srwlock_seq
< 21) Sleep(1);
2106 pReleaseSRWLockExclusive(&srwlock_base
);
2107 pAcquireSRWLockShared(&srwlock_base
);
2108 if (InterlockedIncrement(&srwlock_seq
) != 22)
2109 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2112 while (srwlock_seq
< 23) Sleep(1);
2113 pReleaseSRWLockShared(&srwlock_base
);
2114 pAcquireSRWLockShared(&srwlock_base
);
2115 if (InterlockedIncrement(&srwlock_seq
) != 24)
2116 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2119 pAcquireSRWLockExclusive(&srwlock_base
);
2120 if (srwlock_seq
!= 25)
2121 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2122 pReleaseSRWLockExclusive(&srwlock_base
);
2124 pAcquireSRWLockShared(&srwlock_base
);
2125 pAcquireSRWLockShared(&srwlock_base
);
2126 if (InterlockedIncrement(&srwlock_seq
) != 26)
2127 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2130 while (srwlock_seq
< 27) Sleep(1);
2131 pReleaseSRWLockShared(&srwlock_base
);
2132 if (InterlockedIncrement(&srwlock_seq
) != 28)
2133 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2136 while (srwlock_seq
< 29) Sleep(1);
2137 pReleaseSRWLockShared(&srwlock_base
);
2138 if (InterlockedIncrement(&srwlock_seq
) != 30)
2139 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2144 static DWORD WINAPI
srwlock_base_thread2(LPVOID x
)
2147 while (srwlock_seq
< 1) Sleep(1);
2148 pAcquireSRWLockExclusive(&srwlock_base
);
2149 if (InterlockedIncrement(&srwlock_seq
) != 2)
2150 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2153 pAcquireSRWLockExclusive(&srwlock_base
);
2154 if (srwlock_seq
!= 3)
2155 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2156 pReleaseSRWLockExclusive(&srwlock_base
);
2157 pAcquireSRWLockExclusive(&srwlock_base
);
2158 if (InterlockedIncrement(&srwlock_seq
) != 4)
2159 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2162 pAcquireSRWLockShared(&srwlock_base
);
2163 if (srwlock_seq
!= 5)
2164 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2165 pReleaseSRWLockShared(&srwlock_base
);
2166 pAcquireSRWLockShared(&srwlock_base
);
2167 if (InterlockedIncrement(&srwlock_seq
) != 6)
2168 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2171 pAcquireSRWLockExclusive(&srwlock_base
);
2172 if (srwlock_seq
!= 7)
2173 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2174 pReleaseSRWLockExclusive(&srwlock_base
);
2175 pAcquireSRWLockShared(&srwlock_base
);
2176 pAcquireSRWLockShared(&srwlock_base
);
2177 pReleaseSRWLockShared(&srwlock_base
);
2178 pReleaseSRWLockShared(&srwlock_base
);
2179 if (InterlockedIncrement(&srwlock_seq
) != 8)
2180 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2183 while (srwlock_seq
< 9) Sleep(1);
2184 pAcquireSRWLockExclusive(&srwlock_base
);
2185 if (srwlock_seq
!= 10)
2186 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2187 pReleaseSRWLockExclusive(&srwlock_base
);
2188 if (InterlockedIncrement(&srwlock_seq
) != 11)
2189 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2192 while (srwlock_seq
< 12) Sleep(1);
2193 pAcquireSRWLockShared(&srwlock_base
);
2194 pReleaseSRWLockShared(&srwlock_base
);
2195 if (InterlockedIncrement(&srwlock_seq
) != 13)
2196 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2199 while (srwlock_seq
< 14) Sleep(1);
2200 if (InterlockedIncrement(&srwlock_seq
) != 15)
2201 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2204 pAcquireSRWLockExclusive(&srwlock_base
);
2205 if (srwlock_seq
!= 17)
2206 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2207 if (InterlockedIncrement(&srwlock_seq
) != 18)
2208 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2209 pReleaseSRWLockExclusive(&srwlock_base
);
2211 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2212 if (!pTryAcquireSRWLockExclusive
)
2216 while (srwlock_seq
< 20) Sleep(1);
2217 if (pTryAcquireSRWLockShared(&srwlock_base
))
2218 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2219 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2220 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2221 if (InterlockedIncrement(&srwlock_seq
) != 21)
2222 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2225 while (srwlock_seq
< 22) Sleep(1);
2226 if (pTryAcquireSRWLockShared(&srwlock_base
))
2227 pReleaseSRWLockShared(&srwlock_base
);
2229 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2230 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2231 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2232 if (InterlockedIncrement(&srwlock_seq
) != 23)
2233 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2236 while (srwlock_seq
< 24) Sleep(1);
2237 Sleep(50); /* ensure that exclusive access request is queued */
2238 if (pTryAcquireSRWLockShared(&srwlock_base
))
2240 pReleaseSRWLockShared(&srwlock_base
);
2241 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2243 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2244 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2245 if (InterlockedIncrement(&srwlock_seq
) != 25)
2246 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2247 pReleaseSRWLockShared(&srwlock_base
);
2250 while (srwlock_seq
< 26) Sleep(1);
2251 if (pTryAcquireSRWLockShared(&srwlock_base
))
2252 pReleaseSRWLockShared(&srwlock_base
);
2254 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2255 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2256 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2257 if (InterlockedIncrement(&srwlock_seq
) != 27)
2258 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2261 while (srwlock_seq
< 28) Sleep(1);
2262 if (pTryAcquireSRWLockShared(&srwlock_base
))
2263 pReleaseSRWLockShared(&srwlock_base
);
2265 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2266 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2267 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2268 if (InterlockedIncrement(&srwlock_seq
) != 29)
2269 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2272 while (srwlock_seq
< 30) Sleep(1);
2273 if (pTryAcquireSRWLockShared(&srwlock_base
))
2274 pReleaseSRWLockShared(&srwlock_base
);
2276 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2277 if (pTryAcquireSRWLockExclusive(&srwlock_base
))
2278 pReleaseSRWLockExclusive(&srwlock_base
);
2280 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2281 if (InterlockedIncrement(&srwlock_seq
) != 31)
2282 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2287 static DWORD WINAPI
srwlock_base_thread3(LPVOID x
)
2290 while (srwlock_seq
< 15) Sleep(1);
2291 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2292 if (InterlockedIncrement(&srwlock_seq
) != 16)
2293 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2296 pAcquireSRWLockShared(&srwlock_base
);
2297 if (srwlock_seq
!= 18)
2298 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2299 pReleaseSRWLockShared(&srwlock_base
);
2300 if (InterlockedIncrement(&srwlock_seq
) != 19)
2301 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2303 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2304 if (!pTryAcquireSRWLockExclusive
)
2306 /* function is only in Windows 7 and newer */
2307 win_skip("no srw trylock support.\n");
2308 srwlock_seq
= 31; /* end */
2315 static void test_srwlock_base(void)
2320 if (!pInitializeSRWLock
)
2322 /* function is not yet in XP, only in newer Windows */
2323 win_skip("no srw lock support.\n");
2327 pInitializeSRWLock(&srwlock_base
);
2328 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2330 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, NULL
, 0, &dummy
);
2331 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, NULL
, 0, &dummy
);
2332 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, NULL
, 0, &dummy
);
2334 srwlock_seq
= 1; /* go */
2335 while (srwlock_seq
< 31)
2338 WaitForSingleObject(h1
, 100);
2339 WaitForSingleObject(h2
, 100);
2340 WaitForSingleObject(h3
, 100);
2342 ok(!srwlock_base_errors
.wrong_execution_order
,
2343 "thread commands were executed in the wrong order (occurred %d times).\n",
2344 srwlock_base_errors
.wrong_execution_order
);
2346 ok(!srwlock_base_errors
.samethread_excl_excl
,
2347 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2348 srwlock_base_errors
.samethread_excl_excl
);
2350 ok(!srwlock_base_errors
.samethread_excl_shared
,
2351 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2352 srwlock_base_errors
.samethread_excl_shared
);
2354 ok(!srwlock_base_errors
.samethread_shared_excl
,
2355 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2356 srwlock_base_errors
.samethread_shared_excl
);
2358 ok(!srwlock_base_errors
.multithread_excl_excl
,
2359 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2360 srwlock_base_errors
.multithread_excl_excl
);
2362 ok(!srwlock_base_errors
.excl_not_preferred
,
2363 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2364 srwlock_base_errors
.excl_not_preferred
);
2366 ok(!srwlock_base_errors
.trylock_excl
,
2367 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2368 srwlock_base_errors
.trylock_excl
);
2370 ok(!srwlock_base_errors
.trylock_shared
,
2371 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2372 srwlock_base_errors
.trylock_shared
);
2376 static SRWLOCK srwlock_example
;
2377 static LONG srwlock_protected_value
= 0;
2378 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2379 static BOOL srwlock_stop
= FALSE
;
2381 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2385 while (!srwlock_stop
)
2388 /* periodically request exclusive access */
2389 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2391 pAcquireSRWLockExclusive(&srwlock_example
);
2392 if (InterlockedIncrement(&srwlock_inside
) != 1)
2393 InterlockedIncrement(&srwlock_example_errors
);
2395 InterlockedIncrement(&srwlock_protected_value
);
2398 if (InterlockedDecrement(&srwlock_inside
) != 0)
2399 InterlockedIncrement(&srwlock_example_errors
);
2400 pReleaseSRWLockExclusive(&srwlock_example
);
2403 /* request shared access */
2404 pAcquireSRWLockShared(&srwlock_example
);
2405 InterlockedIncrement(&srwlock_inside
);
2406 old
= srwlock_protected_value
;
2411 if (old
!= srwlock_protected_value
)
2412 InterlockedIncrement(&srwlock_example_errors
);
2413 InterlockedDecrement(&srwlock_inside
);
2414 pReleaseSRWLockShared(&srwlock_example
);
2420 static void test_srwlock_example(void)
2424 DWORD cnt1
, cnt2
, cnt3
;
2426 if (!pInitializeSRWLock
) {
2427 /* function is not yet in XP, only in newer Windows */
2428 win_skip("no srw lock support.\n");
2432 pInitializeSRWLock(&srwlock_example
);
2434 cnt1
= cnt2
= cnt3
= 0;
2436 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2437 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2438 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2440 /* limit run to 1 second. */
2443 /* tear down start */
2444 srwlock_stop
= TRUE
;
2446 WaitForSingleObject(h1
, 1000);
2447 WaitForSingleObject(h2
, 1000);
2448 WaitForSingleObject(h3
, 1000);
2450 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2451 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2452 srwlock_example_errors
);
2454 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2455 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2458 static DWORD WINAPI
alertable_wait_thread(void *param
)
2460 HANDLE
*semaphores
= param
;
2461 LARGE_INTEGER timeout
;
2465 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2466 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 1000, TRUE
);
2467 ok(result
== WAIT_IO_COMPLETION
, "expected WAIT_IO_COMPLETION, got %u\n", result
);
2468 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 200, TRUE
);
2469 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2471 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2472 timeout
.QuadPart
= -10000000;
2473 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2474 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2475 timeout
.QuadPart
= -2000000;
2476 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2477 ok(status
== STATUS_WAIT_0
, "expected STATUS_WAIT_0, got %08x\n", status
);
2479 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2480 timeout
.QuadPart
= -10000000;
2481 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2482 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2483 result
= WaitForSingleObject(semaphores
[0], 0);
2484 ok(result
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", result
);
2489 static void CALLBACK
alertable_wait_apc(ULONG_PTR userdata
)
2491 HANDLE
*semaphores
= (void *)userdata
;
2492 ReleaseSemaphore(semaphores
[1], 1, NULL
);
2495 static void CALLBACK
alertable_wait_apc2(ULONG_PTR userdata
)
2497 HANDLE
*semaphores
= (void *)userdata
;
2500 result
= WaitForSingleObject(semaphores
[0], 1000);
2501 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2504 static void test_alertable_wait(void)
2506 HANDLE thread
, semaphores
[2];
2509 semaphores
[0] = CreateSemaphoreW(NULL
, 0, 2, NULL
);
2510 ok(semaphores
[0] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2511 semaphores
[1] = CreateSemaphoreW(NULL
, 0, 1, NULL
);
2512 ok(semaphores
[1] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2513 thread
= CreateThread(NULL
, 0, alertable_wait_thread
, semaphores
, 0, NULL
);
2514 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2516 result
= WaitForSingleObject(semaphores
[0], 1000);
2517 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2518 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2519 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2520 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2522 result
= WaitForSingleObject(semaphores
[0], 1000);
2523 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2524 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2525 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2526 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2528 result
= WaitForSingleObject(semaphores
[0], 1000);
2529 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2530 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2531 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2532 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2533 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2534 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2535 ReleaseSemaphore(semaphores
[0], 2, NULL
);
2537 result
= WaitForSingleObject(thread
, 1000);
2538 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2539 CloseHandle(thread
);
2540 CloseHandle(semaphores
[0]);
2541 CloseHandle(semaphores
[1]);
2544 struct apc_deadlock_info
2546 PROCESS_INFORMATION
*pi
;
2551 static DWORD WINAPI
apc_deadlock_thread(void *param
)
2553 struct apc_deadlock_info
*info
= param
;
2554 PROCESS_INFORMATION
*pi
= info
->pi
;
2559 while (info
->running
)
2563 status
= pNtAllocateVirtualMemory(pi
->hProcess
, &base
, 0, &size
,
2564 MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2565 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2566 ok(base
!= NULL
, "expected base != NULL, got %p\n", base
);
2567 SetEvent(info
->event
);
2570 status
= pNtFreeVirtualMemory(pi
->hProcess
, &base
, &size
, MEM_RELEASE
);
2571 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2572 SetEvent(info
->event
);
2578 static void test_apc_deadlock(void)
2580 struct apc_deadlock_info info
;
2581 PROCESS_INFORMATION pi
;
2582 STARTUPINFOA si
= { sizeof(si
) };
2583 char cmdline
[MAX_PATH
];
2584 HANDLE event
, thread
;
2590 winetest_get_mainargs(&argv
);
2591 sprintf(cmdline
, "\"%s\" sync apc_deadlock", argv
[0]);
2592 success
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2593 ok(success
, "CreateProcess failed with %u\n", GetLastError());
2595 event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2596 ok(event
!= NULL
, "CreateEvent failed with %u\n", GetLastError());
2600 info
.running
= TRUE
;
2602 thread
= CreateThread(NULL
, 0, apc_deadlock_thread
, &info
, 0, NULL
);
2603 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2604 result
= WaitForSingleObject(event
, 1000);
2605 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2607 for (i
= 0; i
< 1000 && info
.running
; i
++)
2609 result
= SuspendThread(pi
.hThread
);
2610 ok(result
== 0, "expected 0, got %u\n", result
);
2612 WaitForSingleObject(event
, 0); /* reset event */
2613 result
= WaitForSingleObject(event
, 1000);
2614 if (result
== WAIT_TIMEOUT
)
2617 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2618 info
.running
= FALSE
;
2621 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2623 result
= ResumeThread(pi
.hThread
);
2624 ok(result
== 1, "expected 1, got %u\n", result
);
2628 info
.running
= FALSE
;
2629 result
= WaitForSingleObject(thread
, 1000);
2630 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2631 CloseHandle(thread
);
2634 TerminateProcess(pi
.hProcess
, 0);
2635 CloseHandle(pi
.hThread
);
2636 CloseHandle(pi
.hProcess
);
2643 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2644 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2646 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2647 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2648 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2649 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2650 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2651 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2652 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2653 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2654 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2655 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2656 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2657 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2658 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2659 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2660 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2661 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2662 pNtAllocateVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtAllocateVirtualMemory");
2663 pNtFreeVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtFreeVirtualMemory");
2664 pNtWaitForSingleObject
= (void *)GetProcAddress(hntdll
, "NtWaitForSingleObject");
2665 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2666 pRtlInterlockedPushListSList
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSList");
2667 pRtlInterlockedPushListSListEx
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSListEx");
2669 argc
= winetest_get_mainargs( &argv
);
2672 if (!strcmp(argv
[2], "apc_deadlock"))
2674 for (;;) SleepEx(INFINITE
, TRUE
);
2679 init_fastcall_thunk();
2680 test_signalandwait();
2685 test_waitable_timer();
2686 test_iocp_callback();
2688 test_WaitForSingleObject();
2689 test_WaitForMultipleObjects();
2691 test_condvars_base();
2692 test_condvars_consumer_producer();
2693 test_srwlock_base();
2694 test_srwlock_example();
2695 test_alertable_wait();
2696 test_apc_deadlock();