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
26 #define WIN32_NO_STATUS
31 #include "wine/test.h"
34 #define __fastcall __stdcall
36 static HANDLE (WINAPI
*pCreateMemoryResourceNotification
)(MEMORY_RESOURCE_NOTIFICATION_TYPE
);
37 static BOOL (WINAPI
*pQueryMemoryResourceNotification
)(HANDLE
, PBOOL
);
38 static VOID (WINAPI
*pInitOnceInitialize
)(PINIT_ONCE
);
39 static BOOL (WINAPI
*pInitOnceExecuteOnce
)(PINIT_ONCE
,PINIT_ONCE_FN
,PVOID
,LPVOID
*);
40 static BOOL (WINAPI
*pInitOnceBeginInitialize
)(PINIT_ONCE
,DWORD
,BOOL
*,LPVOID
*);
41 static BOOL (WINAPI
*pInitOnceComplete
)(PINIT_ONCE
,DWORD
,LPVOID
);
43 static BOOL (WINAPI
*pInitializeCriticalSectionEx
)(CRITICAL_SECTION
*,DWORD
,DWORD
);
44 static VOID (WINAPI
*pInitializeConditionVariable
)(PCONDITION_VARIABLE
);
45 static BOOL (WINAPI
*pSleepConditionVariableCS
)(PCONDITION_VARIABLE
,PCRITICAL_SECTION
,DWORD
);
46 static BOOL (WINAPI
*pSleepConditionVariableSRW
)(PCONDITION_VARIABLE
,PSRWLOCK
,DWORD
,ULONG
);
47 static VOID (WINAPI
*pWakeAllConditionVariable
)(PCONDITION_VARIABLE
);
48 static VOID (WINAPI
*pWakeConditionVariable
)(PCONDITION_VARIABLE
);
50 static VOID (WINAPI
*pInitializeSRWLock
)(PSRWLOCK
);
51 static VOID (WINAPI
*pAcquireSRWLockExclusive
)(PSRWLOCK
);
52 static VOID (WINAPI
*pAcquireSRWLockShared
)(PSRWLOCK
);
53 static VOID (WINAPI
*pReleaseSRWLockExclusive
)(PSRWLOCK
);
54 static VOID (WINAPI
*pReleaseSRWLockShared
)(PSRWLOCK
);
55 static BOOLEAN (WINAPI
*pTryAcquireSRWLockExclusive
)(PSRWLOCK
);
56 static BOOLEAN (WINAPI
*pTryAcquireSRWLockShared
)(PSRWLOCK
);
58 static NTSTATUS (WINAPI
*pNtAllocateVirtualMemory
)(HANDLE
, PVOID
*, ULONG_PTR
, SIZE_T
*, ULONG
, ULONG
);
59 static NTSTATUS (WINAPI
*pNtFreeVirtualMemory
)(HANDLE
, PVOID
*, SIZE_T
*, ULONG
);
60 static NTSTATUS (WINAPI
*pNtWaitForSingleObject
)(HANDLE
, BOOLEAN
, const LARGE_INTEGER
*);
61 static NTSTATUS (WINAPI
*pNtWaitForMultipleObjects
)(ULONG
,const HANDLE
*,BOOLEAN
,BOOLEAN
,const LARGE_INTEGER
*);
62 static PSLIST_ENTRY (__fastcall
*pRtlInterlockedPushListSList
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
63 PSLIST_ENTRY last
, ULONG count
);
64 static PSLIST_ENTRY (WINAPI
*pRtlInterlockedPushListSListEx
)(PSLIST_HEADER list
, PSLIST_ENTRY first
,
65 PSLIST_ENTRY last
, ULONG count
);
66 static NTSTATUS (WINAPI
*pNtQueueApcThread
)(HANDLE
,PNTAPCFUNC
,ULONG_PTR
,ULONG_PTR
,ULONG_PTR
);
73 BYTE pop_edx
; /* popl %edx (ret addr) */
74 BYTE pop_eax
; /* popl %eax (func) */
75 BYTE pop_ecx
; /* popl %ecx (param 1) */
76 BYTE xchg
[3]; /* xchgl (%esp),%edx (param 2) */
77 WORD jmp_eax
; /* jmp *%eax */
81 static void * (WINAPI
*call_fastcall_func4
)(void *func
, const void *a
, const void *b
, const void *c
, const void *d
);
83 static void init_fastcall_thunk(void)
85 struct fastcall_thunk
*thunk
= VirtualAlloc(NULL
, sizeof(*thunk
), MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
86 thunk
->pop_edx
= 0x5a; /* popl %edx */
87 thunk
->pop_eax
= 0x58; /* popl %eax */
88 thunk
->pop_ecx
= 0x59; /* popl %ecx */
89 thunk
->xchg
[0] = 0x87; /* xchgl (%esp),%edx */
90 thunk
->xchg
[1] = 0x14;
91 thunk
->xchg
[2] = 0x24;
92 thunk
->jmp_eax
= 0xe0ff; /* jmp *%eax */
93 call_fastcall_func4
= (void *)thunk
;
96 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
97 (const void *)(b), (const void *)(c), (const void *)(d))
101 #define init_fastcall_thunk() do { } while(0)
102 #define call_func4(func, a, b, c, d) func(a, b, c, d)
104 #endif /* __i386__ */
106 static void test_signalandwait(void)
109 HANDLE event
[2], semaphore
[2], file
;
112 /* invalid parameters */
113 r
= SignalObjectAndWait(NULL
, NULL
, 0, 0);
114 ok( r
== WAIT_FAILED
, "should fail\n");
116 event
[0] = CreateEventW(NULL
, 0, 0, NULL
);
117 event
[1] = CreateEventW(NULL
, 1, 1, NULL
);
119 ok( event
[0] && event
[1], "failed to create event flags\n");
121 r
= SignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
122 ok( r
== WAIT_FAILED
, "should fail\n");
124 r
= SignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
125 ok( r
== WAIT_FAILED
, "should fail\n");
128 /* valid parameters */
129 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
130 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
132 /* event[0] is now signalled - we repeat this test multiple times
133 * to ensure that the wineserver handles this situation properly. */
134 for (i
= 0; i
< 10000; i
++)
136 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
137 ok(r
== WAIT_OBJECT_0
, "should succeed\n");
140 /* event[0] is not signalled */
141 r
= WaitForSingleObject(event
[0], 0);
142 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
144 r
= SignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
145 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
147 /* clear event[1] and check for a timeout */
148 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
149 r
= SignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
150 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
152 CloseHandle(event
[0]);
153 CloseHandle(event
[1]);
156 semaphore
[0] = CreateSemaphoreW( NULL
, 0, 1, NULL
);
157 semaphore
[1] = CreateSemaphoreW( NULL
, 1, 1, NULL
);
158 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
160 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
161 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
163 r
= SignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
164 ok( r
== WAIT_FAILED
, "should fail\n");
166 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
167 ok( r
== FALSE
, "should fail\n");
169 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
170 ok( r
== TRUE
, "should succeed\n");
172 CloseHandle(semaphore
[0]);
173 CloseHandle(semaphore
[1]);
175 /* try a registry key */
176 file
= CreateFileA("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
177 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
178 r
= SignalObjectAndWait(file
, file
, 0, FALSE
);
179 ok( r
== WAIT_FAILED
, "should fail\n");
180 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
184 static void test_mutex(void)
193 SetLastError(0xdeadbeef);
194 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
195 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
196 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
198 SetLastError(0xdeadbeef);
199 hCreated
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
200 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
202 SetLastError(0xdeadbeef);
203 hOpened
= OpenMutexA(0, FALSE
, "WineTestMutex");
205 ok(hOpened
== NULL
, "OpenMutex succeeded\n");
207 ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u\n", GetLastError());
209 SetLastError(0xdeadbeef);
210 hOpened
= OpenMutexA(GENERIC_EXECUTE
, FALSE
, "WineTestMutex");
211 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
212 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
213 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error %d\n", GetLastError());
214 CloseHandle(hOpened
);
216 for(i
=0; i
< 31; i
++)
218 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
219 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
222 SetLastError(0xdeadbeef);
223 hOpened
= OpenMutexA(GENERIC_READ
| GENERIC_WRITE
, FALSE
, "WineTestMutex");
224 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
225 wait_ret
= WaitForSingleObject(hOpened
, INFINITE
);
226 ok(wait_ret
== WAIT_FAILED
, "WaitForSingleObject succeeded\n");
227 CloseHandle(hOpened
);
229 for (i
= 0; i
< 32; i
++)
231 SetLastError(0xdeadbeef);
232 hOpened
= OpenMutexA(0x1 << i
, FALSE
, "WineTestMutex");
235 SetLastError(0xdeadbeef);
236 ret
= ReleaseMutex(hOpened
);
237 ok(ret
, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i
);
238 CloseHandle(hOpened
);
242 if ((1 << i
) == ACCESS_SYSTEM_SECURITY
)
243 todo_wine
ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD
, "wrong error %u, access %x\n", GetLastError(), 1 << i
);
245 todo_wine
ok(GetLastError() == ERROR_ACCESS_DENIED
, "wrong error %u, , access %x\n", GetLastError(), 1 << i
);
246 ReleaseMutex(hCreated
);
252 ok( failed
== 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed
);
254 SetLastError(0xdeadbeef);
255 ret
= ReleaseMutex(hCreated
);
256 ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
257 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
259 /* test case sensitivity */
261 SetLastError(0xdeadbeef);
262 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
263 ok(!hOpened
, "OpenMutex succeeded\n");
264 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
266 SetLastError(0xdeadbeef);
267 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, "winetestmutex");
268 ok(!hOpened
, "OpenMutex succeeded\n");
269 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
271 SetLastError(0xdeadbeef);
272 hOpened
= OpenMutexA(READ_CONTROL
, FALSE
, NULL
);
273 ok(!hOpened
, "OpenMutex succeeded\n");
274 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
276 SetLastError(0xdeadbeef);
277 hOpened
= OpenMutexW(READ_CONTROL
, FALSE
, NULL
);
278 ok(!hOpened
, "OpenMutex succeeded\n");
279 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
281 SetLastError(0xdeadbeef);
282 hOpened
= CreateMutexA(NULL
, FALSE
, "WineTestMutex");
283 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
284 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
285 CloseHandle(hOpened
);
287 SetLastError(0xdeadbeef);
288 hOpened
= CreateMutexA(NULL
, FALSE
, "WINETESTMUTEX");
289 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
290 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
291 CloseHandle(hOpened
);
293 CloseHandle(hCreated
);
296 static void test_slist(void)
302 } item1
, item2
, item3
, *item
;
303 SLIST_HEADER slist_header
;
312 memset(&slist_header
, 0xff, sizeof(slist_header
));
313 InitializeSListHead(&slist_header
);
314 size
= QueryDepthSList(&slist_header
);
315 ok(size
== 0, "Expected size == 0, got %u\n", size
);
317 /* test PushEntry, PopEntry and Flush */
318 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
319 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
320 size
= QueryDepthSList(&slist_header
);
321 ok(size
== 1, "Expected size == 1, got %u\n", size
);
323 entry
= InterlockedPushEntrySList(&slist_header
, &item2
.entry
);
324 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
325 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
326 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
327 size
= QueryDepthSList(&slist_header
);
328 ok(size
== 2, "Expected size == 2, got %u\n", size
);
330 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
331 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
332 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
333 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
334 size
= QueryDepthSList(&slist_header
);
335 ok(size
== 3, "Expected size == 3, got %u\n", size
);
337 entry
= InterlockedPopEntrySList(&slist_header
);
338 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
339 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
340 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
341 size
= QueryDepthSList(&slist_header
);
342 ok(size
== 2, "Expected size == 2, got %u\n", size
);
344 entry
= InterlockedFlushSList(&slist_header
);
345 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
346 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
347 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
348 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
349 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
350 size
= QueryDepthSList(&slist_header
);
351 ok(size
== 0, "Expected size == 0, got %u\n", size
);
352 entry
= InterlockedPopEntrySList(&slist_header
);
353 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
355 /* test RtlInterlockedPushListSList */
356 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
357 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
358 entry
= call_func4(pRtlInterlockedPushListSList
, &slist_header
, &item2
.entry
, &item1
.entry
, 42);
359 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
360 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
361 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
362 size
= QueryDepthSList(&slist_header
);
363 ok(size
== 43, "Expected size == 43, got %u\n", size
);
365 entry
= InterlockedPopEntrySList(&slist_header
);
366 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
367 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
368 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
369 size
= QueryDepthSList(&slist_header
);
370 ok(size
== 42, "Expected size == 42, got %u\n", size
);
372 entry
= InterlockedPopEntrySList(&slist_header
);
373 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
374 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
375 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
376 size
= QueryDepthSList(&slist_header
);
377 ok(size
== 41, "Expected size == 41, got %u\n", size
);
379 entry
= InterlockedPopEntrySList(&slist_header
);
380 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
381 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
382 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
383 size
= QueryDepthSList(&slist_header
);
384 ok(size
== 40, "Expected size == 40, got %u\n", size
);
386 entry
= InterlockedPopEntrySList(&slist_header
);
387 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
388 size
= QueryDepthSList(&slist_header
);
389 ok(size
== 40, "Expected size == 40, got %u\n", size
);
391 entry
= InterlockedFlushSList(&slist_header
);
392 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
393 size
= QueryDepthSList(&slist_header
);
394 ok(size
== 40 || broken(size
== 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size
);
396 entry
= InterlockedPushEntrySList(&slist_header
, &item1
.entry
);
397 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
398 entry
= InterlockedFlushSList(&slist_header
);
399 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
400 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
401 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
402 size
= QueryDepthSList(&slist_header
);
403 ok(size
== 0, "Expected size == 0, got %u\n", size
);
405 /* test RtlInterlockedPushListSListEx */
406 if (pRtlInterlockedPushListSListEx
)
408 entry
= InterlockedPushEntrySList(&slist_header
, &item3
.entry
);
409 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
410 entry
= pRtlInterlockedPushListSListEx(&slist_header
, &item2
.entry
, &item1
.entry
, 42);
411 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
412 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
413 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
414 size
= QueryDepthSList(&slist_header
);
415 ok(size
== 43, "Expected size == 43, got %u\n", size
);
417 entry
= InterlockedFlushSList(&slist_header
);
418 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
419 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
420 ok(item
->value
== 2, "Expected item->value == 2, got %u\n", item
->value
);
421 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
422 ok(item
->value
== 1, "Expected item->value == 1, got %u\n", item
->value
);
423 item
= CONTAINING_RECORD(item
->entry
.Next
, struct item
, entry
);
424 ok(item
->value
== 3, "Expected item->value == 3, got %u\n", item
->value
);
425 size
= QueryDepthSList(&slist_header
);
426 ok(size
== 0, "Expected size == 0, got %u\n", size
);
429 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
431 /* test with a lot of items */
432 for (i
= 0; i
< 65536; i
++)
434 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
436 entry
= InterlockedPushEntrySList(&slist_header
, &item
->entry
);
439 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
440 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
441 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
445 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
447 size
= QueryDepthSList(&slist_header
);
448 ok(size
== ((i
+ 1) & 0xffff), "Expected size == %u, got %u\n", (i
+ 1) & 0xffff, size
);
451 entry
= InterlockedFlushSList(&slist_header
);
452 for (i
= 65536; i
> 0; i
--)
454 ok(entry
!= NULL
, "Expected entry != NULL, got %p\n", entry
);
455 item
= CONTAINING_RECORD(entry
, struct item
, entry
);
456 ok(item
->value
== i
, "Expected item->value == %u, got %u\n", i
, item
->value
);
457 entry
= item
->entry
.Next
;
458 HeapFree(GetProcessHeap(), 0, item
);
460 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
461 size
= QueryDepthSList(&slist_header
);
462 ok(size
== 0, "Expected size == 0, got %u\n", size
);
463 entry
= InterlockedPopEntrySList(&slist_header
);
464 ok(entry
== NULL
, "Expected entry == NULL, got %p\n", entry
);
467 static void test_event(void)
469 HANDLE handle
, handle2
;
470 SECURITY_ATTRIBUTES sa
;
471 SECURITY_DESCRIPTOR sd
;
477 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
478 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
481 sa
.nLength
= sizeof(sa
);
482 sa
.lpSecurityDescriptor
= &sd
;
483 sa
.bInheritHandle
= FALSE
;
485 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
488 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
489 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
492 /* sd with NULL dacl */
493 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
494 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
495 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
498 /* sd with empty dacl */
499 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
500 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
501 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
502 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
505 /* test case sensitivity */
507 SetLastError(0xdeadbeef);
508 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
509 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
510 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
512 SetLastError(0xdeadbeef);
513 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
514 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
515 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
516 CloseHandle( handle2
);
518 SetLastError(0xdeadbeef);
519 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
520 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
521 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
522 CloseHandle( handle2
);
524 SetLastError(0xdeadbeef);
525 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
526 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
527 CloseHandle( handle2
);
529 SetLastError(0xdeadbeef);
530 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
531 ok( !handle2
, "OpenEvent succeeded\n");
532 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
534 SetLastError(0xdeadbeef);
535 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, NULL
);
536 ok( !handle2
, "OpenEvent succeeded\n");
537 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
539 SetLastError(0xdeadbeef);
540 handle2
= OpenEventW( EVENT_ALL_ACCESS
, FALSE
, NULL
);
541 ok( !handle2
, "OpenEvent succeeded\n");
542 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
544 CloseHandle( handle
);
546 /* resource notifications are events too */
548 if (!pCreateMemoryResourceNotification
|| !pQueryMemoryResourceNotification
)
550 trace( "memory resource notifications not supported\n" );
553 handle
= pCreateMemoryResourceNotification( HighMemoryResourceNotification
+ 1 );
554 ok( !handle
, "CreateMemoryResourceNotification succeeded\n" );
555 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
556 ret
= pQueryMemoryResourceNotification( handle
, &val
);
557 ok( !ret
, "QueryMemoryResourceNotification succeeded\n" );
558 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError() );
560 handle
= pCreateMemoryResourceNotification( LowMemoryResourceNotification
);
561 ok( handle
!= 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
562 ret
= WaitForSingleObject( handle
, 10 );
563 ok( ret
== WAIT_OBJECT_0
|| ret
== WAIT_TIMEOUT
, "WaitForSingleObject wrong ret %u\n", ret
);
566 ret
= pQueryMemoryResourceNotification( handle
, &val
);
567 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
568 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
569 ret
= CloseHandle( handle
);
570 ok( ret
, "CloseHandle failed err %u\n", GetLastError() );
572 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
574 ret
= pQueryMemoryResourceNotification( handle
, &val
);
575 ok( ret
, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
576 ok( val
== FALSE
|| val
== TRUE
, "wrong value %u\n", val
);
577 CloseHandle( handle
);
580 static void test_semaphore(void)
582 HANDLE handle
, handle2
;
584 /* test case sensitivity */
586 SetLastError(0xdeadbeef);
587 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
588 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
589 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
591 SetLastError(0xdeadbeef);
592 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
593 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
594 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
595 CloseHandle( handle2
);
597 SetLastError(0xdeadbeef);
598 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
599 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
600 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
601 CloseHandle( handle2
);
603 SetLastError(0xdeadbeef);
604 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
605 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
606 CloseHandle( handle2
);
608 SetLastError(0xdeadbeef);
609 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
610 ok( !handle2
, "OpenSemaphore succeeded\n");
611 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
613 SetLastError(0xdeadbeef);
614 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
615 ok( !handle2
, "OpenSemaphore succeeded\n");
616 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
618 SetLastError(0xdeadbeef);
619 handle2
= OpenSemaphoreW( SEMAPHORE_ALL_ACCESS
, FALSE
, NULL
);
620 ok( !handle2
, "OpenSemaphore succeeded\n");
621 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
623 CloseHandle( handle
);
626 static void test_waitable_timer(void)
628 HANDLE handle
, handle2
;
630 /* test case sensitivity */
632 SetLastError(0xdeadbeef);
633 handle
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
634 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
635 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
637 SetLastError(0xdeadbeef);
638 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
639 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
640 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
641 CloseHandle( handle2
);
643 SetLastError(0xdeadbeef);
644 handle2
= CreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
645 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
646 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
647 CloseHandle( handle2
);
649 SetLastError(0xdeadbeef);
650 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
651 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
652 CloseHandle( handle2
);
654 SetLastError(0xdeadbeef);
655 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
656 ok( !handle2
, "OpenWaitableTimer succeeded\n");
657 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
659 SetLastError(0xdeadbeef);
660 handle2
= OpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, NULL
);
661 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
662 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
664 SetLastError(0xdeadbeef);
665 handle2
= OpenWaitableTimerW( TIMER_ALL_ACCESS
, FALSE
, NULL
);
666 ok( !handle2
, "OpenWaitableTimer failed with error %d\n", GetLastError());
667 ok( GetLastError() == ERROR_INVALID_PARAMETER
, "wrong error %u\n", GetLastError());
669 CloseHandle( handle
);
672 static HANDLE sem
= 0;
674 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
676 ReleaseSemaphore(sem
, 1, NULL
);
679 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
681 static void test_iocp_callback(void)
683 char temp_path
[MAX_PATH
];
684 char filename
[MAX_PATH
];
687 static const char prefix
[] = "pfx";
689 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
691 const char *buffer
= "12345678123456781234567812345678";
692 OVERLAPPED overlapped
;
694 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
695 if(!p_BindIoCompletionCallback
) {
696 win_skip("BindIoCompletionCallback not found in this DLL\n");
700 sem
= CreateSemaphoreW(NULL
, 0, 1, NULL
);
701 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
703 ret
= GetTempPathA(MAX_PATH
, temp_path
);
704 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
705 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
707 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
708 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
710 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
711 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
712 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
714 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
715 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
716 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
718 ret
= CloseHandle(hFile
);
719 ok( ret
, "CloseHandle: error %d\n", GetLastError());
720 ret
= DeleteFileA(filename
);
721 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
723 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
724 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
725 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
727 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
728 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
730 memset(&overlapped
, 0, sizeof(overlapped
));
731 retb
= WriteFile(hFile
, buffer
, 4, &bytesWritten
, &overlapped
);
732 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
734 ret
= WaitForSingleObject(sem
, 5000);
735 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
738 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
739 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
740 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
741 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
742 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
743 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
745 ret
= CloseHandle(hFile
);
746 ok( ret
, "CloseHandle: error %d\n", GetLastError());
747 ret
= DeleteFileA(filename
);
748 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
750 /* win2k3 requires the Flags parameter to be zero */
751 SetLastError(0xdeadbeef);
752 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
753 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
754 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
755 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
757 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
758 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
760 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
761 ret
= CloseHandle(hFile
);
762 ok( ret
, "CloseHandle: error %d\n", GetLastError());
763 ret
= DeleteFileA(filename
);
764 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
766 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
767 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
768 ok(GetLastError() == ERROR_INVALID_HANDLE
||
769 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
770 "Last error is %d\n", GetLastError());
773 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
776 ok(timedOut
, "Timer callbacks should always time out\n");
780 struct timer_queue_data1
787 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
789 struct timer_queue_data1
*d
= p
;
790 ok(timedOut
, "Timer callbacks should always time out\n");
791 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
794 SetLastError(0xdeadbeef);
795 /* Note, XP SP2 does *not* do any deadlock checking, so passing
796 INVALID_HANDLE_VALUE here will just hang. */
797 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
798 ok(!ret
, "DeleteTimerQueueTimer\n");
799 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
803 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
805 struct timer_queue_data1
*d
= p
;
806 ok(timedOut
, "Timer callbacks should always time out\n");
807 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
809 /* Basically kill the timer since it won't have time to run
811 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
812 ok(ret
, "ChangeTimerQueueTimer\n");
816 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
818 struct timer_queue_data1
*d
= p
;
819 ok(timedOut
, "Timer callbacks should always time out\n");
822 /* This tests whether a timer gets flagged for deletion before
823 or after the callback runs. If we start this timer with a
824 period of zero (run once), then ChangeTimerQueueTimer will
825 fail if the timer is already flagged. Hence we really run
826 only once. Otherwise we will run multiple times. */
827 BOOL ret
= ChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
828 ok(ret
, "ChangeTimerQueueTimer\n");
833 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
835 DWORD_PTR delay
= (DWORD_PTR
) p
;
836 ok(timedOut
, "Timer callbacks should always time out\n");
841 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
843 struct timer_queue_data1
*d
= p
;
844 ok(timedOut
, "Timer callbacks should always time out\n");
845 /* This tests an original implementation bug where a deleted timer may get
846 to run, but it is tricky to set up. */
847 if (d
->q
&& d
->num_calls
++ == 0)
849 /* First run: delete ourselves, then insert and remove a timer
850 that goes in front of us in the sorted timeout list. Once
851 removed, we will still timeout at the faster timer's due time,
852 but this should be a no-op if we are bug-free. There should
853 not be a second run. We can test the value of num_calls later. */
857 /* The delete will pend while we are in this callback. */
858 SetLastError(0xdeadbeef);
859 ret
= DeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
860 ok(!ret
, "DeleteTimerQueueTimer\n");
861 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
863 ret
= CreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
864 ok(ret
, "CreateTimerQueueTimer\n");
865 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
867 ret
= DeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
868 ok(ret
, "DeleteTimerQueueTimer\n");
870 /* Now we stay alive by hanging around in the callback. */
875 static void test_timer_queue(void)
877 HANDLE q
, t0
, t1
, t2
, t3
, t4
, t5
;
878 int n0
, n1
, n2
, n3
, n4
, n5
;
879 struct timer_queue_data1 d1
, d2
, d3
, d4
;
883 /* Test asynchronous deletion of the queue. */
884 q
= CreateTimerQueue();
885 ok(q
!= NULL
, "CreateTimerQueue\n");
887 SetLastError(0xdeadbeef);
888 ret
= DeleteTimerQueueEx(q
, NULL
);
889 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
890 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
893 /* Test synchronous deletion of the queue and running timers. */
894 q
= CreateTimerQueue();
895 ok(q
!= NULL
, "CreateTimerQueue\n");
900 ret
= CreateTimerQueueTimer(&t0
, q
, timer_queue_cb1
, &n0
, 0, 300, 0);
901 ok(ret
, "CreateTimerQueueTimer\n");
902 ok(t0
!= NULL
, "CreateTimerQueueTimer\n");
903 ret0
= DeleteTimerQueueTimer(q
, t0
, NULL
);
904 ok((!ret0
&& GetLastError() == ERROR_IO_PENDING
) ||
905 broken(ret0
), /* Win 2000 & XP & 2003 */
906 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0
, GetLastError());
911 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0, 0, 0);
912 ok(ret
, "CreateTimerQueueTimer\n");
913 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
918 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0, 100, 0);
919 ok(ret
, "CreateTimerQueueTimer\n");
920 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
925 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0, 10, 0);
926 ok(ret
, "CreateTimerQueueTimer\n");
927 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
929 /* Start really late (it won't start). */
932 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000, 10, 0);
933 ok(ret
, "CreateTimerQueueTimer\n");
934 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
936 /* Start soon, but delay so long it won't run again. */
939 ret
= CreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0, 10000, 0);
940 ok(ret
, "CreateTimerQueueTimer\n");
941 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
943 /* Give them a chance to do some work. */
946 /* Test deleting a once-only timer. */
947 ret
= DeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
948 ok(ret
, "DeleteTimerQueueTimer\n");
950 /* A periodic timer. */
951 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
952 ok(ret
, "DeleteTimerQueueTimer\n");
954 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
955 ok(ret
, "DeleteTimerQueueEx\n");
957 ok(n0
== 1 || broken(ret0
&& n0
== 0), "Timer callback 0 expected 1 got %d\n", n0
);
958 ok(n1
== 1, "Timer callback 1 expected 1 got %d\n", n1
);
959 ok(n2
< n3
, "Timer callback 2 & 3 expected %d < %d\n", n2
, n3
);
960 ok(n4
== 0, "Timer callback 4 expected 0 got %d\n", n4
);
961 ok(n5
== 1, "Timer callback 5 expected 1 got %d\n", n5
);
963 /* Test synchronous deletion of the timer/queue with event trigger. */
964 e
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
965 et1
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
966 et2
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
967 if (!e
|| !et1
|| !et2
)
969 skip("Failed to create timer queue descruction event\n");
973 q
= CreateTimerQueue();
974 ok(q
!= NULL
, "CreateTimerQueue\n");
976 /* Run once and finish quickly (should be done when we delete it). */
978 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
979 ok(ret
, "CreateTimerQueueTimer\n");
980 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
982 /* Run once and finish slowly (shouldn't be done when we delete it). */
984 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
985 ok(ret
, "CreateTimerQueueTimer\n");
986 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
988 /* Run once and finish quickly (should be done when we delete it). */
990 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
991 ok(ret
, "CreateTimerQueueTimer\n");
992 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
994 /* Run once and finish slowly (shouldn't be done when we delete it). */
996 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0, 0, 0);
997 ok(ret
, "CreateTimerQueueTimer\n");
998 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1000 /* Give them a chance to start. */
1003 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1004 even if the timer is finished. */
1005 SetLastError(0xdeadbeef);
1006 ret
= DeleteTimerQueueTimer(q
, t1
, NULL
);
1007 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1008 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1011 SetLastError(0xdeadbeef);
1012 ret
= DeleteTimerQueueTimer(q
, t2
, NULL
);
1013 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1014 ok(GetLastError() == ERROR_IO_PENDING
,
1015 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1018 SetLastError(0xdeadbeef);
1019 ret
= DeleteTimerQueueTimer(q
, t3
, et1
);
1020 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1021 ok(GetLastError() == 0xdeadbeef,
1022 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
1024 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
1025 "Timer destruction event not triggered\n");
1027 SetLastError(0xdeadbeef);
1028 ret
= DeleteTimerQueueTimer(q
, t4
, et2
);
1029 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
1030 ok(GetLastError() == ERROR_IO_PENDING
,
1031 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1033 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
1034 "Timer destruction event not triggered\n");
1036 SetLastError(0xdeadbeef);
1037 ret
= DeleteTimerQueueEx(q
, e
);
1038 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1039 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1041 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
1042 "Queue destruction event not triggered\n");
1045 /* Test deleting/changing a timer in execution. */
1046 q
= CreateTimerQueue();
1047 ok(q
!= NULL
, "CreateTimerQueue\n");
1049 /* Test changing a once-only timer before it fires (this is allowed,
1050 whereas after it fires you cannot). */
1052 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000, 0, 0);
1053 ok(ret
, "CreateTimerQueueTimer\n");
1054 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1055 ret
= ChangeTimerQueueTimer(q
, t1
, 0, 0);
1056 ok(ret
, "ChangeTimerQueueTimer\n");
1062 ret
= CreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10, 10, 0);
1064 ok(ret
, "CreateTimerQueueTimer\n");
1065 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1071 ret
= CreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10, 10, 0);
1073 ok(ret
, "CreateTimerQueueTimer\n");
1074 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
1079 ret
= CreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10, 0, 0);
1081 ok(ret
, "CreateTimerQueueTimer\n");
1082 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
1086 ret
= DeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
1087 ok(ret
, "DeleteTimerQueueEx\n");
1088 ok(n1
== 1, "ChangeTimerQueueTimer\n");
1089 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
1090 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
1091 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
1093 /* Test an obscure bug that was in the original implementation. */
1094 q
= CreateTimerQueue();
1095 ok(q
!= NULL
, "CreateTimerQueue\n");
1097 /* All the work is done in the callback. */
1101 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100, 100, WT_EXECUTELONGFUNCTION
);
1103 ok(ret
, "CreateTimerQueueTimer\n");
1104 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1108 SetLastError(0xdeadbeef);
1109 ret
= DeleteTimerQueueEx(q
, NULL
);
1110 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1111 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1113 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
1115 /* Test functions on the default timer queue. */
1118 ret
= CreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1119 ok(ret
, "CreateTimerQueueTimer, default queue\n");
1120 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
1122 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1123 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
1125 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1126 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
1128 /* Try mixing default and non-default queues. Apparently this works. */
1129 q
= CreateTimerQueue();
1130 ok(q
!= NULL
, "CreateTimerQueue\n");
1134 ret
= CreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000, 1000, 0);
1135 ok(ret
, "CreateTimerQueueTimer\n");
1136 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
1140 ret
= CreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000, 1000, 0);
1141 ok(ret
, "CreateTimerQueueTimer\n");
1142 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
1144 ret
= ChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
1145 ok(ret
, "ChangeTimerQueueTimer\n");
1147 ret
= ChangeTimerQueueTimer(q
, t2
, 2000, 2000);
1148 ok(ret
, "ChangeTimerQueueTimer\n");
1150 ret
= DeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
1151 ok(ret
, "DeleteTimerQueueTimer\n");
1153 ret
= DeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
1154 ok(ret
, "DeleteTimerQueueTimer\n");
1156 /* Try to delete the default queue? In any case: not allowed. */
1157 SetLastError(0xdeadbeef);
1158 ret
= DeleteTimerQueueEx(NULL
, NULL
);
1159 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
1160 ok(GetLastError() == ERROR_INVALID_HANDLE
,
1161 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1164 SetLastError(0xdeadbeef);
1165 ret
= DeleteTimerQueueEx(q
, NULL
);
1166 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
1167 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1171 static HANDLE
modify_handle(HANDLE handle
, DWORD modify
)
1173 DWORD tmp
= HandleToULong(handle
);
1175 return ULongToHandle(tmp
);
1178 static void test_WaitForSingleObject(void)
1180 HANDLE signaled
, nonsignaled
, invalid
;
1181 LARGE_INTEGER timeout
;
1185 signaled
= CreateEventW(NULL
, TRUE
, TRUE
, NULL
);
1186 nonsignaled
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
1187 invalid
= (HANDLE
) 0xdeadbee0;
1189 /* invalid handle with different values for lower 2 bits */
1190 SetLastError(0xdeadbeef);
1191 ret
= WaitForSingleObject(invalid
, 0);
1192 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1193 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1195 SetLastError(0xdeadbeef);
1196 ret
= WaitForSingleObject(modify_handle(invalid
, 1), 0);
1197 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1198 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1200 SetLastError(0xdeadbeef);
1201 ret
= WaitForSingleObject(modify_handle(invalid
, 2), 0);
1202 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1203 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1205 SetLastError(0xdeadbeef);
1206 ret
= WaitForSingleObject(modify_handle(invalid
, 3), 0);
1207 ok(ret
== WAIT_FAILED
, "expected WAIT_FAILED, got %d\n", ret
);
1208 ok(GetLastError() == ERROR_INVALID_HANDLE
, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1210 /* valid handle with different values for lower 2 bits */
1211 SetLastError(0xdeadbeef);
1212 ret
= WaitForSingleObject(nonsignaled
, 0);
1213 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1214 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1216 SetLastError(0xdeadbeef);
1217 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 1), 0);
1218 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1219 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1221 SetLastError(0xdeadbeef);
1222 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 2), 0);
1223 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1224 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1226 SetLastError(0xdeadbeef);
1227 ret
= WaitForSingleObject(modify_handle(nonsignaled
, 3), 0);
1228 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %d\n", ret
);
1229 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1231 /* valid handle with different values for lower 2 bits */
1232 SetLastError(0xdeadbeef);
1233 ret
= WaitForSingleObject(signaled
, 0);
1234 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1235 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1237 SetLastError(0xdeadbeef);
1238 ret
= WaitForSingleObject(modify_handle(signaled
, 1), 0);
1239 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1240 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1242 SetLastError(0xdeadbeef);
1243 ret
= WaitForSingleObject(modify_handle(signaled
, 2), 0);
1244 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1245 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1247 SetLastError(0xdeadbeef);
1248 ret
= WaitForSingleObject(modify_handle(signaled
, 3), 0);
1249 ok(ret
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %d\n", ret
);
1250 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1252 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1253 ret
= WaitForSingleObject(GetCurrentProcess(), 100);
1254 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1256 ret
= WaitForSingleObject(GetCurrentThread(), 100);
1257 ok(ret
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", ret
);
1259 timeout
.QuadPart
= -1000000;
1260 status
= pNtWaitForSingleObject(GetCurrentProcess(), FALSE
, &timeout
);
1261 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1263 timeout
.QuadPart
= -1000000;
1264 status
= pNtWaitForSingleObject(GetCurrentThread(), FALSE
, &timeout
);
1265 ok(status
== STATUS_TIMEOUT
, "expected STATUS_TIMEOUT, got %08x\n", status
);
1267 CloseHandle(signaled
);
1268 CloseHandle(nonsignaled
);
1271 static void test_WaitForMultipleObjects(void)
1273 LARGE_INTEGER timeout
;
1277 HANDLE maxevents
[MAXIMUM_WAIT_OBJECTS
];
1279 /* create the maximum number of events and make sure
1280 * we can wait on that many */
1281 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1283 maxevents
[i
] = CreateEventW(NULL
, i
==0, TRUE
, NULL
);
1284 ok( maxevents
[i
] != 0, "should create enough events\n");
1287 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1288 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1289 ok( r
== WAIT_OBJECT_0
, "should signal lowest handle first, got %d\n", r
);
1290 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1291 ok( r
== WAIT_OBJECT_0
, "should signal handle #0 first, got %d\n", r
);
1292 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1293 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1295 /* the lowest index is checked first and remaining events are untouched */
1296 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, FALSE
, 0);
1297 ok( r
== WAIT_OBJECT_0
+i
, "should signal handle #%d first, got %d\n", i
, r
);
1300 /* run same test with Nt* call */
1301 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1302 SetEvent(maxevents
[i
]);
1304 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1305 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1306 ok(status
== STATUS_WAIT_0
, "should signal lowest handle first, got %08x\n", status
);
1307 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1308 ok(status
== STATUS_WAIT_0
, "should signal handle #0 first, got %08x\n", status
);
1309 ok(ResetEvent(maxevents
[0]), "ResetEvent\n");
1310 for (i
=1; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1312 /* the lowest index is checked first and remaining events are untouched */
1313 status
= pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, TRUE
, FALSE
, NULL
);
1314 ok(status
== STATUS_WAIT_0
+ i
, "should signal handle #%d first, got %08x\n", i
, status
);
1317 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
1318 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
1320 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1321 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1322 maxevents
[0] = GetCurrentProcess();
1323 SetLastError(0xdeadbeef);
1324 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1325 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1326 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1327 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1329 maxevents
[0] = GetCurrentThread();
1330 SetLastError(0xdeadbeef);
1331 r
= WaitForMultipleObjects(1, maxevents
, FALSE
, 100);
1332 todo_wine
ok(r
== WAIT_FAILED
, "expected WAIT_FAILED, got %u\n", r
);
1333 todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE
,
1334 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError());
1336 timeout
.QuadPart
= -1000000;
1337 maxevents
[0] = GetCurrentProcess();
1338 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1339 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1341 timeout
.QuadPart
= -1000000;
1342 maxevents
[0] = GetCurrentThread();
1343 status
= pNtWaitForMultipleObjects(1, maxevents
, TRUE
, FALSE
, &timeout
);
1344 todo_wine
ok(status
== STATUS_INVALID_HANDLE
, "expected STATUS_INVALID_HANDLE, got %08x\n", status
);
1347 static BOOL g_initcallback_ret
, g_initcallback_called
;
1348 static void *g_initctxt
;
1350 static BOOL CALLBACK
initonce_callback(INIT_ONCE
*initonce
, void *parameter
, void **ctxt
)
1352 g_initcallback_called
= TRUE
;
1353 /* zero bit set means here that initialization is taking place - initialization locked */
1354 ok(g_initctxt
== *ctxt
, "got wrong context value %p, expected %p\n", *ctxt
, g_initctxt
);
1355 ok(initonce
->Ptr
== (void*)0x1, "got %p\n", initonce
->Ptr
);
1356 ok(parameter
== (void*)0xdeadbeef, "got wrong parameter\n");
1357 return g_initcallback_ret
;
1360 static void test_initonce(void)
1365 if (!pInitOnceInitialize
|| !pInitOnceExecuteOnce
)
1367 win_skip("one-time initialization API not supported\n");
1371 /* blocking initialization with callback */
1372 initonce
.Ptr
= (void*)0xdeadbeef;
1373 pInitOnceInitialize(&initonce
);
1374 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1376 /* initialisation completed successfully */
1377 g_initcallback_ret
= TRUE
;
1379 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1380 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1381 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1382 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1383 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1385 /* so it's been called already so won't be called again */
1387 g_initcallback_called
= FALSE
;
1388 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1389 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1390 ok(initonce
.Ptr
== (void*)0x2, "got %p\n", initonce
.Ptr
);
1391 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1392 ok(!g_initcallback_called
, "got %d\n", g_initcallback_called
);
1394 pInitOnceInitialize(&initonce
);
1395 g_initcallback_called
= FALSE
;
1396 /* 2 lower order bits should never be used, you'll get a crash in result */
1397 g_initctxt
= (void*)0xFFFFFFF0;
1398 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1399 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1400 ok(initonce
.Ptr
== (void*)0xFFFFFFF2, "got %p\n", initonce
.Ptr
);
1401 ok(g_initctxt
== (void*)0xFFFFFFF0, "got %p\n", g_initctxt
);
1402 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1404 /* callback failed */
1405 g_initcallback_ret
= FALSE
;
1406 g_initcallback_called
= FALSE
;
1408 pInitOnceInitialize(&initonce
);
1409 SetLastError( 0xdeadbeef );
1410 ret
= pInitOnceExecuteOnce(&initonce
, initonce_callback
, (void*)0xdeadbeef, &g_initctxt
);
1411 ok(!ret
&& GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret
, GetLastError());
1412 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1413 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1414 ok(g_initcallback_called
, "got %d\n", g_initcallback_called
);
1416 /* blocking initialization without a callback */
1417 pInitOnceInitialize(&initonce
);
1420 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1421 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1422 ok(pending
, "got %d\n", pending
);
1423 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1424 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1425 /* another attempt to begin initialization with block a single thread */
1429 SetLastError( 0xdeadbeef );
1430 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1431 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1432 ok(pending
== 0xf, "got %d\n", pending
);
1433 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1434 ok(g_initctxt
== NULL
, "got %p\n", g_initctxt
);
1436 g_initctxt
= (void*)0xdeadbee0;
1437 SetLastError( 0xdeadbeef );
1438 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, g_initctxt
);
1439 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1440 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1442 /* once failed already */
1443 g_initctxt
= (void*)0xdeadbee0;
1444 ret
= pInitOnceComplete(&initonce
, 0, g_initctxt
);
1445 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1446 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1448 pInitOnceInitialize(&initonce
);
1449 SetLastError( 0xdeadbeef );
1450 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1451 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1452 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1454 SetLastError( 0xdeadbeef );
1455 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1456 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1457 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1459 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1460 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1461 ok(pending
, "got %d\n", pending
);
1462 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1464 SetLastError( 0xdeadbeef );
1465 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1466 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1468 SetLastError( 0xdeadbeef );
1469 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1470 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1471 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1473 SetLastError( 0xdeadbeef );
1474 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbeef);
1475 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1476 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1478 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1479 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1480 ok(initonce
.Ptr
== NULL
, "got %p\n", initonce
.Ptr
);
1482 pInitOnceInitialize(&initonce
);
1483 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1484 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1485 ok(pending
, "got %d\n", pending
);
1486 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1488 SetLastError( 0xdeadbeef );
1489 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1490 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1492 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1493 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1494 ok(pending
, "got %d\n", pending
);
1495 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1497 SetLastError( 0xdeadbeef );
1498 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
, NULL
);
1499 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1500 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1502 SetLastError( 0xdeadbeef );
1503 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1504 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1505 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1507 SetLastError( 0xdeadbeef );
1508 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbeef);
1509 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1510 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1512 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1513 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1514 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1516 SetLastError( 0xdeadbeef );
1517 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_INIT_FAILED
| INIT_ONCE_ASYNC
, NULL
);
1518 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1519 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1521 pInitOnceInitialize(&initonce
);
1522 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1523 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1524 ok(pending
, "got %d\n", pending
);
1525 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1527 /* test INIT_ONCE_CHECK_ONLY */
1529 pInitOnceInitialize(&initonce
);
1530 SetLastError( 0xdeadbeef );
1531 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1532 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1533 SetLastError( 0xdeadbeef );
1534 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1535 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1537 ret
= pInitOnceBeginInitialize(&initonce
, 0, &pending
, &g_initctxt
);
1538 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1539 ok(pending
, "got %d\n", pending
);
1540 ok(initonce
.Ptr
== (void*)1, "got %p\n", initonce
.Ptr
);
1542 SetLastError( 0xdeadbeef );
1543 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1544 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1545 SetLastError( 0xdeadbeef );
1546 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1547 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1549 ret
= pInitOnceComplete(&initonce
, 0, (void *)0xdeadbee0);
1550 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1551 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1553 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1554 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1555 ok(!pending
, "got %d\n", pending
);
1556 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1557 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1559 SetLastError( 0xdeadbeef );
1560 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1561 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1563 pInitOnceInitialize(&initonce
);
1564 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1565 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1566 ok(pending
, "got %d\n", pending
);
1567 ok(initonce
.Ptr
== (void*)3, "got %p\n", initonce
.Ptr
);
1569 SetLastError( 0xdeadbeef );
1570 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1571 ok(!ret
&& GetLastError() == ERROR_GEN_FAILURE
, "wrong ret %d err %u\n", ret
, GetLastError());
1572 SetLastError( 0xdeadbeef );
1573 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1574 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1576 ret
= pInitOnceComplete(&initonce
, INIT_ONCE_ASYNC
, (void *)0xdeadbee0);
1577 ok(ret
, "wrong ret %d err %u\n", ret
, GetLastError());
1578 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1580 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
, &pending
, &g_initctxt
);
1581 ok(ret
, "got wrong ret value %d err %u\n", ret
, GetLastError());
1582 ok(!pending
, "got %d\n", pending
);
1583 ok(initonce
.Ptr
== (void*)0xdeadbee2, "got %p\n", initonce
.Ptr
);
1584 ok(g_initctxt
== (void*)0xdeadbee0, "got %p\n", initonce
.Ptr
);
1586 SetLastError( 0xdeadbeef );
1587 ret
= pInitOnceBeginInitialize(&initonce
, INIT_ONCE_CHECK_ONLY
|INIT_ONCE_ASYNC
, &pending
, &g_initctxt
);
1588 ok(!ret
&& GetLastError() == ERROR_INVALID_PARAMETER
, "wrong ret %d err %u\n", ret
, GetLastError());
1591 static CONDITION_VARIABLE buffernotempty
= CONDITION_VARIABLE_INIT
;
1592 static CONDITION_VARIABLE buffernotfull
= CONDITION_VARIABLE_INIT
;
1593 static CRITICAL_SECTION buffercrit
;
1594 static BOOL condvar_stop
= FALSE
, condvar_sleeperr
= FALSE
;
1595 static LONG bufferlen
,totalproduced
,totalconsumed
;
1596 static LONG condvar_producer_sleepcnt
,condvar_consumer_sleepcnt
;
1598 #define BUFFER_SIZE 5
1600 static DWORD WINAPI
condvar_producer(LPVOID x
) {
1601 DWORD sleepinterval
= 5;
1604 Sleep(sleepinterval
);
1605 if (sleepinterval
> 1)
1608 EnterCriticalSection(&buffercrit
);
1609 while ((bufferlen
== BUFFER_SIZE
) && !condvar_stop
) {
1610 condvar_producer_sleepcnt
++;
1611 if (!pSleepConditionVariableCS(&buffernotfull
, &buffercrit
, sleepinterval
)) {
1612 if (GetLastError() != ERROR_TIMEOUT
)
1613 condvar_sleeperr
= TRUE
;
1617 LeaveCriticalSection(&buffercrit
);
1622 LeaveCriticalSection(&buffercrit
);
1623 pWakeConditionVariable(&buffernotempty
);
1628 static DWORD WINAPI
condvar_consumer(LPVOID x
) {
1629 DWORD
*cnt
= (DWORD
*)x
;
1630 DWORD sleepinterval
= 1;
1633 EnterCriticalSection(&buffercrit
);
1634 while ((bufferlen
== 0) && !condvar_stop
) {
1635 condvar_consumer_sleepcnt
++;
1636 if (!pSleepConditionVariableCS (&buffernotempty
, &buffercrit
, sleepinterval
)) {
1637 if (GetLastError() != ERROR_TIMEOUT
)
1638 condvar_sleeperr
= TRUE
;
1641 if (condvar_stop
&& (bufferlen
== 0)) {
1642 LeaveCriticalSection(&buffercrit
);
1648 LeaveCriticalSection(&buffercrit
);
1649 pWakeConditionVariable(&buffernotfull
);
1650 Sleep(sleepinterval
);
1651 if (sleepinterval
< 5) sleepinterval
+= 1;
1656 static void test_condvars_consumer_producer(void)
1658 HANDLE hp1
,hp2
,hp3
,hc1
,hc2
,hc3
;
1660 DWORD cnt1
,cnt2
,cnt3
;
1662 if (!pInitializeConditionVariable
) {
1663 /* function is not yet in XP, only in newer Windows */
1664 win_skip("no condition variable support.\n");
1668 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1670 /* If we have static initialized condition variables, InitializeConditionVariable
1671 * is not strictly necessary.
1672 * pInitializeConditionVariable(&buffernotfull);
1674 pInitializeConditionVariable(&buffernotempty
);
1675 InitializeCriticalSection(&buffercrit
);
1677 /* Larger Test: consumer/producer example */
1679 bufferlen
= totalproduced
= totalconsumed
= cnt1
= cnt2
= cnt3
= 0;
1681 hp1
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1682 hp2
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1683 hp3
= CreateThread(NULL
, 0, condvar_producer
, NULL
, 0, &dummy
);
1684 hc1
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt1
, 0, &dummy
);
1685 hc2
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt2
, 0, &dummy
);
1686 hc3
= CreateThread(NULL
, 0, condvar_consumer
, (PVOID
)&cnt3
, 0, &dummy
);
1688 /* Limit run to 0.5 seconds. */
1691 /* tear down start */
1692 condvar_stop
= TRUE
;
1694 /* final wake up call */
1695 pWakeAllConditionVariable (&buffernotfull
);
1696 pWakeAllConditionVariable (&buffernotempty
);
1698 /* (mostly an implementation detail)
1699 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1702 WaitForSingleObject(hp1
, 1000);
1703 WaitForSingleObject(hp2
, 1000);
1704 WaitForSingleObject(hp3
, 1000);
1705 WaitForSingleObject(hc1
, 1000);
1706 WaitForSingleObject(hc2
, 1000);
1707 WaitForSingleObject(hc3
, 1000);
1709 ok(totalconsumed
== totalproduced
,
1710 "consumed %d != produced %d\n", totalconsumed
, totalproduced
);
1711 ok (!condvar_sleeperr
, "error occurred during SleepConditionVariableCS\n");
1713 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1714 * one consumer does not get anything to do is possible. */
1715 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced
, cnt1
, cnt2
, cnt3
);
1716 /* The sleeps of the producer or consumer should not go above 100* produced count,
1717 * otherwise the implementation does not sleep correctly. But yet again, this is
1718 * not hard defined. */
1719 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt
, condvar_consumer_sleepcnt
);
1722 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1723 static DWORD condvar_seq
= 0;
1724 static CONDITION_VARIABLE aligned_cv
;
1725 static CRITICAL_SECTION condvar_crit
;
1726 static SRWLOCK condvar_srwlock
;
1728 #include "pshpack1.h"
1732 CONDITION_VARIABLE cv
;
1734 #include "poppack.h"
1736 /* Sequence of wake/sleep to check boundary conditions:
1738 * 1: producer emits a WakeConditionVariable without consumer waiting.
1739 * 2: consumer sleeps without a wake expecting timeout
1740 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1741 * 4: consumer sleeps without a wake expecting timeout
1742 * 5: a wake is handed to a SleepConditionVariableCS
1743 * 6: a wakeall is handed to a SleepConditionVariableCS
1744 * 7: sleep after above should timeout
1745 * 8: wake with crit section locked into the sleep timeout
1747 * the following tests will only be executed if InitializeSRWLock is available
1749 * 9: producer (exclusive) wakes up consumer (exclusive)
1750 * 10: producer (exclusive) wakes up consumer (shared)
1751 * 11: producer (shared) wakes up consumer (exclusive)
1752 * 12: producer (shared) wakes up consumer (shared)
1755 static DWORD WINAPI
condvar_base_producer(void *arg
)
1757 CONDITION_VARIABLE
*cv
= arg
;
1759 while (condvar_seq
< 1) Sleep(1);
1761 pWakeConditionVariable(cv
);
1764 while (condvar_seq
< 3) Sleep(1);
1765 pWakeAllConditionVariable(cv
);
1768 while (condvar_seq
< 5) Sleep(1);
1769 EnterCriticalSection (&condvar_crit
);
1770 pWakeConditionVariable(cv
);
1771 LeaveCriticalSection (&condvar_crit
);
1772 while (condvar_seq
< 6) Sleep(1);
1773 EnterCriticalSection (&condvar_crit
);
1774 pWakeAllConditionVariable(cv
);
1775 LeaveCriticalSection (&condvar_crit
);
1777 while (condvar_seq
< 8) Sleep(1);
1778 EnterCriticalSection (&condvar_crit
);
1779 pWakeConditionVariable(cv
);
1781 LeaveCriticalSection (&condvar_crit
);
1783 /* skip over remaining tests if InitializeSRWLock is not available */
1784 if (!pInitializeSRWLock
)
1787 while (condvar_seq
< 9) Sleep(1);
1788 pAcquireSRWLockExclusive(&condvar_srwlock
);
1789 pWakeConditionVariable(cv
);
1790 pReleaseSRWLockExclusive(&condvar_srwlock
);
1792 while (condvar_seq
< 10) Sleep(1);
1793 pAcquireSRWLockExclusive(&condvar_srwlock
);
1794 pWakeConditionVariable(cv
);
1795 pReleaseSRWLockExclusive(&condvar_srwlock
);
1797 while (condvar_seq
< 11) Sleep(1);
1798 pAcquireSRWLockShared(&condvar_srwlock
);
1799 pWakeConditionVariable(cv
);
1800 pReleaseSRWLockShared(&condvar_srwlock
);
1802 while (condvar_seq
< 12) Sleep(1);
1803 Sleep(50); /* ensure that consumer waits for cond variable */
1804 pAcquireSRWLockShared(&condvar_srwlock
);
1805 pWakeConditionVariable(cv
);
1806 pReleaseSRWLockShared(&condvar_srwlock
);
1811 static DWORD WINAPI
condvar_base_consumer(void *arg
)
1813 CONDITION_VARIABLE
*cv
= arg
;
1816 while (condvar_seq
< 2) Sleep(1);
1818 /* wake was emitted, but we were not sleeping */
1819 EnterCriticalSection (&condvar_crit
);
1820 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 10);
1821 LeaveCriticalSection (&condvar_crit
);
1822 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1823 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1826 while (condvar_seq
< 4) Sleep(1);
1828 /* wake all was emitted, but we were not sleeping */
1829 EnterCriticalSection (&condvar_crit
);
1830 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 10);
1831 LeaveCriticalSection (&condvar_crit
);
1832 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1833 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1835 EnterCriticalSection (&condvar_crit
);
1837 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 200);
1838 LeaveCriticalSection (&condvar_crit
);
1839 ok (ret
, "SleepConditionVariableCS should return TRUE on good wake\n");
1841 EnterCriticalSection (&condvar_crit
);
1843 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 200);
1844 LeaveCriticalSection (&condvar_crit
);
1845 ok (ret
, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1848 EnterCriticalSection (&condvar_crit
);
1849 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 10);
1850 LeaveCriticalSection (&condvar_crit
);
1851 ok (!ret
, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1852 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1854 EnterCriticalSection (&condvar_crit
);
1856 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 20);
1857 LeaveCriticalSection (&condvar_crit
);
1858 ok (ret
, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1860 /* skip over remaining tests if InitializeSRWLock is not available */
1861 if (!pInitializeSRWLock
)
1863 win_skip("no srw lock support.\n");
1864 condvar_seq
= 13; /* end */
1868 pAcquireSRWLockExclusive(&condvar_srwlock
);
1870 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 200, 0);
1871 pReleaseSRWLockExclusive(&condvar_srwlock
);
1872 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1874 pAcquireSRWLockShared(&condvar_srwlock
);
1876 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1877 pReleaseSRWLockShared(&condvar_srwlock
);
1878 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1880 pAcquireSRWLockExclusive(&condvar_srwlock
);
1882 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 200, 0);
1883 pReleaseSRWLockExclusive(&condvar_srwlock
);
1884 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1886 pAcquireSRWLockShared(&condvar_srwlock
);
1888 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 200, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1889 pReleaseSRWLockShared(&condvar_srwlock
);
1890 ok (ret
, "pSleepConditionVariableSRW should return TRUE on good wake\n");
1896 static void test_condvars_base(RTL_CONDITION_VARIABLE
*cv
)
1902 if (!pInitializeConditionVariable
) {
1903 /* function is not yet in XP, only in newer Windows */
1904 win_skip("no condition variable support.\n");
1908 InitializeCriticalSection (&condvar_crit
);
1910 if (pInitializeSRWLock
)
1911 pInitializeSRWLock(&condvar_srwlock
);
1913 EnterCriticalSection (&condvar_crit
);
1914 ret
= pSleepConditionVariableCS(cv
, &condvar_crit
, 10);
1915 LeaveCriticalSection (&condvar_crit
);
1917 ok (!ret
, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1918 ok (GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1920 if (pInitializeSRWLock
)
1922 pAcquireSRWLockExclusive(&condvar_srwlock
);
1923 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 10, 0);
1924 pReleaseSRWLockExclusive(&condvar_srwlock
);
1926 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1927 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1929 pAcquireSRWLockShared(&condvar_srwlock
);
1930 ret
= pSleepConditionVariableSRW(cv
, &condvar_srwlock
, 10, CONDITION_VARIABLE_LOCKMODE_SHARED
);
1931 pReleaseSRWLockShared(&condvar_srwlock
);
1933 ok(!ret
, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
1934 ok(GetLastError() == ERROR_TIMEOUT
, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1938 hp
= CreateThread(NULL
, 0, condvar_base_producer
, cv
, 0, &dummy
);
1939 hc
= CreateThread(NULL
, 0, condvar_base_consumer
, cv
, 0, &dummy
);
1941 condvar_seq
= 1; /* go */
1943 while (condvar_seq
< 9)
1945 WaitForSingleObject(hp
, 100);
1946 WaitForSingleObject(hc
, 100);
1949 static LONG srwlock_seq
= 0;
1950 static SRWLOCK aligned_srwlock
;
1953 LONG wrong_execution_order
;
1954 LONG samethread_excl_excl
;
1955 LONG samethread_excl_shared
;
1956 LONG samethread_shared_excl
;
1957 LONG multithread_excl_excl
;
1958 LONG excl_not_preferred
;
1960 LONG trylock_shared
;
1961 } srwlock_base_errors
;
1963 #include "pshpack1.h"
1968 } unaligned_srwlock
;
1969 #include "poppack.h"
1971 /* Sequence of acquire/release to check boundary conditions:
1974 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
1975 * 2: thread1 expects a deadlock and releases the waiting lock
1976 * thread2 releases the lock again
1978 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
1979 * 4: thread1 expects a deadlock and releases the waiting lock
1980 * thread2 releases the lock again
1982 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
1983 * 6: thread1 expects a deadlock and releases the waiting lock
1984 * thread2 releases the lock again
1986 * 7: thread2 acquires and releases two nested shared locks
1988 * 8: thread1 acquires an exclusive lock
1989 * 9: thread2 tries to acquire the exclusive lock, too
1990 * thread1 releases the exclusive lock again
1991 * 10: thread2 enters the exclusive lock and leaves it immediately again
1993 * 11: thread1 acquires a shared lock
1994 * 12: thread2 acquires and releases a shared lock
1995 * thread1 releases the lock again
1997 * 13: thread1 acquires a shared lock
1998 * 14: thread2 tries to acquire an exclusive lock
1999 * 15: thread3 tries to acquire a shared lock
2000 * 16: thread1 releases the shared lock
2001 * 17: thread2 wakes up and releases the exclusive lock
2002 * 18: thread3 wakes up and releases the shared lock
2004 * the following tests will only be executed if TryAcquireSRWLock* is available
2006 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
2007 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2008 * thread1 releases the exclusive lock
2010 * thread1 calls TryAcquireSRWLockShared which should return TRUE
2011 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2012 * thread1 releases the shared lock
2014 * thread1 acquires an exclusive lock
2015 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
2016 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2017 * 21: thread1 releases the exclusive lock
2019 * thread1 acquires an shared lock
2020 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2021 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2022 * 23: thread1 releases the shared lock
2024 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2025 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2026 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2027 * 25: thread1 releases the exclusive lock
2029 * thread1 acquires two shared locks
2030 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2031 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2032 * 27: thread1 releases one shared lock
2033 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2034 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2035 * 29: thread1 releases the second shared lock
2036 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2037 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2042 static DWORD WINAPI
srwlock_base_thread1(void *arg
)
2044 SRWLOCK
*lock
= arg
;
2047 while (srwlock_seq
< 2) Sleep(1);
2049 if (InterlockedIncrement(&srwlock_seq
) != 3)
2050 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2051 pReleaseSRWLockExclusive(lock
);
2054 while (srwlock_seq
< 4) Sleep(1);
2056 if (InterlockedIncrement(&srwlock_seq
) != 5)
2057 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2058 pReleaseSRWLockExclusive(lock
);
2061 while (srwlock_seq
< 6) Sleep(1);
2063 if (InterlockedIncrement(&srwlock_seq
) != 7)
2064 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2065 pReleaseSRWLockShared(lock
);
2068 while (srwlock_seq
< 8) Sleep(1);
2069 pAcquireSRWLockExclusive(lock
);
2070 if (InterlockedIncrement(&srwlock_seq
) != 9)
2071 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2073 if (InterlockedIncrement(&srwlock_seq
) != 10)
2074 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2075 pReleaseSRWLockExclusive(lock
);
2078 while (srwlock_seq
< 11) Sleep(1);
2079 pAcquireSRWLockShared(lock
);
2080 if (InterlockedIncrement(&srwlock_seq
) != 12)
2081 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2084 while (srwlock_seq
< 13) Sleep(1);
2085 pReleaseSRWLockShared(lock
);
2086 pAcquireSRWLockShared(lock
);
2087 if (InterlockedIncrement(&srwlock_seq
) != 14)
2088 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2091 while (srwlock_seq
< 16) Sleep(1);
2092 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2093 if (InterlockedIncrement(&srwlock_seq
) != 17)
2094 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2095 pReleaseSRWLockShared(lock
);
2097 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2098 if (!pTryAcquireSRWLockExclusive
)
2102 while (srwlock_seq
< 19) Sleep(1);
2103 if (pTryAcquireSRWLockExclusive(lock
))
2105 if (pTryAcquireSRWLockShared(lock
))
2106 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2107 if (pTryAcquireSRWLockExclusive(lock
))
2108 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2109 pReleaseSRWLockExclusive(lock
);
2112 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2114 if (pTryAcquireSRWLockShared(lock
))
2116 if (pTryAcquireSRWLockShared(lock
))
2117 pReleaseSRWLockShared(lock
);
2119 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2120 if (pTryAcquireSRWLockExclusive(lock
))
2121 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2122 pReleaseSRWLockShared(lock
);
2125 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2127 pAcquireSRWLockExclusive(lock
);
2128 if (InterlockedIncrement(&srwlock_seq
) != 20)
2129 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2132 while (srwlock_seq
< 21) Sleep(1);
2133 pReleaseSRWLockExclusive(lock
);
2134 pAcquireSRWLockShared(lock
);
2135 if (InterlockedIncrement(&srwlock_seq
) != 22)
2136 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2139 while (srwlock_seq
< 23) Sleep(1);
2140 pReleaseSRWLockShared(lock
);
2141 pAcquireSRWLockShared(lock
);
2142 if (InterlockedIncrement(&srwlock_seq
) != 24)
2143 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2146 pAcquireSRWLockExclusive(lock
);
2147 if (srwlock_seq
!= 25)
2148 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2149 pReleaseSRWLockExclusive(lock
);
2151 pAcquireSRWLockShared(lock
);
2152 pAcquireSRWLockShared(lock
);
2153 if (InterlockedIncrement(&srwlock_seq
) != 26)
2154 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2157 while (srwlock_seq
< 27) Sleep(1);
2158 pReleaseSRWLockShared(lock
);
2159 if (InterlockedIncrement(&srwlock_seq
) != 28)
2160 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2163 while (srwlock_seq
< 29) Sleep(1);
2164 pReleaseSRWLockShared(lock
);
2165 if (InterlockedIncrement(&srwlock_seq
) != 30)
2166 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2171 static DWORD WINAPI
srwlock_base_thread2(void *arg
)
2173 SRWLOCK
*lock
= arg
;
2176 while (srwlock_seq
< 1) Sleep(1);
2177 pAcquireSRWLockExclusive(lock
);
2178 if (InterlockedIncrement(&srwlock_seq
) != 2)
2179 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2182 pAcquireSRWLockExclusive(lock
);
2183 if (srwlock_seq
!= 3)
2184 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_excl
);
2185 pReleaseSRWLockExclusive(lock
);
2186 pAcquireSRWLockExclusive(lock
);
2187 if (InterlockedIncrement(&srwlock_seq
) != 4)
2188 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2191 pAcquireSRWLockShared(lock
);
2192 if (srwlock_seq
!= 5)
2193 InterlockedIncrement(&srwlock_base_errors
.samethread_excl_shared
);
2194 pReleaseSRWLockShared(lock
);
2195 pAcquireSRWLockShared(lock
);
2196 if (InterlockedIncrement(&srwlock_seq
) != 6)
2197 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2200 pAcquireSRWLockExclusive(lock
);
2201 if (srwlock_seq
!= 7)
2202 InterlockedIncrement(&srwlock_base_errors
.samethread_shared_excl
);
2203 pReleaseSRWLockExclusive(lock
);
2204 pAcquireSRWLockShared(lock
);
2205 pAcquireSRWLockShared(lock
);
2206 pReleaseSRWLockShared(lock
);
2207 pReleaseSRWLockShared(lock
);
2208 if (InterlockedIncrement(&srwlock_seq
) != 8)
2209 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2212 while (srwlock_seq
< 9) Sleep(1);
2213 pAcquireSRWLockExclusive(lock
);
2214 if (srwlock_seq
!= 10)
2215 InterlockedIncrement(&srwlock_base_errors
.multithread_excl_excl
);
2216 pReleaseSRWLockExclusive(lock
);
2217 if (InterlockedIncrement(&srwlock_seq
) != 11)
2218 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2221 while (srwlock_seq
< 12) Sleep(1);
2222 pAcquireSRWLockShared(lock
);
2223 pReleaseSRWLockShared(lock
);
2224 if (InterlockedIncrement(&srwlock_seq
) != 13)
2225 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2228 while (srwlock_seq
< 14) Sleep(1);
2229 if (InterlockedIncrement(&srwlock_seq
) != 15)
2230 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2233 pAcquireSRWLockExclusive(lock
);
2234 if (srwlock_seq
!= 17)
2235 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2236 if (InterlockedIncrement(&srwlock_seq
) != 18)
2237 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2238 pReleaseSRWLockExclusive(lock
);
2240 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2241 if (!pTryAcquireSRWLockExclusive
)
2245 while (srwlock_seq
< 20) Sleep(1);
2246 if (pTryAcquireSRWLockShared(lock
))
2247 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2248 if (pTryAcquireSRWLockExclusive(lock
))
2249 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2250 if (InterlockedIncrement(&srwlock_seq
) != 21)
2251 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2254 while (srwlock_seq
< 22) Sleep(1);
2255 if (pTryAcquireSRWLockShared(lock
))
2256 pReleaseSRWLockShared(lock
);
2258 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2259 if (pTryAcquireSRWLockExclusive(lock
))
2260 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2261 if (InterlockedIncrement(&srwlock_seq
) != 23)
2262 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2265 while (srwlock_seq
< 24) Sleep(1);
2266 Sleep(50); /* ensure that exclusive access request is queued */
2267 if (pTryAcquireSRWLockShared(lock
))
2269 pReleaseSRWLockShared(lock
);
2270 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2272 if (pTryAcquireSRWLockExclusive(lock
))
2273 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2274 if (InterlockedIncrement(&srwlock_seq
) != 25)
2275 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2276 pReleaseSRWLockShared(lock
);
2279 while (srwlock_seq
< 26) Sleep(1);
2280 if (pTryAcquireSRWLockShared(lock
))
2281 pReleaseSRWLockShared(lock
);
2283 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2284 if (pTryAcquireSRWLockExclusive(lock
))
2285 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2286 if (InterlockedIncrement(&srwlock_seq
) != 27)
2287 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2290 while (srwlock_seq
< 28) Sleep(1);
2291 if (pTryAcquireSRWLockShared(lock
))
2292 pReleaseSRWLockShared(lock
);
2294 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2295 if (pTryAcquireSRWLockExclusive(lock
))
2296 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2297 if (InterlockedIncrement(&srwlock_seq
) != 29)
2298 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2301 while (srwlock_seq
< 30) Sleep(1);
2302 if (pTryAcquireSRWLockShared(lock
))
2303 pReleaseSRWLockShared(lock
);
2305 InterlockedIncrement(&srwlock_base_errors
.trylock_shared
);
2306 if (pTryAcquireSRWLockExclusive(lock
))
2307 pReleaseSRWLockExclusive(lock
);
2309 InterlockedIncrement(&srwlock_base_errors
.trylock_excl
);
2310 if (InterlockedIncrement(&srwlock_seq
) != 31)
2311 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2316 static DWORD WINAPI
srwlock_base_thread3(void *arg
)
2318 SRWLOCK
*lock
= arg
;
2321 while (srwlock_seq
< 15) Sleep(1);
2322 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2323 if (InterlockedIncrement(&srwlock_seq
) != 16)
2324 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2327 pAcquireSRWLockShared(lock
);
2328 if (srwlock_seq
!= 18)
2329 InterlockedIncrement(&srwlock_base_errors
.excl_not_preferred
);
2330 pReleaseSRWLockShared(lock
);
2331 if (InterlockedIncrement(&srwlock_seq
) != 19)
2332 InterlockedIncrement(&srwlock_base_errors
.wrong_execution_order
);
2334 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2335 if (!pTryAcquireSRWLockExclusive
)
2337 /* function is only in Windows 7 and newer */
2338 win_skip("no srw trylock support.\n");
2339 srwlock_seq
= 31; /* end */
2346 static void test_srwlock_base(SRWLOCK
*lock
)
2351 if (!pInitializeSRWLock
)
2353 /* function is not yet in XP, only in newer Windows */
2354 win_skip("no srw lock support.\n");
2358 pInitializeSRWLock(lock
);
2359 memset(&srwlock_base_errors
, 0, sizeof(srwlock_base_errors
));
2362 h1
= CreateThread(NULL
, 0, srwlock_base_thread1
, lock
, 0, &dummy
);
2363 h2
= CreateThread(NULL
, 0, srwlock_base_thread2
, lock
, 0, &dummy
);
2364 h3
= CreateThread(NULL
, 0, srwlock_base_thread3
, lock
, 0, &dummy
);
2366 srwlock_seq
= 1; /* go */
2367 while (srwlock_seq
< 31)
2370 WaitForSingleObject(h1
, 100);
2371 WaitForSingleObject(h2
, 100);
2372 WaitForSingleObject(h3
, 100);
2374 ok(!srwlock_base_errors
.wrong_execution_order
,
2375 "thread commands were executed in the wrong order (occurred %d times).\n",
2376 srwlock_base_errors
.wrong_execution_order
);
2378 ok(!srwlock_base_errors
.samethread_excl_excl
,
2379 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n",
2380 srwlock_base_errors
.samethread_excl_excl
);
2382 ok(!srwlock_base_errors
.samethread_excl_shared
,
2383 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n",
2384 srwlock_base_errors
.samethread_excl_shared
);
2386 ok(!srwlock_base_errors
.samethread_shared_excl
,
2387 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n",
2388 srwlock_base_errors
.samethread_shared_excl
);
2390 ok(!srwlock_base_errors
.multithread_excl_excl
,
2391 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n",
2392 srwlock_base_errors
.multithread_excl_excl
);
2394 ok(!srwlock_base_errors
.excl_not_preferred
,
2395 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n",
2396 srwlock_base_errors
.excl_not_preferred
);
2398 ok(!srwlock_base_errors
.trylock_excl
,
2399 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n",
2400 srwlock_base_errors
.trylock_excl
);
2402 ok(!srwlock_base_errors
.trylock_shared
,
2403 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n",
2404 srwlock_base_errors
.trylock_shared
);
2408 static SRWLOCK srwlock_example
;
2409 static LONG srwlock_protected_value
= 0;
2410 static LONG srwlock_example_errors
= 0, srwlock_inside
= 0, srwlock_cnt
= 0;
2411 static BOOL srwlock_stop
= FALSE
;
2413 static DWORD WINAPI
srwlock_example_thread(LPVOID x
) {
2417 while (!srwlock_stop
)
2420 /* periodically request exclusive access */
2421 if (InterlockedIncrement(&srwlock_cnt
) % 13 == 0)
2423 pAcquireSRWLockExclusive(&srwlock_example
);
2424 if (InterlockedIncrement(&srwlock_inside
) != 1)
2425 InterlockedIncrement(&srwlock_example_errors
);
2427 InterlockedIncrement(&srwlock_protected_value
);
2430 if (InterlockedDecrement(&srwlock_inside
) != 0)
2431 InterlockedIncrement(&srwlock_example_errors
);
2432 pReleaseSRWLockExclusive(&srwlock_example
);
2435 /* request shared access */
2436 pAcquireSRWLockShared(&srwlock_example
);
2437 InterlockedIncrement(&srwlock_inside
);
2438 old
= srwlock_protected_value
;
2443 if (old
!= srwlock_protected_value
)
2444 InterlockedIncrement(&srwlock_example_errors
);
2445 InterlockedDecrement(&srwlock_inside
);
2446 pReleaseSRWLockShared(&srwlock_example
);
2452 static void test_srwlock_example(void)
2456 DWORD cnt1
, cnt2
, cnt3
;
2458 if (!pInitializeSRWLock
) {
2459 /* function is not yet in XP, only in newer Windows */
2460 win_skip("no srw lock support.\n");
2464 pInitializeSRWLock(&srwlock_example
);
2466 cnt1
= cnt2
= cnt3
= 0;
2468 h1
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt1
, 0, &dummy
);
2469 h2
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt2
, 0, &dummy
);
2470 h3
= CreateThread(NULL
, 0, srwlock_example_thread
, &cnt3
, 0, &dummy
);
2472 /* limit run to 1 second. */
2475 /* tear down start */
2476 srwlock_stop
= TRUE
;
2478 WaitForSingleObject(h1
, 1000);
2479 WaitForSingleObject(h2
, 1000);
2480 WaitForSingleObject(h3
, 1000);
2482 ok(!srwlock_inside
, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside
);
2483 ok(!srwlock_example_errors
, "errors occurred while running SRWLock example test (number of errors: %d)\n",
2484 srwlock_example_errors
);
2486 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1
, cnt2
, cnt3
);
2487 trace("number of total exclusive accesses is %d\n", srwlock_protected_value
);
2490 static DWORD WINAPI
alertable_wait_thread(void *param
)
2492 HANDLE
*semaphores
= param
;
2493 LARGE_INTEGER timeout
;
2497 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2498 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 1000, TRUE
);
2499 ok(result
== WAIT_IO_COMPLETION
, "expected WAIT_IO_COMPLETION, got %u\n", result
);
2500 result
= WaitForMultipleObjectsEx(1, &semaphores
[1], TRUE
, 200, TRUE
);
2501 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2503 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2504 timeout
.QuadPart
= -10000000;
2505 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2506 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2507 timeout
.QuadPart
= -2000000;
2508 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2509 ok(status
== STATUS_WAIT_0
, "expected STATUS_WAIT_0, got %08x\n", status
);
2511 ReleaseSemaphore(semaphores
[0], 1, NULL
);
2512 timeout
.QuadPart
= -10000000;
2513 status
= pNtWaitForMultipleObjects(1, &semaphores
[1], FALSE
, TRUE
, &timeout
);
2514 ok(status
== STATUS_USER_APC
, "expected STATUS_USER_APC, got %08x\n", status
);
2515 result
= WaitForSingleObject(semaphores
[0], 0);
2516 ok(result
== WAIT_TIMEOUT
, "expected WAIT_TIMEOUT, got %u\n", result
);
2521 static void CALLBACK
alertable_wait_apc(ULONG_PTR userdata
)
2523 HANDLE
*semaphores
= (void *)userdata
;
2524 ReleaseSemaphore(semaphores
[1], 1, NULL
);
2527 static void CALLBACK
alertable_wait_apc2(ULONG_PTR userdata
)
2529 HANDLE
*semaphores
= (void *)userdata
;
2532 result
= WaitForSingleObject(semaphores
[0], 1000);
2533 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2536 static void test_alertable_wait(void)
2538 HANDLE thread
, semaphores
[2];
2541 semaphores
[0] = CreateSemaphoreW(NULL
, 0, 2, NULL
);
2542 ok(semaphores
[0] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2543 semaphores
[1] = CreateSemaphoreW(NULL
, 0, 1, NULL
);
2544 ok(semaphores
[1] != NULL
, "CreateSemaphore failed with %u\n", GetLastError());
2545 thread
= CreateThread(NULL
, 0, alertable_wait_thread
, semaphores
, 0, NULL
);
2546 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2548 result
= WaitForSingleObject(semaphores
[0], 1000);
2549 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2550 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2551 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2552 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2554 result
= WaitForSingleObject(semaphores
[0], 1000);
2555 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2556 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2557 result
= QueueUserAPC(alertable_wait_apc
, thread
, (ULONG_PTR
)semaphores
);
2558 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2560 result
= WaitForSingleObject(semaphores
[0], 1000);
2561 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2562 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2563 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2564 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2565 result
= QueueUserAPC(alertable_wait_apc2
, thread
, (ULONG_PTR
)semaphores
);
2566 ok(result
!= 0, "QueueUserAPC failed with %u\n", GetLastError());
2567 ReleaseSemaphore(semaphores
[0], 2, NULL
);
2569 result
= WaitForSingleObject(thread
, 1000);
2570 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2571 CloseHandle(thread
);
2572 CloseHandle(semaphores
[0]);
2573 CloseHandle(semaphores
[1]);
2576 struct apc_deadlock_info
2578 PROCESS_INFORMATION
*pi
;
2583 static DWORD WINAPI
apc_deadlock_thread(void *param
)
2585 struct apc_deadlock_info
*info
= param
;
2586 PROCESS_INFORMATION
*pi
= info
->pi
;
2591 while (info
->running
)
2595 status
= pNtAllocateVirtualMemory(pi
->hProcess
, &base
, 0, &size
,
2596 MEM_RESERVE
| MEM_COMMIT
, PAGE_READWRITE
);
2597 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2598 ok(base
!= NULL
, "expected base != NULL, got %p\n", base
);
2599 SetEvent(info
->event
);
2602 status
= pNtFreeVirtualMemory(pi
->hProcess
, &base
, &size
, MEM_RELEASE
);
2603 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
2604 SetEvent(info
->event
);
2610 static void test_apc_deadlock(void)
2612 struct apc_deadlock_info info
;
2613 PROCESS_INFORMATION pi
;
2614 STARTUPINFOA si
= { sizeof(si
) };
2615 char cmdline
[MAX_PATH
];
2616 HANDLE event
, thread
;
2622 winetest_get_mainargs(&argv
);
2623 sprintf(cmdline
, "\"%s\" sync apc_deadlock", argv
[0]);
2624 success
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2625 ok(success
, "CreateProcess failed with %u\n", GetLastError());
2627 event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2628 ok(event
!= NULL
, "CreateEvent failed with %u\n", GetLastError());
2632 info
.running
= TRUE
;
2634 thread
= CreateThread(NULL
, 0, apc_deadlock_thread
, &info
, 0, NULL
);
2635 ok(thread
!= NULL
, "CreateThread failed with %u\n", GetLastError());
2636 result
= WaitForSingleObject(event
, 1000);
2637 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2639 for (i
= 0; i
< 1000 && info
.running
; i
++)
2641 result
= SuspendThread(pi
.hThread
);
2642 ok(result
== 0, "expected 0, got %u\n", result
);
2644 WaitForSingleObject(event
, 0); /* reset event */
2645 result
= WaitForSingleObject(event
, 1000);
2646 if (result
== WAIT_TIMEOUT
)
2649 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2650 info
.running
= FALSE
;
2653 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2655 result
= ResumeThread(pi
.hThread
);
2656 ok(result
== 1, "expected 1, got %u\n", result
);
2660 info
.running
= FALSE
;
2661 result
= WaitForSingleObject(thread
, 1000);
2662 ok(result
== WAIT_OBJECT_0
, "expected WAIT_OBJECT_0, got %u\n", result
);
2663 CloseHandle(thread
);
2666 TerminateProcess(pi
.hProcess
, 0);
2667 CloseHandle(pi
.hThread
);
2668 CloseHandle(pi
.hProcess
);
2671 static void test_crit_section(void)
2673 CRITICAL_SECTION cs
;
2676 /* Win8+ does not initialize debug info, one has to use RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
2677 to override that. */
2678 memset(&cs
, 0, sizeof(cs
));
2679 InitializeCriticalSection(&cs
);
2680 ok(cs
.DebugInfo
!= NULL
, "Unexpected debug info pointer %p.\n", cs
.DebugInfo
);
2681 DeleteCriticalSection(&cs
);
2682 ok(cs
.DebugInfo
== NULL
, "Unexpected debug info pointer %p.\n", cs
.DebugInfo
);
2684 if (!pInitializeCriticalSectionEx
)
2686 win_skip("InitializeCriticalSectionEx isn't available, skipping tests.\n");
2690 memset(&cs
, 0, sizeof(cs
));
2691 ret
= pInitializeCriticalSectionEx(&cs
, 0, CRITICAL_SECTION_NO_DEBUG_INFO
);
2692 ok(ret
, "Failed to initialize critical section.\n");
2693 ok(cs
.DebugInfo
== (void *)(ULONG_PTR
)-1, "Unexpected debug info pointer %p.\n", cs
.DebugInfo
);
2695 ret
= TryEnterCriticalSection(&cs
);
2696 ok(ret
, "Failed to enter critical section.\n");
2697 LeaveCriticalSection(&cs
);
2699 cs
.DebugInfo
= NULL
;
2701 ret
= TryEnterCriticalSection(&cs
);
2702 ok(ret
, "Failed to enter critical section.\n");
2703 LeaveCriticalSection(&cs
);
2705 DeleteCriticalSection(&cs
);
2706 ok(cs
.DebugInfo
== NULL
, "Unexpected debug info pointer %p.\n", cs
.DebugInfo
);
2709 static DWORD WINAPI
thread_proc(LPVOID unused
)
2715 static void CALLBACK
user_apc(ULONG_PTR unused
)
2719 static void CALLBACK
call_user_apc(ULONG_PTR arg1
, ULONG_PTR arg2
, ULONG_PTR arg3
)
2721 PAPCFUNC func
= (PAPCFUNC
)arg1
;
2725 static void test_QueueUserAPC(void)
2730 thread
= CreateThread(NULL
, 0, thread_proc
, NULL
, CREATE_SUSPENDED
, &tid
);
2731 ok(thread
!= NULL
, "CreateThread error %u\n", GetLastError());
2733 ret
= TerminateThread(thread
, 0xdeadbeef);
2734 ok(ret
, "TerminateThread error %u\n", GetLastError());
2736 ret
= WaitForSingleObject(thread
, 1000);
2737 ok(ret
== WAIT_OBJECT_0
, "got %u\n", ret
);
2739 ret
= pNtQueueApcThread(thread
, call_user_apc
, (ULONG_PTR
)user_apc
, 0, 0);
2740 ok(ret
== STATUS_UNSUCCESSFUL
, "got %#x\n", ret
);
2742 SetLastError(0xdeadbeef);
2743 ret
= QueueUserAPC(user_apc
, thread
, 0);
2744 ok(!ret
, "QueueUserAPC should fail\n");
2745 ok(GetLastError() == ERROR_GEN_FAILURE
, "got %u\n", GetLastError());
2747 CloseHandle(thread
);
2754 HMODULE hdll
= GetModuleHandleA("kernel32.dll");
2755 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
2757 pInitOnceInitialize
= (void *)GetProcAddress(hdll
, "InitOnceInitialize");
2758 pInitOnceExecuteOnce
= (void *)GetProcAddress(hdll
, "InitOnceExecuteOnce");
2759 pInitOnceBeginInitialize
= (void *)GetProcAddress(hdll
, "InitOnceBeginInitialize");
2760 pInitOnceComplete
= (void *)GetProcAddress(hdll
, "InitOnceComplete");
2761 pInitializeConditionVariable
= (void *)GetProcAddress(hdll
, "InitializeConditionVariable");
2762 pSleepConditionVariableCS
= (void *)GetProcAddress(hdll
, "SleepConditionVariableCS");
2763 pSleepConditionVariableSRW
= (void *)GetProcAddress(hdll
, "SleepConditionVariableSRW");
2764 pWakeAllConditionVariable
= (void *)GetProcAddress(hdll
, "WakeAllConditionVariable");
2765 pWakeConditionVariable
= (void *)GetProcAddress(hdll
, "WakeConditionVariable");
2766 pInitializeCriticalSectionEx
= (void *)GetProcAddress(hdll
, "InitializeCriticalSectionEx");
2767 pInitializeSRWLock
= (void *)GetProcAddress(hdll
, "InitializeSRWLock");
2768 pAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "AcquireSRWLockExclusive");
2769 pAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "AcquireSRWLockShared");
2770 pReleaseSRWLockExclusive
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockExclusive");
2771 pReleaseSRWLockShared
= (void *)GetProcAddress(hdll
, "ReleaseSRWLockShared");
2772 pTryAcquireSRWLockExclusive
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockExclusive");
2773 pTryAcquireSRWLockShared
= (void *)GetProcAddress(hdll
, "TryAcquireSRWLockShared");
2774 pNtAllocateVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtAllocateVirtualMemory");
2775 pNtFreeVirtualMemory
= (void *)GetProcAddress(hntdll
, "NtFreeVirtualMemory");
2776 pNtWaitForSingleObject
= (void *)GetProcAddress(hntdll
, "NtWaitForSingleObject");
2777 pNtWaitForMultipleObjects
= (void *)GetProcAddress(hntdll
, "NtWaitForMultipleObjects");
2778 pRtlInterlockedPushListSList
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSList");
2779 pRtlInterlockedPushListSListEx
= (void *)GetProcAddress(hntdll
, "RtlInterlockedPushListSListEx");
2780 pNtQueueApcThread
= (void *)GetProcAddress(hntdll
, "NtQueueApcThread");
2782 argc
= winetest_get_mainargs( &argv
);
2785 if (!strcmp(argv
[2], "apc_deadlock"))
2787 for (;;) SleepEx(INFINITE
, TRUE
);
2792 init_fastcall_thunk();
2794 test_QueueUserAPC();
2795 test_signalandwait();
2800 test_waitable_timer();
2801 test_iocp_callback();
2803 test_WaitForSingleObject();
2804 test_WaitForMultipleObjects();
2806 test_condvars_base(&aligned_cv
);
2807 test_condvars_base(&unaligned_cv
.cv
);
2808 test_condvars_consumer_producer();
2809 test_srwlock_base(&aligned_srwlock
);
2810 test_srwlock_base(&unaligned_srwlock
.lock
);
2811 test_srwlock_example();
2812 test_alertable_wait();
2813 test_apc_deadlock();
2814 test_crit_section();