Reactos
1/*
2 * Synchronization tests
3 *
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21#include <stdarg.h>
22#include <stdlib.h>
23#include <stdio.h>
24
25#include "ntstatus.h"
26#define WIN32_NO_STATUS
27#include <windef.h>
28#include <winbase.h>
29#include <winternl.h>
30#include <setjmp.h>
31
32#include "wine/test.h"
33
34#undef __fastcall
35#define __fastcall __stdcall
36
37static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
38static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
39static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
40static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
41static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
42static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
43
44static BOOL (WINAPI *pInitializeCriticalSectionEx)(CRITICAL_SECTION*,DWORD,DWORD);
45static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
46static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
47static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG);
48static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
49static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
50
51static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK);
52static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK);
53static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK);
54static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK);
55static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK);
56static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK);
57static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK);
58
59static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG_PTR, SIZE_T *, ULONG, ULONG);
60static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG);
61static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *);
62static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*);
63static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first,
64 PSLIST_ENTRY last, ULONG count);
65static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first,
66 PSLIST_ENTRY last, ULONG count);
67static NTSTATUS (WINAPI *pNtQueueApcThread)(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
68static NTSTATUS (WINAPI *pNtTestAlert)(void);
69
70#ifdef __i386__
71
72#include "pshpack1.h"
73struct fastcall_thunk
74{
75 BYTE pop_edx; /* popl %edx (ret addr) */
76 BYTE pop_eax; /* popl %eax (func) */
77 BYTE pop_ecx; /* popl %ecx (param 1) */
78 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */
79 WORD jmp_eax; /* jmp *%eax */
80};
81#include "poppack.h"
82
83static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d);
84
85static void init_fastcall_thunk(void)
86{
87 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
88 thunk->pop_edx = 0x5a; /* popl %edx */
89 thunk->pop_eax = 0x58; /* popl %eax */
90 thunk->pop_ecx = 0x59; /* popl %ecx */
91 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */
92 thunk->xchg[1] = 0x14;
93 thunk->xchg[2] = 0x24;
94 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */
95 call_fastcall_func4 = (void *)thunk;
96}
97
98#define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \
99 (const void *)(b), (const void *)(c), (const void *)(d))
100
101#else /* __i386__ */
102
103#define init_fastcall_thunk() do { } while(0)
104#define call_func4(func, a, b, c, d) func(a, b, c, d)
105
106#endif /* __i386__ */
107
108static void test_signalandwait(void)
109{
110 DWORD r;
111 HANDLE event[2], semaphore[2], file;
112 int i;
113
114 /* invalid parameters */
115 r = SignalObjectAndWait(NULL, NULL, 0, 0);
116 ok( r == WAIT_FAILED, "should fail\n");
117
118 event[0] = CreateEventW(NULL, 0, 0, NULL);
119 event[1] = CreateEventW(NULL, 1, 1, NULL);
120
121 ok( event[0] && event[1], "failed to create event flags\n");
122
123 r = SignalObjectAndWait(event[0], NULL, 0, FALSE);
124 ok( r == WAIT_FAILED, "should fail\n");
125
126 r = SignalObjectAndWait(NULL, event[0], 0, FALSE);
127 ok( r == WAIT_FAILED, "should fail\n");
128
129
130 /* valid parameters */
131 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
132 ok( r == WAIT_OBJECT_0, "should succeed\n");
133
134 /* event[0] is now signalled - we repeat this test multiple times
135 * to ensure that the wineserver handles this situation properly. */
136 for (i = 0; i < 10000; i++)
137 {
138 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
139 ok(r == WAIT_OBJECT_0, "should succeed\n");
140 }
141
142 /* event[0] is not signalled */
143 r = WaitForSingleObject(event[0], 0);
144 ok( r == WAIT_TIMEOUT, "event was signalled\n");
145
146 r = SignalObjectAndWait(event[0], event[0], 0, FALSE);
147 ok( r == WAIT_OBJECT_0, "should succeed\n");
148
149 /* clear event[1] and check for a timeout */
150 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
151 r = SignalObjectAndWait(event[0], event[1], 0, FALSE);
152 ok( r == WAIT_TIMEOUT, "should timeout\n");
153
154 CloseHandle(event[0]);
155 CloseHandle(event[1]);
156
157 /* semaphores */
158 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL );
159 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL );
160 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
161
162 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
163 ok( r == WAIT_OBJECT_0, "should succeed\n");
164
165 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
166 ok( r == WAIT_FAILED, "should fail\n");
167
168 r = ReleaseSemaphore(semaphore[0],1,NULL);
169 ok( r == FALSE, "should fail\n");
170
171 r = ReleaseSemaphore(semaphore[1],1,NULL);
172 ok( r == TRUE, "should succeed\n");
173
174 CloseHandle(semaphore[0]);
175 CloseHandle(semaphore[1]);
176
177 /* try a registry key */
178 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
179 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
180 r = SignalObjectAndWait(file, file, 0, FALSE);
181 ok( r == WAIT_FAILED, "should fail\n");
182 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
183 CloseHandle(file);
184}
185
186static void test_temporary_objects(void)
187{
188 HANDLE handle;
189
190 SetLastError(0xdeadbeef);
191 handle = CreateMutexA(NULL, FALSE, "WineTestMutex2");
192 ok(handle != NULL, "CreateMutex failed with error %ld\n", GetLastError());
193 CloseHandle(handle);
194
195 SetLastError(0xdeadbeef);
196 handle = OpenMutexA(READ_CONTROL, FALSE, "WineTestMutex2");
197 ok(!handle, "OpenMutex succeeded\n");
198 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
199
200 SetLastError(0xdeadbeef);
201 handle = CreateSemaphoreA(NULL, 0, 1, "WineTestSemaphore2");
202 ok(handle != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
203 CloseHandle(handle);
204
205 SetLastError(0xdeadbeef);
206 handle = OpenSemaphoreA(READ_CONTROL, FALSE, "WineTestSemaphore2");
207 ok(!handle, "OpenSemaphore succeeded\n");
208 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
209
210 SetLastError(0xdeadbeef);
211 handle = CreateEventA(NULL, FALSE, FALSE, "WineTestEvent2");
212 ok(handle != NULL, "CreateEvent failed with error %ld\n", GetLastError());
213 CloseHandle(handle);
214
215 SetLastError(0xdeadbeef);
216 handle = OpenEventA(READ_CONTROL, FALSE, "WineTestEvent2");
217 ok(!handle, "OpenEvent succeeded\n");
218 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
219
220 SetLastError(0xdeadbeef);
221 handle = CreateWaitableTimerA(NULL, FALSE, "WineTestWaitableTimer2");
222 ok(handle != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
223 CloseHandle(handle);
224
225 SetLastError(0xdeadbeef);
226 handle = OpenWaitableTimerA(READ_CONTROL, FALSE, "WineTestWaitableTimer2");
227 ok(!handle, "OpenWaitableTimer succeeded\n");
228 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
229}
230
231static void test_mutex(void)
232{
233 DWORD wait_ret;
234 BOOL ret;
235 HANDLE hCreated;
236 HANDLE hOpened;
237 int i;
238 DWORD failed = 0;
239
240 SetLastError(0xdeadbeef);
241 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
242 ok(hOpened == NULL, "OpenMutex succeeded\n");
243 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
244
245 SetLastError(0xdeadbeef);
246 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex");
247 ok(hCreated != NULL, "CreateMutex failed with error %ld\n", GetLastError());
248
249 SetLastError(0xdeadbeef);
250 hOpened = OpenMutexA(0, FALSE, "WineTestMutex");
251 todo_wine
252 ok(hOpened == NULL, "OpenMutex succeeded\n");
253 todo_wine
254 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu\n", GetLastError());
255
256 SetLastError(0xdeadbeef);
257 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex");
258 ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError());
259 wait_ret = WaitForSingleObject(hOpened, INFINITE);
260 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %ld\n", GetLastError());
261 CloseHandle(hOpened);
262
263 for(i=0; i < 31; i++)
264 {
265 wait_ret = WaitForSingleObject(hCreated, INFINITE);
266 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08lx\n", wait_ret);
267 }
268
269 SetLastError(0xdeadbeef);
270 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
271 ok(hOpened != NULL, "OpenMutex failed with error %ld\n", GetLastError());
272 wait_ret = WaitForSingleObject(hOpened, INFINITE);
273 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
274 CloseHandle(hOpened);
275
276 for (i = 0; i < 32; i++)
277 {
278 SetLastError(0xdeadbeef);
279 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex");
280 if(hOpened != NULL)
281 {
282 SetLastError(0xdeadbeef);
283 ret = ReleaseMutex(hOpened);
284 ok(ret, "ReleaseMutex failed with error %ld, access %x\n", GetLastError(), 1 << i);
285 CloseHandle(hOpened);
286 }
287 else
288 {
289 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
290 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %lu, access %x\n", GetLastError(), 1 << i);
291 else
292 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %lu, , access %x\n", GetLastError(), 1 << i);
293 ReleaseMutex(hCreated);
294 failed |=0x1 << i;
295 }
296 }
297
298 todo_wine
299 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %lx\n", failed);
300
301 SetLastError(0xdeadbeef);
302 ret = ReleaseMutex(hCreated);
303 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
304 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %ld\n", GetLastError());
305
306 /* test case sensitivity */
307
308 SetLastError(0xdeadbeef);
309 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX");
310 ok(!hOpened, "OpenMutex succeeded\n");
311 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
312
313 SetLastError(0xdeadbeef);
314 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex");
315 ok(!hOpened, "OpenMutex succeeded\n");
316 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
317
318 SetLastError(0xdeadbeef);
319 hOpened = OpenMutexA(READ_CONTROL, FALSE, NULL);
320 ok(!hOpened, "OpenMutex succeeded\n");
321 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
322
323 SetLastError(0xdeadbeef);
324 hOpened = OpenMutexW(READ_CONTROL, FALSE, NULL);
325 ok(!hOpened, "OpenMutex succeeded\n");
326 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
327
328 SetLastError(0xdeadbeef);
329 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex");
330 ok(hOpened != NULL, "CreateMutex failed with error %ld\n", GetLastError());
331 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
332 CloseHandle(hOpened);
333
334 SetLastError(0xdeadbeef);
335 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX");
336 ok(hOpened != NULL, "CreateMutex failed with error %ld\n", GetLastError());
337 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
338 CloseHandle(hOpened);
339
340 CloseHandle(hCreated);
341}
342
343static void test_slist(void)
344{
345 struct item
346 {
347 SLIST_ENTRY entry;
348 int value;
349 } item1, item2, item3, *item;
350 SLIST_HEADER slist_header;
351 SLIST_ENTRY *entry;
352 USHORT size;
353 int i;
354
355 item1.value = 1;
356 item2.value = 2;
357 item3.value = 3;
358
359 memset(&slist_header, 0xff, sizeof(slist_header));
360 InitializeSListHead(&slist_header);
361 size = QueryDepthSList(&slist_header);
362 ok(size == 0, "Expected size == 0, got %u\n", size);
363
364 /* test PushEntry, PopEntry and Flush */
365 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
366 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
367 size = QueryDepthSList(&slist_header);
368 ok(size == 1, "Expected size == 1, got %u\n", size);
369
370 entry = InterlockedPushEntrySList(&slist_header, &item2.entry);
371 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
372 item = CONTAINING_RECORD(entry, struct item, entry);
373 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
374 size = QueryDepthSList(&slist_header);
375 ok(size == 2, "Expected size == 2, got %u\n", size);
376
377 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
378 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
379 item = CONTAINING_RECORD(entry, struct item, entry);
380 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
381 size = QueryDepthSList(&slist_header);
382 ok(size == 3, "Expected size == 3, got %u\n", size);
383
384 entry = InterlockedPopEntrySList(&slist_header);
385 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
386 item = CONTAINING_RECORD(entry, struct item, entry);
387 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
388 size = QueryDepthSList(&slist_header);
389 ok(size == 2, "Expected size == 2, got %u\n", size);
390
391 entry = InterlockedFlushSList(&slist_header);
392 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
393 item = CONTAINING_RECORD(entry, struct item, entry);
394 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
395 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
396 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
397 size = QueryDepthSList(&slist_header);
398 ok(size == 0, "Expected size == 0, got %u\n", size);
399 entry = InterlockedPopEntrySList(&slist_header);
400 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
401
402 /* test RtlInterlockedPushListSList */
403 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
404 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
405 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42);
406 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
407 item = CONTAINING_RECORD(entry, struct item, entry);
408 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
409 size = QueryDepthSList(&slist_header);
410 ok(size == 43, "Expected size == 43, got %u\n", size);
411
412 entry = InterlockedPopEntrySList(&slist_header);
413 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
414 item = CONTAINING_RECORD(entry, struct item, entry);
415 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
416 size = QueryDepthSList(&slist_header);
417 ok(size == 42, "Expected size == 42, got %u\n", size);
418
419 entry = InterlockedPopEntrySList(&slist_header);
420 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
421 item = CONTAINING_RECORD(entry, struct item, entry);
422 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
423 size = QueryDepthSList(&slist_header);
424 ok(size == 41, "Expected size == 41, got %u\n", size);
425
426 entry = InterlockedPopEntrySList(&slist_header);
427 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
428 item = CONTAINING_RECORD(entry, struct item, entry);
429 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
430 size = QueryDepthSList(&slist_header);
431 ok(size == 40, "Expected size == 40, got %u\n", size);
432
433 entry = InterlockedPopEntrySList(&slist_header);
434 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
435 size = QueryDepthSList(&slist_header);
436 ok(size == 40, "Expected size == 40, got %u\n", size);
437
438 entry = InterlockedFlushSList(&slist_header);
439 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
440 size = QueryDepthSList(&slist_header);
441 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size);
442
443 entry = InterlockedPushEntrySList(&slist_header, &item1.entry);
444 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
445 entry = InterlockedFlushSList(&slist_header);
446 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
447 item = CONTAINING_RECORD(entry, struct item, entry);
448 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
449 size = QueryDepthSList(&slist_header);
450 ok(size == 0, "Expected size == 0, got %u\n", size);
451
452 /* test RtlInterlockedPushListSListEx */
453 if (pRtlInterlockedPushListSListEx)
454 {
455 entry = InterlockedPushEntrySList(&slist_header, &item3.entry);
456 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
457 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42);
458 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
459 item = CONTAINING_RECORD(entry, struct item, entry);
460 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
461 size = QueryDepthSList(&slist_header);
462 ok(size == 43, "Expected size == 43, got %u\n", size);
463
464 entry = InterlockedFlushSList(&slist_header);
465 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
466 item = CONTAINING_RECORD(entry, struct item, entry);
467 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value);
468 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
469 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value);
470 item = CONTAINING_RECORD(item->entry.Next, struct item, entry);
471 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value);
472 size = QueryDepthSList(&slist_header);
473 ok(size == 0, "Expected size == 0, got %u\n", size);
474 }
475 else
476 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n");
477
478 /* test with a lot of items */
479 for (i = 0; i < 65536; i++)
480 {
481 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
482 item->value = i + 1;
483 entry = InterlockedPushEntrySList(&slist_header, &item->entry);
484 if (i)
485 {
486 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
487 item = CONTAINING_RECORD(entry, struct item, entry);
488 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
489 }
490 else
491 {
492 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
493 }
494 size = QueryDepthSList(&slist_header);
495 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size);
496 }
497
498 entry = InterlockedFlushSList(&slist_header);
499 for (i = 65536; i > 0; i--)
500 {
501 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry);
502 item = CONTAINING_RECORD(entry, struct item, entry);
503 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value);
504 entry = item->entry.Next;
505 HeapFree(GetProcessHeap(), 0, item);
506 }
507 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
508 size = QueryDepthSList(&slist_header);
509 ok(size == 0, "Expected size == 0, got %u\n", size);
510 entry = InterlockedPopEntrySList(&slist_header);
511 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry);
512}
513
514static void test_event(void)
515{
516 HANDLE handle, handle2;
517 SECURITY_ATTRIBUTES sa;
518 SECURITY_DESCRIPTOR sd;
519 ACL acl;
520 DWORD ret;
521 BOOL val;
522
523 /* no sd */
524#if defined(__REACTOS__) && defined(_MSC_VER)
525 handle = CreateEventA(NULL, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
526#else
527 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
528#endif
529 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
530 CloseHandle(handle);
531
532 sa.nLength = sizeof(sa);
533 sa.lpSecurityDescriptor = &sd;
534 sa.bInheritHandle = FALSE;
535
536 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
537
538 /* blank sd */
539#if defined(__REACTOS__) && defined(_MSC_VER)
540 handle = CreateEventA(&sa, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
541#else
542 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
543#endif
544 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
545 CloseHandle(handle);
546
547 /* sd with NULL dacl */
548 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
549#if defined(__REACTOS__) && defined(_MSC_VER)
550 handle = CreateEventA(&sa, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
551#else
552 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
553#endif
554 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
555 CloseHandle(handle);
556
557 /* sd with empty dacl */
558 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
559 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
560#if defined(__REACTOS__) && defined(_MSC_VER)
561 handle = CreateEventA(&sa, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
562#else
563 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
564#endif
565 ok(handle != NULL, "CreateEventW with blank sd failed with error %ld\n", GetLastError());
566 CloseHandle(handle);
567
568 /* test case sensitivity */
569
570 SetLastError(0xdeadbeef);
571#if defined(__REACTOS__) && defined(_MSC_VER)
572 handle = CreateEventA(NULL, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
573#else
574 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
575#endif
576 ok( handle != NULL, "CreateEvent failed with error %lu\n", GetLastError());
577 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
578
579 SetLastError(0xdeadbeef);
580#if defined(__REACTOS__) && defined(_MSC_VER)
581 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
582#else
583 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
584#endif
585 ok( handle2 != NULL, "CreateEvent failed with error %ld\n", GetLastError());
586 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
587 CloseHandle( handle2 );
588
589 SetLastError(0xdeadbeef);
590#if defined(__REACTOS__) && defined(_MSC_VER)
591 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE_FW_SLASH__ ": TEST EVENT");
592#else
593 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
594#endif
595 ok( handle2 != NULL, "CreateEvent failed with error %ld\n", GetLastError());
596 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
597 CloseHandle( handle2 );
598
599 SetLastError(0xdeadbeef);
600#if defined(__REACTOS__) && defined(_MSC_VER)
601 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": Test Event");
602#else
603 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
604#endif
605 ok( handle2 != NULL, "OpenEvent failed with error %ld\n", GetLastError());
606 CloseHandle( handle2 );
607
608 SetLastError(0xdeadbeef);
609#if defined(__REACTOS__) && defined(_MSC_VER)
610 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": TEST EVENT");
611#else
612 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
613#endif
614 ok( !handle2, "OpenEvent succeeded\n");
615 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
616
617 SetLastError(0xdeadbeef);
618 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, NULL );
619 ok( !handle2, "OpenEvent succeeded\n");
620 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
621
622 SetLastError(0xdeadbeef);
623 handle2 = OpenEventW( EVENT_ALL_ACCESS, FALSE, NULL );
624 ok( !handle2, "OpenEvent succeeded\n");
625 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
626
627 CloseHandle( handle );
628
629 /* resource notifications are events too */
630
631 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
632 {
633 trace( "memory resource notifications not supported\n" );
634 return;
635 }
636 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
637 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
638 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
639 ret = pQueryMemoryResourceNotification( handle, &val );
640 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
641 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
642
643 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
644 ok( handle != 0, "CreateMemoryResourceNotification failed err %lu\n", GetLastError() );
645 ret = WaitForSingleObject( handle, 10 );
646 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %lu\n", ret );
647
648 val = ~0;
649 ret = pQueryMemoryResourceNotification( handle, &val );
650 ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() );
651 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
652 ret = CloseHandle( handle );
653 ok( ret, "CloseHandle failed err %lu\n", GetLastError() );
654
655#if defined(__REACTOS__) && defined(_MSC_VER)
656 handle = CreateEventA(NULL, FALSE, FALSE, __FILE_FW_SLASH__ ": Test Event");
657#else
658 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
659#endif
660 val = ~0;
661 ret = pQueryMemoryResourceNotification( handle, &val );
662 ok( ret, "QueryMemoryResourceNotification failed err %lu\n", GetLastError() );
663 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
664 CloseHandle( handle );
665}
666
667static void test_semaphore(void)
668{
669 HANDLE handle, handle2;
670
671 /* test case sensitivity */
672
673 SetLastError(0xdeadbeef);
674#if defined(__REACTOS__) && defined(_MSC_VER)
675 handle = CreateSemaphoreA(NULL, 0, 1, __FILE_FW_SLASH__ ": Test Semaphore");
676#else
677 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
678#endif
679 ok(handle != NULL, "CreateSemaphore failed with error %lu\n", GetLastError());
680 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
681
682 SetLastError(0xdeadbeef);
683#if defined(__REACTOS__) && defined(_MSC_VER)
684 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE_FW_SLASH__ ": Test Semaphore");
685#else
686 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
687#endif
688 ok( handle2 != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
689 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
690 CloseHandle( handle2 );
691
692 SetLastError(0xdeadbeef);
693#if defined(__REACTOS__) && defined(_MSC_VER)
694 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE_FW_SLASH__ ": TEST SEMAPHORE");
695#else
696 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
697#endif
698 ok( handle2 != NULL, "CreateSemaphore failed with error %ld\n", GetLastError());
699 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
700 CloseHandle( handle2 );
701
702 SetLastError(0xdeadbeef);
703#if defined(__REACTOS__) && defined(_MSC_VER)
704 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": Test Semaphore");
705#else
706 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
707#endif
708 ok( handle2 != NULL, "OpenSemaphore failed with error %ld\n", GetLastError());
709 CloseHandle( handle2 );
710
711 SetLastError(0xdeadbeef);
712#if defined(__REACTOS__) && defined(_MSC_VER)
713 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": TEST SEMAPHORE");
714#else
715 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
716#endif
717 ok( !handle2, "OpenSemaphore succeeded\n");
718 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
719
720 SetLastError(0xdeadbeef);
721 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
722 ok( !handle2, "OpenSemaphore succeeded\n");
723 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
724
725 SetLastError(0xdeadbeef);
726 handle2 = OpenSemaphoreW( SEMAPHORE_ALL_ACCESS, FALSE, NULL );
727 ok( !handle2, "OpenSemaphore succeeded\n");
728 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
729
730 CloseHandle( handle );
731}
732
733static void test_waitable_timer(void)
734{
735 HANDLE handle, handle2;
736
737 /* test case sensitivity */
738
739 SetLastError(0xdeadbeef);
740#if defined(__REACTOS__) && defined(_MSC_VER)
741 handle = CreateWaitableTimerA(NULL, FALSE, __FILE_FW_SLASH__ ": Test WaitableTimer");
742#else
743 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
744#endif
745 ok(handle != NULL, "CreateWaitableTimer failed with error %lu\n", GetLastError());
746 ok(GetLastError() == 0, "wrong error %lu\n", GetLastError());
747
748 SetLastError(0xdeadbeef);
749#if defined(__REACTOS__) && defined(_MSC_VER)
750 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE_FW_SLASH__ ": Test WaitableTimer");
751#else
752 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
753#endif
754 ok( handle2 != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
755 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %lu\n", GetLastError());
756 CloseHandle( handle2 );
757
758 SetLastError(0xdeadbeef);
759#if defined(__REACTOS__) && defined(_MSC_VER)
760 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE_FW_SLASH__ ": TEST WAITABLETIMER");
761#else
762 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
763#endif
764 ok( handle2 != NULL, "CreateWaitableTimer failed with error %ld\n", GetLastError());
765 ok( GetLastError() == 0, "wrong error %lu\n", GetLastError());
766 CloseHandle( handle2 );
767
768 SetLastError(0xdeadbeef);
769#if defined(__REACTOS__) && defined(_MSC_VER)
770 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": Test WaitableTimer");
771#else
772 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
773#endif
774 ok( handle2 != NULL, "OpenWaitableTimer failed with error %ld\n", GetLastError());
775 CloseHandle( handle2 );
776
777 SetLastError(0xdeadbeef);
778#if defined(__REACTOS__) && defined(_MSC_VER)
779 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE_FW_SLASH__ ": TEST WAITABLETIMER");
780#else
781 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
782#endif
783 ok( !handle2, "OpenWaitableTimer succeeded\n");
784 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError());
785
786 SetLastError(0xdeadbeef);
787 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, NULL );
788 ok( !handle2, "OpenWaitableTimer failed with error %ld\n", GetLastError());
789 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
790
791 SetLastError(0xdeadbeef);
792 handle2 = OpenWaitableTimerW( TIMER_ALL_ACCESS, FALSE, NULL );
793 ok( !handle2, "OpenWaitableTimer failed with error %ld\n", GetLastError());
794 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError());
795
796 CloseHandle( handle );
797}
798
799static HANDLE sem = 0;
800
801static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
802{
803 ReleaseSemaphore(sem, 1, NULL);
804}
805
806static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
807
808static void test_iocp_callback(void)
809{
810 char temp_path[MAX_PATH];
811 char filename[MAX_PATH];
812 DWORD ret;
813 BOOL retb;
814 static const char prefix[] = "pfx";
815 HANDLE hFile;
816 HMODULE hmod = GetModuleHandleA("kernel32.dll");
817 DWORD bytesWritten;
818 const char *buffer = "12345678123456781234567812345678";
819 OVERLAPPED overlapped;
820
821 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
822 if(!p_BindIoCompletionCallback) {
823 win_skip("BindIoCompletionCallback not found in this DLL\n");
824 return;
825 }
826
827 sem = CreateSemaphoreW(NULL, 0, 1, NULL);
828 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
829
830 ret = GetTempPathA(MAX_PATH, temp_path);
831 ok(ret != 0, "GetTempPathA error %ld\n", GetLastError());
832 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
833
834 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
835 ok(ret != 0, "GetTempFileNameA error %ld\n", GetLastError());
836
837 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
838 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
839 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
840
841 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
842 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
843 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
844
845 ret = CloseHandle(hFile);
846 ok( ret, "CloseHandle: error %ld\n", GetLastError());
847 ret = DeleteFileA(filename);
848 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
849
850 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
851 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
852 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
853
854 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
855 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
856
857 memset(&overlapped, 0, sizeof(overlapped));
858 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
859 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %ld\n", GetLastError());
860
861 ret = WaitForSingleObject(sem, 5000);
862 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
863 CloseHandle(sem);
864
865 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
866 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
867 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
868 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
869 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
870 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %ld\n", GetLastError());
871
872 ret = CloseHandle(hFile);
873 ok( ret, "CloseHandle: error %ld\n", GetLastError());
874 ret = DeleteFileA(filename);
875 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
876
877 /* win2k3 requires the Flags parameter to be zero */
878 SetLastError(0xdeadbeef);
879 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
880 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
881 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
882 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
883 if (!retb)
884 ok(GetLastError() == ERROR_INVALID_PARAMETER,
885 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
886 else
887 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
888 ret = CloseHandle(hFile);
889 ok( ret, "CloseHandle: error %ld\n", GetLastError());
890 ret = DeleteFileA(filename);
891 ok( ret, "DeleteFileA: error %ld\n", GetLastError());
892
893 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
894 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
895 ok(GetLastError() == ERROR_INVALID_HANDLE ||
896 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
897 "Last error is %ld\n", GetLastError());
898}
899
900static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
901{
902 int *pn = p;
903 ok(timedOut, "Timer callbacks should always time out\n");
904 ++*pn;
905}
906
907struct timer_queue_data1
908{
909 int num_calls;
910 int max_calls;
911 HANDLE q, t;
912};
913
914static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
915{
916 struct timer_queue_data1 *d = p;
917 ok(timedOut, "Timer callbacks should always time out\n");
918 if (d->t && ++d->num_calls == d->max_calls)
919 {
920 BOOL ret;
921 SetLastError(0xdeadbeef);
922 /* Note, XP SP2 does *not* do any deadlock checking, so passing
923 INVALID_HANDLE_VALUE here will just hang. */
924 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
925 ok(!ret, "DeleteTimerQueueTimer\n");
926 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
927 }
928}
929
930static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
931{
932 struct timer_queue_data1 *d = p;
933 ok(timedOut, "Timer callbacks should always time out\n");
934 if (d->t && ++d->num_calls == d->max_calls)
935 {
936 /* Basically kill the timer since it won't have time to run
937 again. */
938 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0);
939 ok(ret, "ChangeTimerQueueTimer\n");
940 }
941}
942
943static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
944{
945 struct timer_queue_data1 *d = p;
946 ok(timedOut, "Timer callbacks should always time out\n");
947 if (d->t)
948 {
949 /* This tests whether a timer gets flagged for deletion before
950 or after the callback runs. If we start this timer with a
951 period of zero (run once), then ChangeTimerQueueTimer will
952 fail if the timer is already flagged. Hence we really run
953 only once. Otherwise we will run multiple times. */
954 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50);
955 ok(ret, "ChangeTimerQueueTimer\n");
956 ++d->num_calls;
957 }
958}
959
960static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
961{
962 DWORD_PTR delay = (DWORD_PTR) p;
963 ok(timedOut, "Timer callbacks should always time out\n");
964 if (delay)
965 Sleep(delay);
966}
967
968static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
969{
970 struct timer_queue_data1 *d = p;
971 ok(timedOut, "Timer callbacks should always time out\n");
972 /* This tests an original implementation bug where a deleted timer may get
973 to run, but it is tricky to set up. */
974 if (d->q && d->num_calls++ == 0)
975 {
976 /* First run: delete ourselves, then insert and remove a timer
977 that goes in front of us in the sorted timeout list. Once
978 removed, we will still timeout at the faster timer's due time,
979 but this should be a no-op if we are bug-free. There should
980 not be a second run. We can test the value of num_calls later. */
981 BOOL ret;
982 HANDLE t;
983
984 /* The delete will pend while we are in this callback. */
985 SetLastError(0xdeadbeef);
986 ret = DeleteTimerQueueTimer(d->q, d->t, NULL);
987 ok(!ret, "DeleteTimerQueueTimer\n");
988 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
989
990 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
991 ok(ret, "CreateTimerQueueTimer\n");
992 ok(t != NULL, "CreateTimerQueueTimer\n");
993
994 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
995 ok(ret, "DeleteTimerQueueTimer\n");
996
997 /* Now we stay alive by hanging around in the callback. */
998 Sleep(500);
999 }
1000}
1001
1002static void test_timer_queue(void)
1003{
1004 HANDLE q, t0, t1, t2, t3, t4, t5;
1005 int n0, n1, n2, n3, n4, n5;
1006 struct timer_queue_data1 d1, d2, d3, d4;
1007 HANDLE e, et1, et2;
1008 BOOL ret, ret0;
1009
1010 /* Test asynchronous deletion of the queue. */
1011 q = CreateTimerQueue();
1012 ok(q != NULL, "CreateTimerQueue\n");
1013
1014 SetLastError(0xdeadbeef);
1015 ret = DeleteTimerQueueEx(q, NULL);
1016 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1017 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1018 GetLastError());
1019
1020 /* Test synchronous deletion of the queue and running timers. */
1021 q = CreateTimerQueue();
1022 ok(q != NULL, "CreateTimerQueue\n");
1023
1024 /* Not called. */
1025 t0 = NULL;
1026 n0 = 0;
1027 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0);
1028 ok(ret, "CreateTimerQueueTimer\n");
1029 ok(t0 != NULL, "CreateTimerQueueTimer\n");
1030 ret0 = DeleteTimerQueueTimer(q, t0, NULL);
1031 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
1032 broken(ret0), /* Win 2000 & XP & 2003 */
1033 "DeleteTimerQueueTimer ret=%d le=%lu\n", ret0, GetLastError());
1034
1035 /* Called once. */
1036 t1 = NULL;
1037 n1 = 0;
1038 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0);
1039 ok(ret, "CreateTimerQueueTimer\n");
1040 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1041
1042 /* A slow one. */
1043 t2 = NULL;
1044 n2 = 0;
1045 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0);
1046 ok(ret, "CreateTimerQueueTimer\n");
1047 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1048
1049 /* A fast one. */
1050 t3 = NULL;
1051 n3 = 0;
1052 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0);
1053 ok(ret, "CreateTimerQueueTimer\n");
1054 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1055
1056 /* Start really late (it won't start). */
1057 t4 = NULL;
1058 n4 = 0;
1059 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0);
1060 ok(ret, "CreateTimerQueueTimer\n");
1061 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1062
1063 /* Start soon, but delay so long it won't run again. */
1064 t5 = NULL;
1065 n5 = 0;
1066 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0);
1067 ok(ret, "CreateTimerQueueTimer\n");
1068 ok(t5 != NULL, "CreateTimerQueueTimer\n");
1069
1070 /* Give them a chance to do some work. */
1071 Sleep(500);
1072
1073 /* Test deleting a once-only timer. */
1074 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
1075 ok(ret, "DeleteTimerQueueTimer\n");
1076
1077 /* A periodic timer. */
1078 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1079 ok(ret, "DeleteTimerQueueTimer\n");
1080
1081 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1082 ok(ret, "DeleteTimerQueueEx\n");
1083 todo_wine
1084 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
1085 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
1086 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
1087 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
1088 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
1089
1090 /* Test synchronous deletion of the timer/queue with event trigger. */
1091 e = CreateEventW(NULL, TRUE, FALSE, NULL);
1092 et1 = CreateEventW(NULL, TRUE, FALSE, NULL);
1093 et2 = CreateEventW(NULL, TRUE, FALSE, NULL);
1094 if (!e || !et1 || !et2)
1095 {
1096 skip("Failed to create timer queue descruction event\n");
1097 return;
1098 }
1099
1100 q = CreateTimerQueue();
1101 ok(q != NULL, "CreateTimerQueue\n");
1102
1103 /* Run once and finish quickly (should be done when we delete it). */
1104 t1 = NULL;
1105 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
1106 ok(ret, "CreateTimerQueueTimer\n");
1107 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1108
1109 /* Run once and finish slowly (shouldn't be done when we delete it). */
1110 t2 = NULL;
1111 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
1112 ok(ret, "CreateTimerQueueTimer\n");
1113 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1114
1115 /* Run once and finish quickly (should be done when we delete it). */
1116 t3 = NULL;
1117 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
1118 ok(ret, "CreateTimerQueueTimer\n");
1119 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1120
1121 /* Run once and finish slowly (shouldn't be done when we delete it). */
1122 t4 = NULL;
1123 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0);
1124 ok(ret, "CreateTimerQueueTimer\n");
1125 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1126
1127 /* Give them a chance to start. */
1128 Sleep(400);
1129
1130 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
1131 even if the timer is finished. */
1132 SetLastError(0xdeadbeef);
1133 ret = DeleteTimerQueueTimer(q, t1, NULL);
1134 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1135 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1136 GetLastError());
1137
1138 SetLastError(0xdeadbeef);
1139 ret = DeleteTimerQueueTimer(q, t2, NULL);
1140 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1141 ok(GetLastError() == ERROR_IO_PENDING,
1142 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1143 GetLastError());
1144
1145 SetLastError(0xdeadbeef);
1146 ret = DeleteTimerQueueTimer(q, t3, et1);
1147 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
1148 ok(GetLastError() == 0xdeadbeef,
1149 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %ld\n",
1150 GetLastError());
1151 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
1152 "Timer destruction event not triggered\n");
1153
1154 SetLastError(0xdeadbeef);
1155 ret = DeleteTimerQueueTimer(q, t4, et2);
1156 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
1157 ok(GetLastError() == ERROR_IO_PENDING,
1158 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1159 GetLastError());
1160 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
1161 "Timer destruction event not triggered\n");
1162
1163 SetLastError(0xdeadbeef);
1164 ret = DeleteTimerQueueEx(q, e);
1165 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1166 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1167 GetLastError());
1168 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
1169 "Queue destruction event not triggered\n");
1170 CloseHandle(e);
1171
1172 /* Test deleting/changing a timer in execution. */
1173 q = CreateTimerQueue();
1174 ok(q != NULL, "CreateTimerQueue\n");
1175
1176 /* Test changing a once-only timer before it fires (this is allowed,
1177 whereas after it fires you cannot). */
1178 n1 = 0;
1179 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0);
1180 ok(ret, "CreateTimerQueueTimer\n");
1181 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1182 ret = ChangeTimerQueueTimer(q, t1, 0, 0);
1183 ok(ret, "ChangeTimerQueueTimer\n");
1184
1185 d2.t = t2 = NULL;
1186 d2.num_calls = 0;
1187 d2.max_calls = 3;
1188 d2.q = q;
1189 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0);
1190 d2.t = t2;
1191 ok(ret, "CreateTimerQueueTimer\n");
1192 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1193
1194 d3.t = t3 = NULL;
1195 d3.num_calls = 0;
1196 d3.max_calls = 4;
1197 d3.q = q;
1198 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0);
1199 d3.t = t3;
1200 ok(ret, "CreateTimerQueueTimer\n");
1201 ok(t3 != NULL, "CreateTimerQueueTimer\n");
1202
1203 d4.t = t4 = NULL;
1204 d4.num_calls = 0;
1205 d4.q = q;
1206 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0);
1207 d4.t = t4;
1208 ok(ret, "CreateTimerQueueTimer\n");
1209 ok(t4 != NULL, "CreateTimerQueueTimer\n");
1210
1211 Sleep(500);
1212
1213 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
1214 ok(ret, "DeleteTimerQueueEx\n");
1215 ok(n1 == 1, "ChangeTimerQueueTimer\n");
1216 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
1217 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
1218 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
1219
1220 /* Test an obscure bug that was in the original implementation. */
1221 q = CreateTimerQueue();
1222 ok(q != NULL, "CreateTimerQueue\n");
1223
1224 /* All the work is done in the callback. */
1225 d1.t = t1 = NULL;
1226 d1.num_calls = 0;
1227 d1.q = q;
1228 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION);
1229 d1.t = t1;
1230 ok(ret, "CreateTimerQueueTimer\n");
1231 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1232
1233 Sleep(750);
1234
1235 SetLastError(0xdeadbeef);
1236 ret = DeleteTimerQueueEx(q, NULL);
1237 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1238 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1239 GetLastError());
1240 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
1241
1242 /* Test functions on the default timer queue. */
1243 t1 = NULL;
1244 n1 = 0;
1245 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0);
1246 ok(ret, "CreateTimerQueueTimer, default queue\n");
1247 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
1248
1249 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1250 ok(ret, "ChangeTimerQueueTimer, default queue\n");
1251
1252 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1253 ok(ret, "DeleteTimerQueueTimer, default queue\n");
1254
1255 /* Try mixing default and non-default queues. Apparently this works. */
1256 q = CreateTimerQueue();
1257 ok(q != NULL, "CreateTimerQueue\n");
1258
1259 t1 = NULL;
1260 n1 = 0;
1261 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0);
1262 ok(ret, "CreateTimerQueueTimer\n");
1263 ok(t1 != NULL, "CreateTimerQueueTimer\n");
1264
1265 t2 = NULL;
1266 n2 = 0;
1267 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0);
1268 ok(ret, "CreateTimerQueueTimer\n");
1269 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1270
1271 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1272 ok(ret, "ChangeTimerQueueTimer\n");
1273
1274 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000);
1275 ok(ret, "ChangeTimerQueueTimer\n");
1276
1277 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1278 ok(ret, "DeleteTimerQueueTimer\n");
1279
1280 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1281 ok(ret, "DeleteTimerQueueTimer\n");
1282
1283 /* Try to delete the default queue? In any case: not allowed. */
1284 SetLastError(0xdeadbeef);
1285 ret = DeleteTimerQueueEx(NULL, NULL);
1286 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1287 ok(GetLastError() == ERROR_INVALID_HANDLE,
1288 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %ld\n",
1289 GetLastError());
1290
1291 SetLastError(0xdeadbeef);
1292 ret = DeleteTimerQueueEx(q, NULL);
1293 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1294 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %ld\n",
1295 GetLastError());
1296}
1297
1298static HANDLE modify_handle(HANDLE handle, DWORD modify)
1299{
1300 DWORD tmp = HandleToULong(handle);
1301 tmp |= modify;
1302 return ULongToHandle(tmp);
1303}
1304
1305static void test_WaitForSingleObject(void)
1306{
1307 HANDLE signaled, nonsignaled, invalid;
1308 LARGE_INTEGER timeout;
1309 NTSTATUS status;
1310 DWORD ret;
1311
1312 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1313 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1314 invalid = (HANDLE) 0xdeadbee0;
1315
1316 /* invalid handle with different values for lower 2 bits */
1317 SetLastError(0xdeadbeef);
1318 ret = WaitForSingleObject(invalid, 0);
1319 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1320 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1321
1322 SetLastError(0xdeadbeef);
1323 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1324 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1325 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1326
1327 SetLastError(0xdeadbeef);
1328 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1329 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1330 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1331
1332 SetLastError(0xdeadbeef);
1333 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1334 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret);
1335 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
1336
1337 /* valid handle with different values for lower 2 bits */
1338 SetLastError(0xdeadbeef);
1339 ret = WaitForSingleObject(nonsignaled, 0);
1340 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1341 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1342
1343 SetLastError(0xdeadbeef);
1344 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1345 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1346 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1347
1348 SetLastError(0xdeadbeef);
1349 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1350 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1351 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1352
1353 SetLastError(0xdeadbeef);
1354 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1355 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %ld\n", ret);
1356 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1357
1358 /* valid handle with different values for lower 2 bits */
1359 SetLastError(0xdeadbeef);
1360 ret = WaitForSingleObject(signaled, 0);
1361 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1362 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1363
1364 SetLastError(0xdeadbeef);
1365 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1366 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1367 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1368
1369 SetLastError(0xdeadbeef);
1370 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1371 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1372 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1373
1374 SetLastError(0xdeadbeef);
1375 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1376 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret);
1377 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
1378
1379 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */
1380 ret = WaitForSingleObject(GetCurrentProcess(), 100);
1381 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret);
1382
1383 ret = WaitForSingleObject(GetCurrentThread(), 100);
1384 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret);
1385
1386 timeout.QuadPart = -1000000;
1387 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout);
1388 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status);
1389
1390 timeout.QuadPart = -1000000;
1391 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout);
1392 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status);
1393
1394 CloseHandle(signaled);
1395 CloseHandle(nonsignaled);
1396}
1397
1398static void test_WaitForMultipleObjects(void)
1399{
1400 LARGE_INTEGER timeout;
1401 NTSTATUS status;
1402 DWORD r;
1403 int i;
1404 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1405
1406 /* create the maximum number of events and make sure
1407 * we can wait on that many */
1408 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1409 {
1410 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL);
1411 ok( maxevents[i] != 0, "should create enough events\n");
1412 }
1413
1414 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1415 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1416 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %ld\n", r);
1417 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1418 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %ld\n", r);
1419 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1420 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1421 {
1422 /* the lowest index is checked first and remaining events are untouched */
1423 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0);
1424 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %ld\n", i, r);
1425 }
1426
1427 /* run same test with Nt* call */
1428 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1429 SetEvent(maxevents[i]);
1430
1431 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1432 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1433#if defined(__REACTOS__) && defined(_WIN64)
1434 ok(status == STATUS_WAIT_0 || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */, "should signal lowest handle first, got %08lx\n", status);
1435#else
1436 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08lx\n", status);
1437#endif
1438 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1439#if defined(__REACTOS__) && defined(_WIN64)
1440 ok(status == STATUS_WAIT_0 || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */, "should signal handle #0 first, got %08lx\n", status);
1441#else
1442 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08lx\n", status);
1443#endif
1444 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1445 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1446 {
1447 /* the lowest index is checked first and remaining events are untouched */
1448 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL);
1449#if defined(__REACTOS__) && defined(_WIN64)
1450 ok(status == STATUS_WAIT_0 + i || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */, "should signal handle #%d first, got %08lx\n", i, status);
1451#else
1452 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08lx\n", i, status);
1453#endif
1454 }
1455
1456 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1457 if (maxevents[i]) CloseHandle(maxevents[i]);
1458
1459 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in
1460 * WaitForMultipleObjects and NtWaitForMultipleObjects */
1461 maxevents[0] = GetCurrentProcess();
1462 SetLastError(0xdeadbeef);
1463 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1464 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r);
1465#if defined(__REACTOS__) && defined(_WIN64)
1466 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */,
1467#else
1468 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1469#endif
1470 "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError());
1471
1472 maxevents[0] = GetCurrentThread();
1473 SetLastError(0xdeadbeef);
1474 r = WaitForMultipleObjects(1, maxevents, FALSE, 100);
1475 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r);
1476#if defined(__REACTOS__) && defined(_WIN64)
1477 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */,
1478#else
1479 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
1480#endif
1481 "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError());
1482
1483 timeout.QuadPart = -1000000;
1484 maxevents[0] = GetCurrentProcess();
1485 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1486#if defined(__REACTOS__) && defined(_WIN64)
1487 todo_wine ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1488#else
1489 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1490#endif
1491
1492 timeout.QuadPart = -1000000;
1493 maxevents[0] = GetCurrentThread();
1494 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout);
1495#if defined(__REACTOS__) && defined(_WIN64)
1496 todo_wine ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_PARAMETER_3) /* x86_64 */, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1497#else
1498 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
1499#endif
1500}
1501
1502static BOOL g_initcallback_ret, g_initcallback_called;
1503static void *g_initctxt;
1504
1505static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1506{
1507 g_initcallback_called = TRUE;
1508 /* zero bit set means here that initialization is taking place - initialization locked */
1509 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1510 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1511 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1512 return g_initcallback_ret;
1513}
1514
1515static void test_initonce(void)
1516{
1517 INIT_ONCE initonce;
1518 BOOL ret, pending;
1519
1520 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1521 {
1522 win_skip("one-time initialization API not supported\n");
1523 return;
1524 }
1525
1526 /* blocking initialization with callback */
1527 initonce.Ptr = (void*)0xdeadbeef;
1528 pInitOnceInitialize(&initonce);
1529 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1530
1531 /* initialisation completed successfully */
1532 g_initcallback_ret = TRUE;
1533 g_initctxt = NULL;
1534 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1535 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1536 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1537 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1538 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1539
1540 /* so it's been called already so won't be called again */
1541 g_initctxt = NULL;
1542 g_initcallback_called = FALSE;
1543 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1544 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1545 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1546 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1547 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1548
1549 pInitOnceInitialize(&initonce);
1550 g_initcallback_called = FALSE;
1551 /* 2 lower order bits should never be used, you'll get a crash in result */
1552 g_initctxt = (void*)0xFFFFFFF0;
1553 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1554 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1555 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1556 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1557 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1558
1559 /* callback failed */
1560 g_initcallback_ret = FALSE;
1561 g_initcallback_called = FALSE;
1562 g_initctxt = NULL;
1563 pInitOnceInitialize(&initonce);
1564 SetLastError( 0xdeadbeef );
1565 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1566 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %lu\n", ret, GetLastError());
1567 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1568 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1569 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1570
1571 /* blocking initialization without a callback */
1572 pInitOnceInitialize(&initonce);
1573 g_initctxt = NULL;
1574 pending = FALSE;
1575 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1576 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1577 ok(pending, "got %d\n", pending);
1578 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1579 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1580 /* another attempt to begin initialization with block a single thread */
1581
1582 g_initctxt = NULL;
1583 pending = 0xf;
1584 SetLastError( 0xdeadbeef );
1585 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1586 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1587 ok(pending == 0xf, "got %d\n", pending);
1588 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1589 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1590
1591 g_initctxt = (void*)0xdeadbee0;
1592 SetLastError( 0xdeadbeef );
1593 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1594 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1595 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1596
1597 /* once failed already */
1598 g_initctxt = (void*)0xdeadbee0;
1599 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1600 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1601 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1602
1603 pInitOnceInitialize(&initonce);
1604 SetLastError( 0xdeadbeef );
1605 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1606 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1607 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1608
1609 SetLastError( 0xdeadbeef );
1610 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1611 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1612 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1613
1614 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1615 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1616 ok(pending, "got %d\n", pending);
1617 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1618
1619 SetLastError( 0xdeadbeef );
1620 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1621 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1622
1623 SetLastError( 0xdeadbeef );
1624 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1625 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1626 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1627
1628 SetLastError( 0xdeadbeef );
1629 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef);
1630 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1631 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1632
1633 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1634 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1635 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1636
1637 pInitOnceInitialize(&initonce);
1638 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1639 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1640 ok(pending, "got %d\n", pending);
1641 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1642
1643 SetLastError( 0xdeadbeef );
1644 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1645 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1646
1647 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1648 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1649 ok(pending, "got %d\n", pending);
1650 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1651
1652 SetLastError( 0xdeadbeef );
1653 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL);
1654 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1655 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1656
1657 SetLastError( 0xdeadbeef );
1658 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1659 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1660 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1661
1662 SetLastError( 0xdeadbeef );
1663 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef);
1664 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1665 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1666
1667 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1668 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1669 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1670
1671 SetLastError( 0xdeadbeef );
1672 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL);
1673 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1674 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1675
1676 pInitOnceInitialize(&initonce);
1677 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1678 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1679 ok(pending, "got %d\n", pending);
1680 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1681
1682 /* test INIT_ONCE_CHECK_ONLY */
1683
1684 pInitOnceInitialize(&initonce);
1685 SetLastError( 0xdeadbeef );
1686 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1687 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1688 SetLastError( 0xdeadbeef );
1689 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1690 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1691
1692 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1693 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1694 ok(pending, "got %d\n", pending);
1695 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1696
1697 SetLastError( 0xdeadbeef );
1698 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1699 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1700 SetLastError( 0xdeadbeef );
1701 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1702 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1703
1704 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0);
1705 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1706 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1707
1708 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1709 ok(ret, "got wrong ret value %d err %lu\n", ret, GetLastError());
1710 ok(!pending, "got %d\n", pending);
1711 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1712 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1713
1714 SetLastError( 0xdeadbeef );
1715 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1716 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1717
1718 pInitOnceInitialize(&initonce);
1719 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt);
1720 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1721 ok(pending, "got %d\n", pending);
1722 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr);
1723
1724 SetLastError( 0xdeadbeef );
1725 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1726 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %lu\n", ret, GetLastError());
1727 SetLastError( 0xdeadbeef );
1728 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1729 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1730
1731 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0);
1732 ok(ret, "wrong ret %d err %lu\n", ret, GetLastError());
1733 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1734
1735 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1736 ok(ret, "got wrong ret value %d err %lu\n", ret, GetLastError());
1737 ok(!pending, "got %d\n", pending);
1738 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1739 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr);
1740
1741 SetLastError( 0xdeadbeef );
1742 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt);
1743 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %lu\n", ret, GetLastError());
1744}
1745
1746static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT;
1747static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT;
1748static CRITICAL_SECTION buffercrit;
1749static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1750static LONG bufferlen,totalproduced,totalconsumed;
1751static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1752
1753#define BUFFER_SIZE 5
1754
1755static DWORD WINAPI condvar_producer(LPVOID x) {
1756 DWORD sleepinterval = 5;
1757
1758 while (1) {
1759 Sleep(sleepinterval);
1760 if (sleepinterval > 1)
1761 sleepinterval -= 1;
1762
1763 EnterCriticalSection(&buffercrit);
1764 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1765 condvar_producer_sleepcnt++;
1766 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) {
1767 if (GetLastError() != ERROR_TIMEOUT)
1768 condvar_sleeperr = TRUE;
1769 }
1770 }
1771 if (condvar_stop) {
1772 LeaveCriticalSection(&buffercrit);
1773 break;
1774 }
1775 bufferlen++;
1776 totalproduced++;
1777 LeaveCriticalSection(&buffercrit);
1778 pWakeConditionVariable(&buffernotempty);
1779 }
1780 return 0;
1781}
1782
1783static DWORD WINAPI condvar_consumer(LPVOID x) {
1784 DWORD *cnt = (DWORD*)x;
1785 DWORD sleepinterval = 1;
1786
1787 while (1) {
1788 EnterCriticalSection(&buffercrit);
1789 while ((bufferlen == 0) && !condvar_stop) {
1790 condvar_consumer_sleepcnt++;
1791 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) {
1792 if (GetLastError() != ERROR_TIMEOUT)
1793 condvar_sleeperr = TRUE;
1794 }
1795 }
1796 if (condvar_stop && (bufferlen == 0)) {
1797 LeaveCriticalSection(&buffercrit);
1798 break;
1799 }
1800 bufferlen--;
1801 totalconsumed++;
1802 (*cnt)++;
1803 LeaveCriticalSection(&buffercrit);
1804 pWakeConditionVariable(&buffernotfull);
1805 Sleep(sleepinterval);
1806 if (sleepinterval < 5) sleepinterval += 1;
1807 }
1808 return 0;
1809}
1810
1811static void test_condvars_consumer_producer(void)
1812{
1813 HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
1814 DWORD dummy;
1815 DWORD cnt1,cnt2,cnt3;
1816
1817 if (!pInitializeConditionVariable) {
1818 /* function is not yet in XP, only in newer Windows */
1819 win_skip("no condition variable support.\n");
1820 return;
1821 }
1822
1823 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1824
1825 /* If we have static initialized condition variables, InitializeConditionVariable
1826 * is not strictly necessary.
1827 * pInitializeConditionVariable(&buffernotfull);
1828 */
1829 pInitializeConditionVariable(&buffernotempty);
1830 InitializeCriticalSection(&buffercrit);
1831
1832 /* Larger Test: consumer/producer example */
1833
1834 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
1835
1836 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1837 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1838 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1839 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1840 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1841 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy);
1842
1843 /* Limit run to 0.5 seconds. */
1844 Sleep(500);
1845
1846 /* tear down start */
1847 condvar_stop = TRUE;
1848
1849 /* final wake up call */
1850 pWakeAllConditionVariable (&buffernotfull);
1851 pWakeAllConditionVariable (&buffernotempty);
1852
1853 /* (mostly an implementation detail)
1854 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1855 */
1856
1857 WaitForSingleObject(hp1, 1000);
1858 WaitForSingleObject(hp2, 1000);
1859 WaitForSingleObject(hp3, 1000);
1860 WaitForSingleObject(hc1, 1000);
1861 WaitForSingleObject(hc2, 1000);
1862 WaitForSingleObject(hc3, 1000);
1863
1864 ok(totalconsumed == totalproduced,
1865 "consumed %ld != produced %ld\n", totalconsumed, totalproduced);
1866 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1867
1868 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1869 * one consumer does not get anything to do is possible. */
1870 trace("produced %ld, c1 %ld, c2 %ld, c3 %ld\n", totalproduced, cnt1, cnt2, cnt3);
1871 /* The sleeps of the producer or consumer should not go above 100* produced count,
1872 * otherwise the implementation does not sleep correctly. But yet again, this is
1873 * not hard defined. */
1874 trace("producer sleep %ld, consumer sleep %ld\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1875}
1876
1877/* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1878static DWORD condvar_seq = 0;
1879static CONDITION_VARIABLE aligned_cv;
1880static CRITICAL_SECTION condvar_crit;
1881static SRWLOCK condvar_srwlock;
1882
1883#include "pshpack1.h"
1884static struct
1885{
1886 char c;
1887 CONDITION_VARIABLE cv;
1888} unaligned_cv;
1889#include "poppack.h"
1890
1891/* Sequence of wake/sleep to check boundary conditions:
1892 * 0: init
1893 * 1: producer emits a WakeConditionVariable without consumer waiting.
1894 * 2: consumer sleeps without a wake expecting timeout
1895 * 3: producer emits a WakeAllConditionVariable without consumer waiting.
1896 * 4: consumer sleeps without a wake expecting timeout
1897 * 5: a wake is handed to a SleepConditionVariableCS
1898 * 6: a wakeall is handed to a SleepConditionVariableCS
1899 * 7: sleep after above should timeout
1900 * 8: wake with crit section locked into the sleep timeout
1901 *
1902 * the following tests will only be executed if InitializeSRWLock is available
1903 *
1904 * 9: producer (exclusive) wakes up consumer (exclusive)
1905 * 10: producer (exclusive) wakes up consumer (shared)
1906 * 11: producer (shared) wakes up consumer (exclusive)
1907 * 12: producer (shared) wakes up consumer (shared)
1908 * 13: end
1909 */
1910static DWORD WINAPI condvar_base_producer(void *arg)
1911{
1912 CONDITION_VARIABLE *cv = arg;
1913
1914 while (condvar_seq < 1) Sleep(1);
1915
1916 pWakeConditionVariable(cv);
1917 condvar_seq = 2;
1918
1919 while (condvar_seq < 3) Sleep(1);
1920 pWakeAllConditionVariable(cv);
1921 condvar_seq = 4;
1922
1923 while (condvar_seq < 5) Sleep(1);
1924 EnterCriticalSection (&condvar_crit);
1925 pWakeConditionVariable(cv);
1926 LeaveCriticalSection (&condvar_crit);
1927 while (condvar_seq < 6) Sleep(1);
1928 EnterCriticalSection (&condvar_crit);
1929 pWakeAllConditionVariable(cv);
1930 LeaveCriticalSection (&condvar_crit);
1931
1932 while (condvar_seq < 8) Sleep(1);
1933 EnterCriticalSection (&condvar_crit);
1934 pWakeConditionVariable(cv);
1935 Sleep(50);
1936 LeaveCriticalSection (&condvar_crit);
1937
1938 /* skip over remaining tests if InitializeSRWLock is not available */
1939 if (!pInitializeSRWLock)
1940 return 0;
1941
1942 while (condvar_seq < 9) Sleep(1);
1943 pAcquireSRWLockExclusive(&condvar_srwlock);
1944 pWakeConditionVariable(cv);
1945 pReleaseSRWLockExclusive(&condvar_srwlock);
1946
1947 while (condvar_seq < 10) Sleep(1);
1948 pAcquireSRWLockExclusive(&condvar_srwlock);
1949 pWakeConditionVariable(cv);
1950 pReleaseSRWLockExclusive(&condvar_srwlock);
1951
1952 while (condvar_seq < 11) Sleep(1);
1953 pAcquireSRWLockShared(&condvar_srwlock);
1954 pWakeConditionVariable(cv);
1955 pReleaseSRWLockShared(&condvar_srwlock);
1956
1957 while (condvar_seq < 12) Sleep(1);
1958 Sleep(50); /* ensure that consumer waits for cond variable */
1959 pAcquireSRWLockShared(&condvar_srwlock);
1960 pWakeConditionVariable(cv);
1961 pReleaseSRWLockShared(&condvar_srwlock);
1962
1963 return 0;
1964}
1965
1966static DWORD WINAPI condvar_base_consumer(void *arg)
1967{
1968 CONDITION_VARIABLE *cv = arg;
1969 BOOL ret;
1970
1971 while (condvar_seq < 2) Sleep(1);
1972
1973 /* wake was emitted, but we were not sleeping */
1974 EnterCriticalSection (&condvar_crit);
1975 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1976 LeaveCriticalSection (&condvar_crit);
1977 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1978 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
1979
1980 condvar_seq = 3;
1981 while (condvar_seq < 4) Sleep(1);
1982
1983 /* wake all was emitted, but we were not sleeping */
1984 EnterCriticalSection (&condvar_crit);
1985 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
1986 LeaveCriticalSection (&condvar_crit);
1987 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1988 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
1989
1990 EnterCriticalSection (&condvar_crit);
1991 condvar_seq = 5;
1992 ret = pSleepConditionVariableCS(cv, &condvar_crit, 200);
1993 LeaveCriticalSection (&condvar_crit);
1994 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
1995
1996 EnterCriticalSection (&condvar_crit);
1997 condvar_seq = 6;
1998 ret = pSleepConditionVariableCS(cv, &condvar_crit, 200);
1999 LeaveCriticalSection (&condvar_crit);
2000 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
2001 condvar_seq = 7;
2002
2003 EnterCriticalSection (&condvar_crit);
2004 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
2005 LeaveCriticalSection (&condvar_crit);
2006 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
2007 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %ld\n", GetLastError());
2008
2009 EnterCriticalSection (&condvar_crit);
2010 condvar_seq = 8;
2011 ret = pSleepConditionVariableCS(cv, &condvar_crit, 20);
2012 LeaveCriticalSection (&condvar_crit);
2013 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
2014
2015 /* skip over remaining tests if InitializeSRWLock is not available */
2016 if (!pInitializeSRWLock)
2017 {
2018 win_skip("no srw lock support.\n");
2019 condvar_seq = 13; /* end */
2020 return 0;
2021 }
2022
2023 pAcquireSRWLockExclusive(&condvar_srwlock);
2024 condvar_seq = 9;
2025 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0);
2026 pReleaseSRWLockExclusive(&condvar_srwlock);
2027 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
2028
2029 pAcquireSRWLockShared(&condvar_srwlock);
2030 condvar_seq = 10;
2031 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
2032 pReleaseSRWLockShared(&condvar_srwlock);
2033 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
2034
2035 pAcquireSRWLockExclusive(&condvar_srwlock);
2036 condvar_seq = 11;
2037 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, 0);
2038 pReleaseSRWLockExclusive(&condvar_srwlock);
2039 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
2040
2041 pAcquireSRWLockShared(&condvar_srwlock);
2042 condvar_seq = 12;
2043 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED);
2044 pReleaseSRWLockShared(&condvar_srwlock);
2045 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n");
2046
2047 condvar_seq = 13;
2048 return 0;
2049}
2050
2051static void test_condvars_base(RTL_CONDITION_VARIABLE *cv)
2052{
2053 HANDLE hp, hc;
2054 DWORD dummy;
2055 BOOL ret;
2056
2057 if (!pInitializeConditionVariable) {
2058 /* function is not yet in XP, only in newer Windows */
2059 win_skip("no condition variable support.\n");
2060 return;
2061 }
2062
2063 InitializeCriticalSection (&condvar_crit);
2064
2065 if (pInitializeSRWLock)
2066 pInitializeSRWLock(&condvar_srwlock);
2067
2068 EnterCriticalSection (&condvar_crit);
2069 ret = pSleepConditionVariableCS(cv, &condvar_crit, 10);
2070 LeaveCriticalSection (&condvar_crit);
2071
2072 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
2073 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
2074
2075 if (pInitializeSRWLock)
2076 {
2077 pAcquireSRWLockExclusive(&condvar_srwlock);
2078 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, 0);
2079 pReleaseSRWLockExclusive(&condvar_srwlock);
2080
2081 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
2082 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
2083
2084 pAcquireSRWLockShared(&condvar_srwlock);
2085 ret = pSleepConditionVariableSRW(cv, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED);
2086 pReleaseSRWLockShared(&condvar_srwlock);
2087
2088 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n");
2089 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %ld\n", GetLastError());
2090 }
2091
2092 condvar_seq = 0;
2093 hp = CreateThread(NULL, 0, condvar_base_producer, cv, 0, &dummy);
2094 hc = CreateThread(NULL, 0, condvar_base_consumer, cv, 0, &dummy);
2095
2096 condvar_seq = 1; /* go */
2097
2098 while (condvar_seq < 9)
2099 Sleep (5);
2100 WaitForSingleObject(hp, 100);
2101 WaitForSingleObject(hc, 100);
2102}
2103
2104static LONG srwlock_seq = 0;
2105static SRWLOCK aligned_srwlock;
2106static struct
2107{
2108 LONG wrong_execution_order;
2109 LONG samethread_excl_excl;
2110 LONG samethread_excl_shared;
2111 LONG samethread_shared_excl;
2112 LONG multithread_excl_excl;
2113 LONG excl_not_preferred;
2114 LONG trylock_excl;
2115 LONG trylock_shared;
2116} srwlock_base_errors;
2117
2118#if defined(__i386__) || defined(__x86_64__)
2119#include "pshpack1.h"
2120struct
2121{
2122 char c;
2123 SRWLOCK lock;
2124} unaligned_srwlock;
2125#include "poppack.h"
2126#endif
2127
2128/* Sequence of acquire/release to check boundary conditions:
2129 * 0: init
2130 *
2131 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock
2132 * 2: thread1 expects a deadlock and releases the waiting lock
2133 * thread2 releases the lock again
2134 *
2135 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock
2136 * 4: thread1 expects a deadlock and releases the waiting lock
2137 * thread2 releases the lock again
2138 *
2139 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock
2140 * 6: thread1 expects a deadlock and releases the waiting lock
2141 * thread2 releases the lock again
2142 *
2143 * 7: thread2 acquires and releases two nested shared locks
2144 *
2145 * 8: thread1 acquires an exclusive lock
2146 * 9: thread2 tries to acquire the exclusive lock, too
2147 * thread1 releases the exclusive lock again
2148 * 10: thread2 enters the exclusive lock and leaves it immediately again
2149 *
2150 * 11: thread1 acquires a shared lock
2151 * 12: thread2 acquires and releases a shared lock
2152 * thread1 releases the lock again
2153 *
2154 * 13: thread1 acquires a shared lock
2155 * 14: thread2 tries to acquire an exclusive lock
2156 * 15: thread3 tries to acquire a shared lock
2157 * 16: thread1 releases the shared lock
2158 * 17: thread2 wakes up and releases the exclusive lock
2159 * 18: thread3 wakes up and releases the shared lock
2160 *
2161 * the following tests will only be executed if TryAcquireSRWLock* is available
2162 *
2163 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE
2164 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2165 * thread1 releases the exclusive lock
2166 *
2167 * thread1 calls TryAcquireSRWLockShared which should return TRUE
2168 * thread1 checks the result of recursive calls to TryAcquireSRWLock*
2169 * thread1 releases the shared lock
2170 *
2171 * thread1 acquires an exclusive lock
2172 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE
2173 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2174 * 21: thread1 releases the exclusive lock
2175 *
2176 * thread1 acquires an shared lock
2177 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE
2178 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2179 * 23: thread1 releases the shared lock
2180 *
2181 * thread1 acquires a shared lock and tries to acquire an exclusive lock
2182 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE
2183 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2184 * 25: thread1 releases the exclusive lock
2185 *
2186 * thread1 acquires two shared locks
2187 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE
2188 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2189 * 27: thread1 releases one shared lock
2190 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE
2191 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE
2192 * 29: thread1 releases the second shared lock
2193 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE
2194 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE
2195 *
2196 * 31: end
2197 */
2198
2199static DWORD WINAPI srwlock_base_thread1(void *arg)
2200{
2201 SRWLOCK *lock = arg;
2202
2203 /* seq 2 */
2204 while (srwlock_seq < 2) Sleep(1);
2205 Sleep(100);
2206 if (InterlockedIncrement(&srwlock_seq) != 3)
2207 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2208 pReleaseSRWLockExclusive(lock);
2209
2210 /* seq 4 */
2211 while (srwlock_seq < 4) Sleep(1);
2212 Sleep(100);
2213 if (InterlockedIncrement(&srwlock_seq) != 5)
2214 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2215 pReleaseSRWLockExclusive(lock);
2216
2217 /* seq 6 */
2218 while (srwlock_seq < 6) Sleep(1);
2219 Sleep(100);
2220 if (InterlockedIncrement(&srwlock_seq) != 7)
2221 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2222 pReleaseSRWLockShared(lock);
2223
2224 /* seq 8 */
2225 while (srwlock_seq < 8) Sleep(1);
2226 pAcquireSRWLockExclusive(lock);
2227 if (InterlockedIncrement(&srwlock_seq) != 9)
2228 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2229 Sleep(100);
2230 if (InterlockedIncrement(&srwlock_seq) != 10)
2231 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2232 pReleaseSRWLockExclusive(lock);
2233
2234 /* seq 11 */
2235 while (srwlock_seq < 11) Sleep(1);
2236 pAcquireSRWLockShared(lock);
2237 if (InterlockedIncrement(&srwlock_seq) != 12)
2238 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2239
2240 /* seq 13 */
2241 while (srwlock_seq < 13) Sleep(1);
2242 pReleaseSRWLockShared(lock);
2243 pAcquireSRWLockShared(lock);
2244 if (InterlockedIncrement(&srwlock_seq) != 14)
2245 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2246
2247 /* seq 16 */
2248 while (srwlock_seq < 16) Sleep(1);
2249 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */
2250 if (InterlockedIncrement(&srwlock_seq) != 17)
2251 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2252 pReleaseSRWLockShared(lock);
2253
2254 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2255 if (!pTryAcquireSRWLockExclusive)
2256 return 0;
2257
2258 /* seq 19 */
2259 while (srwlock_seq < 19) Sleep(1);
2260 if (pTryAcquireSRWLockExclusive(lock))
2261 {
2262 if (pTryAcquireSRWLockShared(lock))
2263 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2264 if (pTryAcquireSRWLockExclusive(lock))
2265 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2266 pReleaseSRWLockExclusive(lock);
2267 }
2268 else
2269 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2270
2271 if (pTryAcquireSRWLockShared(lock))
2272 {
2273 if (pTryAcquireSRWLockShared(lock))
2274 pReleaseSRWLockShared(lock);
2275 else
2276 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2277 if (pTryAcquireSRWLockExclusive(lock))
2278 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2279 pReleaseSRWLockShared(lock);
2280 }
2281 else
2282 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2283
2284 pAcquireSRWLockExclusive(lock);
2285 if (InterlockedIncrement(&srwlock_seq) != 20)
2286 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2287
2288 /* seq 21 */
2289 while (srwlock_seq < 21) Sleep(1);
2290 pReleaseSRWLockExclusive(lock);
2291 pAcquireSRWLockShared(lock);
2292 if (InterlockedIncrement(&srwlock_seq) != 22)
2293 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2294
2295 /* seq 23 */
2296 while (srwlock_seq < 23) Sleep(1);
2297 pReleaseSRWLockShared(lock);
2298 pAcquireSRWLockShared(lock);
2299 if (InterlockedIncrement(&srwlock_seq) != 24)
2300 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2301
2302 /* seq 25 */
2303 pAcquireSRWLockExclusive(lock);
2304 if (srwlock_seq != 25)
2305 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2306 pReleaseSRWLockExclusive(lock);
2307
2308 pAcquireSRWLockShared(lock);
2309 pAcquireSRWLockShared(lock);
2310 if (InterlockedIncrement(&srwlock_seq) != 26)
2311 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2312
2313 /* seq 27 */
2314 while (srwlock_seq < 27) Sleep(1);
2315 pReleaseSRWLockShared(lock);
2316 if (InterlockedIncrement(&srwlock_seq) != 28)
2317 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2318
2319 /* seq 29 */
2320 while (srwlock_seq < 29) Sleep(1);
2321 pReleaseSRWLockShared(lock);
2322 if (InterlockedIncrement(&srwlock_seq) != 30)
2323 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2324
2325 return 0;
2326}
2327
2328static DWORD WINAPI srwlock_base_thread2(void *arg)
2329{
2330 SRWLOCK *lock = arg;
2331
2332 /* seq 1 */
2333 while (srwlock_seq < 1) Sleep(1);
2334 pAcquireSRWLockExclusive(lock);
2335 if (InterlockedIncrement(&srwlock_seq) != 2)
2336 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2337
2338 /* seq 3 */
2339 pAcquireSRWLockExclusive(lock);
2340 if (srwlock_seq != 3)
2341 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl);
2342 pReleaseSRWLockExclusive(lock);
2343 pAcquireSRWLockExclusive(lock);
2344 if (InterlockedIncrement(&srwlock_seq) != 4)
2345 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2346
2347 /* seq 5 */
2348 pAcquireSRWLockShared(lock);
2349 if (srwlock_seq != 5)
2350 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared);
2351 pReleaseSRWLockShared(lock);
2352 pAcquireSRWLockShared(lock);
2353 if (InterlockedIncrement(&srwlock_seq) != 6)
2354 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2355
2356 /* seq 7 */
2357 pAcquireSRWLockExclusive(lock);
2358 if (srwlock_seq != 7)
2359 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl);
2360 pReleaseSRWLockExclusive(lock);
2361 pAcquireSRWLockShared(lock);
2362 pAcquireSRWLockShared(lock);
2363 pReleaseSRWLockShared(lock);
2364 pReleaseSRWLockShared(lock);
2365 if (InterlockedIncrement(&srwlock_seq) != 8)
2366 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2367
2368 /* seq 9, 10 */
2369 while (srwlock_seq < 9) Sleep(1);
2370 pAcquireSRWLockExclusive(lock);
2371 if (srwlock_seq != 10)
2372 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl);
2373 pReleaseSRWLockExclusive(lock);
2374 if (InterlockedIncrement(&srwlock_seq) != 11)
2375 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2376
2377 /* seq 12 */
2378 while (srwlock_seq < 12) Sleep(1);
2379 pAcquireSRWLockShared(lock);
2380 pReleaseSRWLockShared(lock);
2381 if (InterlockedIncrement(&srwlock_seq) != 13)
2382 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2383
2384 /* seq 14 */
2385 while (srwlock_seq < 14) Sleep(1);
2386 if (InterlockedIncrement(&srwlock_seq) != 15)
2387 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2388
2389 /* seq 17 */
2390 pAcquireSRWLockExclusive(lock);
2391 if (srwlock_seq != 17)
2392 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2393 if (InterlockedIncrement(&srwlock_seq) != 18)
2394 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2395 pReleaseSRWLockExclusive(lock);
2396
2397 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2398 if (!pTryAcquireSRWLockExclusive)
2399 return 0;
2400
2401 /* seq 20 */
2402 while (srwlock_seq < 20) Sleep(1);
2403 if (pTryAcquireSRWLockShared(lock))
2404 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2405 if (pTryAcquireSRWLockExclusive(lock))
2406 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2407 if (InterlockedIncrement(&srwlock_seq) != 21)
2408 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2409
2410 /* seq 22 */
2411 while (srwlock_seq < 22) Sleep(1);
2412 if (pTryAcquireSRWLockShared(lock))
2413 pReleaseSRWLockShared(lock);
2414 else
2415 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2416 if (pTryAcquireSRWLockExclusive(lock))
2417 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2418 if (InterlockedIncrement(&srwlock_seq) != 23)
2419 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2420
2421 /* seq 24 */
2422 while (srwlock_seq < 24) Sleep(1);
2423 Sleep(50); /* ensure that exclusive access request is queued */
2424 if (pTryAcquireSRWLockShared(lock))
2425 {
2426 pReleaseSRWLockShared(lock);
2427 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2428 }
2429 if (pTryAcquireSRWLockExclusive(lock))
2430 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2431 if (InterlockedIncrement(&srwlock_seq) != 25)
2432 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2433 pReleaseSRWLockShared(lock);
2434
2435 /* seq 26 */
2436 while (srwlock_seq < 26) Sleep(1);
2437 if (pTryAcquireSRWLockShared(lock))
2438 pReleaseSRWLockShared(lock);
2439 else
2440 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2441 if (pTryAcquireSRWLockExclusive(lock))
2442 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2443 if (InterlockedIncrement(&srwlock_seq) != 27)
2444 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2445
2446 /* seq 28 */
2447 while (srwlock_seq < 28) Sleep(1);
2448 if (pTryAcquireSRWLockShared(lock))
2449 pReleaseSRWLockShared(lock);
2450 else
2451 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2452 if (pTryAcquireSRWLockExclusive(lock))
2453 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2454 if (InterlockedIncrement(&srwlock_seq) != 29)
2455 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2456
2457 /* seq 30 */
2458 while (srwlock_seq < 30) Sleep(1);
2459 if (pTryAcquireSRWLockShared(lock))
2460 pReleaseSRWLockShared(lock);
2461 else
2462 InterlockedIncrement(&srwlock_base_errors.trylock_shared);
2463 if (pTryAcquireSRWLockExclusive(lock))
2464 pReleaseSRWLockExclusive(lock);
2465 else
2466 InterlockedIncrement(&srwlock_base_errors.trylock_excl);
2467 if (InterlockedIncrement(&srwlock_seq) != 31)
2468 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2469
2470 return 0;
2471}
2472
2473static DWORD WINAPI srwlock_base_thread3(void *arg)
2474{
2475 SRWLOCK *lock = arg;
2476
2477 /* seq 15 */
2478 while (srwlock_seq < 15) Sleep(1);
2479 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */
2480 if (InterlockedIncrement(&srwlock_seq) != 16)
2481 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2482
2483 /* seq 18 */
2484 pAcquireSRWLockShared(lock);
2485 if (srwlock_seq != 18)
2486 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred);
2487 pReleaseSRWLockShared(lock);
2488 if (InterlockedIncrement(&srwlock_seq) != 19)
2489 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order);
2490
2491 /* skip over remaining tests if TryAcquireSRWLock* is not available */
2492 if (!pTryAcquireSRWLockExclusive)
2493 {
2494 /* function is only in Windows 7 and newer */
2495 win_skip("no srw trylock support.\n");
2496 srwlock_seq = 31; /* end */
2497 return 0;
2498 }
2499
2500 return 0;
2501}
2502
2503static void test_srwlock_base(SRWLOCK *lock)
2504{
2505 HANDLE h1, h2, h3;
2506 DWORD dummy;
2507
2508 if (!pInitializeSRWLock)
2509 {
2510 /* function is not yet in XP, only in newer Windows */
2511 win_skip("no srw lock support.\n");
2512 return;
2513 }
2514
2515 pInitializeSRWLock(lock);
2516 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors));
2517 srwlock_seq = 0;
2518
2519 h1 = CreateThread(NULL, 0, srwlock_base_thread1, lock, 0, &dummy);
2520 h2 = CreateThread(NULL, 0, srwlock_base_thread2, lock, 0, &dummy);
2521 h3 = CreateThread(NULL, 0, srwlock_base_thread3, lock, 0, &dummy);
2522
2523 srwlock_seq = 1; /* go */
2524 while (srwlock_seq < 31)
2525 Sleep(5);
2526
2527 WaitForSingleObject(h1, 100);
2528 WaitForSingleObject(h2, 100);
2529 WaitForSingleObject(h3, 100);
2530
2531 ok(!srwlock_base_errors.wrong_execution_order,
2532 "thread commands were executed in the wrong order (occurred %ld times).\n",
2533 srwlock_base_errors.wrong_execution_order);
2534
2535 ok(!srwlock_base_errors.samethread_excl_excl,
2536 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %ld times).\n",
2537 srwlock_base_errors.samethread_excl_excl);
2538
2539 ok(!srwlock_base_errors.samethread_excl_shared,
2540 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %ld times).\n",
2541 srwlock_base_errors.samethread_excl_shared);
2542
2543 ok(!srwlock_base_errors.samethread_shared_excl,
2544 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %ld times).\n",
2545 srwlock_base_errors.samethread_shared_excl);
2546
2547 ok(!srwlock_base_errors.multithread_excl_excl,
2548 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %ld times).\n",
2549 srwlock_base_errors.multithread_excl_excl);
2550
2551 ok(!srwlock_base_errors.excl_not_preferred,
2552 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %ld times).\n",
2553 srwlock_base_errors.excl_not_preferred);
2554
2555 ok(!srwlock_base_errors.trylock_excl,
2556 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %ld times).\n",
2557 srwlock_base_errors.trylock_excl);
2558
2559 ok(!srwlock_base_errors.trylock_shared,
2560 "TryAcquireSRWLockShared didn't behave as expected (occurred %ld times).\n",
2561 srwlock_base_errors.trylock_shared);
2562
2563}
2564
2565static SRWLOCK srwlock_example;
2566static LONG srwlock_protected_value = 0;
2567static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0;
2568static BOOL srwlock_stop = FALSE;
2569
2570static DWORD WINAPI srwlock_example_thread(LPVOID x) {
2571 DWORD *cnt = x;
2572 LONG old;
2573
2574 while (!srwlock_stop)
2575 {
2576
2577 /* periodically request exclusive access */
2578 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0)
2579 {
2580 pAcquireSRWLockExclusive(&srwlock_example);
2581 if (InterlockedIncrement(&srwlock_inside) != 1)
2582 InterlockedIncrement(&srwlock_example_errors);
2583
2584 InterlockedIncrement(&srwlock_protected_value);
2585 Sleep(1);
2586
2587 if (InterlockedDecrement(&srwlock_inside) != 0)
2588 InterlockedIncrement(&srwlock_example_errors);
2589 pReleaseSRWLockExclusive(&srwlock_example);
2590 }
2591
2592 /* request shared access */
2593 pAcquireSRWLockShared(&srwlock_example);
2594 InterlockedIncrement(&srwlock_inside);
2595 old = srwlock_protected_value;
2596
2597 (*cnt)++;
2598 Sleep(1);
2599
2600 if (old != srwlock_protected_value)
2601 InterlockedIncrement(&srwlock_example_errors);
2602 InterlockedDecrement(&srwlock_inside);
2603 pReleaseSRWLockShared(&srwlock_example);
2604 }
2605
2606 return 0;
2607}
2608
2609static void test_srwlock_example(void)
2610{
2611 HANDLE h1, h2, h3;
2612 DWORD dummy;
2613 DWORD cnt1, cnt2, cnt3;
2614
2615 if (!pInitializeSRWLock) {
2616 /* function is not yet in XP, only in newer Windows */
2617 win_skip("no srw lock support.\n");
2618 return;
2619 }
2620
2621 pInitializeSRWLock(&srwlock_example);
2622
2623 cnt1 = cnt2 = cnt3 = 0;
2624
2625 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy);
2626 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy);
2627 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy);
2628
2629 /* limit run to 1 second. */
2630 Sleep(1000);
2631
2632 /* tear down start */
2633 srwlock_stop = TRUE;
2634
2635 WaitForSingleObject(h1, 1000);
2636 WaitForSingleObject(h2, 1000);
2637 WaitForSingleObject(h3, 1000);
2638
2639 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %ld.\n", srwlock_inside);
2640 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %ld)\n",
2641 srwlock_example_errors);
2642
2643 trace("number of shared accesses per thread are c1 %ld, c2 %ld, c3 %ld\n", cnt1, cnt2, cnt3);
2644 trace("number of total exclusive accesses is %ld\n", srwlock_protected_value);
2645}
2646
2647static void test_srwlock_quirk(void)
2648{
2649 union { SRWLOCK *s; LONG *l; } u = { &srwlock_example };
2650
2651 if (!pInitializeSRWLock) {
2652 /* function is not yet in XP, only in newer Windows */
2653 win_skip("no srw lock support.\n");
2654 return;
2655 }
2656
2657 /* WeCom 4.x checks releasing a lock with value 0x1 results in it becoming 0x0. */
2658 *u.l = 1;
2659 pReleaseSRWLockExclusive(&srwlock_example);
2660 ok(*u.l == 0, "expected 0x0, got %lx\n", *u.l);
2661}
2662
2663static DWORD WINAPI alertable_wait_thread(void *param)
2664{
2665 HANDLE *semaphores = param;
2666 LARGE_INTEGER timeout;
2667 NTSTATUS status;
2668 DWORD result;
2669
2670 ReleaseSemaphore(semaphores[0], 1, NULL);
2671 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE);
2672 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %lu\n", result);
2673 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE);
2674 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2675
2676 ReleaseSemaphore(semaphores[0], 1, NULL);
2677 timeout.QuadPart = -10000000;
2678 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2679 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status);
2680 timeout.QuadPart = -2000000;
2681 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2682 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08lx\n", status);
2683
2684 ReleaseSemaphore(semaphores[0], 1, NULL);
2685 timeout.QuadPart = -10000000;
2686 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout);
2687 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08lx\n", status);
2688 result = WaitForSingleObject(semaphores[0], 0);
2689 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", result);
2690
2691 return 0;
2692}
2693
2694static void CALLBACK alertable_wait_apc(ULONG_PTR userdata)
2695{
2696 HANDLE *semaphores = (void *)userdata;
2697 ReleaseSemaphore(semaphores[1], 1, NULL);
2698}
2699
2700static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata)
2701{
2702 HANDLE *semaphores = (void *)userdata;
2703 DWORD result;
2704
2705 result = WaitForSingleObject(semaphores[0], 1000);
2706 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2707}
2708
2709static void test_alertable_wait(void)
2710{
2711 HANDLE thread, semaphores[2];
2712 DWORD result;
2713
2714 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL);
2715 ok(semaphores[0] != NULL, "CreateSemaphore failed with %lu\n", GetLastError());
2716 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
2717 ok(semaphores[1] != NULL, "CreateSemaphore failed with %lu\n", GetLastError());
2718 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL);
2719 ok(thread != NULL, "CreateThread failed with %lu\n", GetLastError());
2720
2721 result = WaitForSingleObject(semaphores[0], 1000);
2722 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2723 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */
2724 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2725 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2726
2727 result = WaitForSingleObject(semaphores[0], 1000);
2728 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2729 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2730 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores);
2731 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2732
2733 result = WaitForSingleObject(semaphores[0], 1000);
2734 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2735 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */
2736 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2737 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2738 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores);
2739 ok(result != 0, "QueueUserAPC failed with %lu\n", GetLastError());
2740 ReleaseSemaphore(semaphores[0], 2, NULL);
2741
2742 result = WaitForSingleObject(thread, 1000);
2743 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2744 CloseHandle(thread);
2745 CloseHandle(semaphores[0]);
2746 CloseHandle(semaphores[1]);
2747}
2748
2749struct apc_deadlock_info
2750{
2751 PROCESS_INFORMATION *pi;
2752 HANDLE event;
2753 BOOL running;
2754};
2755
2756static DWORD WINAPI apc_deadlock_thread(void *param)
2757{
2758 struct apc_deadlock_info *info = param;
2759 PROCESS_INFORMATION *pi = info->pi;
2760 NTSTATUS status;
2761 SIZE_T size;
2762 void *base;
2763
2764 while (info->running)
2765 {
2766 base = NULL;
2767 size = 0x1000;
2768 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size,
2769 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
2770 ok(!status, "expected STATUS_SUCCESS, got %08lx\n", status);
2771 ok(base != NULL, "expected base != NULL, got %p\n", base);
2772 SetEvent(info->event);
2773
2774 size = 0;
2775 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE);
2776 ok(!status, "expected STATUS_SUCCESS, got %08lx\n", status);
2777 SetEvent(info->event);
2778 }
2779
2780 return 0;
2781}
2782
2783static void test_apc_deadlock(void)
2784{
2785 struct apc_deadlock_info info;
2786 PROCESS_INFORMATION pi;
2787 STARTUPINFOA si = { sizeof(si) };
2788 char cmdline[MAX_PATH];
2789 HANDLE event, thread;
2790 DWORD result;
2791 BOOL success;
2792 char **argv;
2793 int i;
2794
2795 winetest_get_mainargs(&argv);
2796 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]);
2797 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2798 ok(success, "CreateProcess failed with %lu\n", GetLastError());
2799
2800 event = CreateEventA(NULL, FALSE, FALSE, NULL);
2801 ok(event != NULL, "CreateEvent failed with %lu\n", GetLastError());
2802
2803 info.pi = π
2804 info.event = event;
2805 info.running = TRUE;
2806
2807 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL);
2808 ok(thread != NULL, "CreateThread failed with %lu\n", GetLastError());
2809 result = WaitForSingleObject(event, 1000);
2810 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2811
2812 for (i = 0; i < 1000 && info.running; i++)
2813 {
2814 result = SuspendThread(pi.hThread);
2815 ok(result == 0, "expected 0, got %lu\n", result);
2816
2817 WaitForSingleObject(event, 0); /* reset event */
2818 result = WaitForSingleObject(event, 1000);
2819 if (result == WAIT_TIMEOUT)
2820 {
2821 todo_wine
2822 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2823 info.running = FALSE;
2824 }
2825 else
2826 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2827
2828 result = ResumeThread(pi.hThread);
2829 ok(result == 1, "expected 1, got %lu\n", result);
2830 Sleep(1);
2831 }
2832
2833 info.running = FALSE;
2834 result = WaitForSingleObject(thread, 1000);
2835 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %lu\n", result);
2836 CloseHandle(thread);
2837 CloseHandle(event);
2838
2839 TerminateProcess(pi.hProcess, 0);
2840 CloseHandle(pi.hThread);
2841 CloseHandle(pi.hProcess);
2842}
2843
2844static jmp_buf bad_cs_jmpbuf;
2845
2846static LONG WINAPI bad_cs_handler( EXCEPTION_POINTERS *eptr )
2847{
2848 EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
2849
2850 ok(!rec->NumberParameters, "got %lu.\n", rec->NumberParameters);
2851 ok(rec->ExceptionFlags == EXCEPTION_NONCONTINUABLE
2852 || rec->ExceptionFlags == (EXCEPTION_NONCONTINUABLE | EXCEPTION_SOFTWARE_ORIGINATE),
2853 "got %#lx.\n", rec->ExceptionFlags);
2854 longjmp(bad_cs_jmpbuf, rec->ExceptionCode);
2855 return EXCEPTION_CONTINUE_SEARCH;
2856}
2857
2858static void test_crit_section(void)
2859{
2860 void *vectored_handler;
2861 CRITICAL_SECTION cs;
2862 int exc_code;
2863 HANDLE old;
2864 BOOL ret;
2865
2866 /* Win8+ does not initialize debug info, one has to use RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
2867 to override that. */
2868 memset(&cs, 0, sizeof(cs));
2869 InitializeCriticalSection(&cs);
2870 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2871 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2872 DeleteCriticalSection(&cs);
2873 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2874
2875 if (!pInitializeCriticalSectionEx)
2876 {
2877 win_skip("InitializeCriticalSectionEx isn't available, skipping tests.\n");
2878 return;
2879 }
2880
2881 memset(&cs, 0, sizeof(cs));
2882 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2883 ok(ret, "Failed to initialize critical section.\n");
2884 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2885 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2886 DeleteCriticalSection(&cs);
2887 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2888
2889 memset(&cs, 0, sizeof(cs));
2890 ret = pInitializeCriticalSectionEx(&cs, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
2891 ok(ret, "Failed to initialize critical section.\n");
2892 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2893 DeleteCriticalSection(&cs);
2894 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2895
2896 memset(&cs, 0, sizeof(cs));
2897 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2898 ok(ret, "Failed to initialize critical section.\n");
2899 ok(cs.DebugInfo == (void *)(ULONG_PTR)-1 || broken(!!cs.DebugInfo) /* before Win8 */,
2900 "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2901 DeleteCriticalSection(&cs);
2902 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2903
2904 memset(&cs, 0, sizeof(cs));
2905 ret = pInitializeCriticalSectionEx(&cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
2906 ok(ret || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* before Win8 */,
2907 "Failed to initialize critical section, error %lu.\n", GetLastError());
2908 if (!ret)
2909 {
2910 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2911 ok(ret, "Failed to initialize critical section.\n");
2912 }
2913 ok(cs.DebugInfo && cs.DebugInfo != (void *)(ULONG_PTR)-1, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2914
2915 ret = TryEnterCriticalSection(&cs);
2916 ok(ret, "Failed to enter critical section.\n");
2917 LeaveCriticalSection(&cs);
2918
2919 cs.DebugInfo = NULL;
2920
2921 ret = TryEnterCriticalSection(&cs);
2922 ok(ret, "Failed to enter critical section.\n");
2923 LeaveCriticalSection(&cs);
2924
2925 DeleteCriticalSection(&cs);
2926 ok(cs.DebugInfo == NULL, "Unexpected debug info pointer %p.\n", cs.DebugInfo);
2927
2928 ret = pInitializeCriticalSectionEx(&cs, 0, 0);
2929 ok(ret, "got error %lu.\n", GetLastError());
2930 old = cs.LockSemaphore;
2931 cs.LockSemaphore = (HANDLE)0xdeadbeef;
2932
2933 cs.LockCount = 0;
2934 vectored_handler = AddVectoredExceptionHandler(TRUE, bad_cs_handler);
2935 if (!(exc_code = setjmp(bad_cs_jmpbuf)))
2936 EnterCriticalSection(&cs);
2937 ok(cs.LockCount, "got %ld.\n", cs.LockCount);
2938 ok(exc_code == STATUS_INVALID_HANDLE, "got %#x.\n", exc_code);
2939 RemoveVectoredExceptionHandler(vectored_handler);
2940 cs.LockSemaphore = old;
2941 DeleteCriticalSection(&cs);
2942}
2943
2944static DWORD WINAPI thread_proc(LPVOID unused)
2945{
2946 Sleep(INFINITE);
2947 return 0;
2948}
2949
2950static int apc_count;
2951
2952static void CALLBACK user_apc(ULONG_PTR unused)
2953{
2954 apc_count++;
2955}
2956
2957static void CALLBACK call_user_apc(ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)
2958{
2959 PAPCFUNC func = (PAPCFUNC)arg1;
2960 func(arg2);
2961}
2962
2963static void test_QueueUserAPC(void)
2964{
2965 HANDLE thread;
2966 DWORD tid, ret;
2967 NTSTATUS status;
2968
2969 thread = CreateThread(NULL, 0, thread_proc, NULL, CREATE_SUSPENDED, &tid);
2970 ok(thread != NULL, "CreateThread error %lu\n", GetLastError());
2971
2972 ret = TerminateThread(thread, 0xdeadbeef);
2973 ok(ret, "TerminateThread error %lu\n", GetLastError());
2974
2975 ret = WaitForSingleObject(thread, 1000);
2976 ok(ret == WAIT_OBJECT_0, "got %lu\n", ret);
2977
2978 ret = pNtQueueApcThread(thread, call_user_apc, (ULONG_PTR)user_apc, 0, 0);
2979 ok(ret == STATUS_UNSUCCESSFUL, "got %#lx\n", ret);
2980 ret = pNtQueueApcThread(thread, NULL, 0, 0, 0);
2981 ok(ret == STATUS_UNSUCCESSFUL, "got %#lx\n", ret);
2982
2983 SetLastError(0xdeadbeef);
2984 ret = QueueUserAPC(user_apc, thread, 0);
2985 ok(!ret, "QueueUserAPC should fail\n");
2986#ifdef __REACTOS__
2987 ok(GetLastError() == ERROR_GEN_FAILURE || broken(GetLastError() == 0xdeadbeef) /* WS03 */, "got %lu\n", GetLastError());
2988#else
2989 ok(GetLastError() == ERROR_GEN_FAILURE, "got %lu\n", GetLastError());
2990#endif
2991
2992 CloseHandle(thread);
2993
2994 apc_count = 0;
2995 ret = QueueUserAPC(user_apc, GetCurrentThread(), 0);
2996 ok(ret, "QueueUserAPC failed err %lu\n", GetLastError());
2997 ok(!apc_count, "APC count %u\n", apc_count);
2998 ret = SleepEx( 100, TRUE );
2999 ok( ret == WAIT_IO_COMPLETION, "SleepEx returned %lu\n", ret);
3000 ok(apc_count == 1, "APC count %u\n", apc_count);
3001
3002 ret = pNtQueueApcThread( GetCurrentThread(), NULL, 0, 0, 0 );
3003 ok( !ret, "got %#lx\n", ret);
3004 ret = SleepEx( 100, TRUE );
3005 ok( ret == WAIT_OBJECT_0, "SleepEx returned %lu\n", ret);
3006
3007 apc_count = 0;
3008 ret = QueueUserAPC(user_apc, GetCurrentThread(), 0);
3009 ok(ret, "QueueUserAPC failed err %lu\n", GetLastError());
3010 ok(!apc_count, "APC count %u\n", apc_count);
3011 status = pNtTestAlert();
3012 ok(!status, "got %lx\n", status);
3013 ok(apc_count == 1, "APC count %u\n", apc_count);
3014 status = pNtTestAlert();
3015 ok(!status, "got %lx\n", status);
3016 ok(apc_count == 1, "APC count %u\n", apc_count);
3017}
3018
3019START_TEST(sync)
3020{
3021 char **argv;
3022 int argc;
3023 HMODULE hdll = GetModuleHandleA("kernel32.dll");
3024 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
3025
3026 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
3027 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
3028 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
3029 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
3030 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
3031 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
3032 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW");
3033 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
3034 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
3035 pInitializeCriticalSectionEx = (void *)GetProcAddress(hdll, "InitializeCriticalSectionEx");
3036 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock");
3037 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive");
3038 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared");
3039 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive");
3040 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared");
3041 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive");
3042 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared");
3043 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory");
3044 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory");
3045 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject");
3046 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects");
3047 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList");
3048 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx");
3049 pNtQueueApcThread = (void *)GetProcAddress(hntdll, "NtQueueApcThread");
3050 pNtTestAlert = (void *)GetProcAddress(hntdll, "NtTestAlert");
3051
3052 argc = winetest_get_mainargs( &argv );
3053 if (argc >= 3)
3054 {
3055 if (!strcmp(argv[2], "apc_deadlock"))
3056 {
3057 for (;;) SleepEx(INFINITE, TRUE);
3058 }
3059 return;
3060 }
3061
3062 init_fastcall_thunk();
3063
3064 test_QueueUserAPC();
3065 test_signalandwait();
3066 test_temporary_objects();
3067 test_mutex();
3068 test_slist();
3069 test_event();
3070 test_semaphore();
3071 test_waitable_timer();
3072 test_iocp_callback();
3073 test_timer_queue();
3074 test_WaitForSingleObject();
3075 test_WaitForMultipleObjects();
3076 test_initonce();
3077 test_condvars_base(&aligned_cv);
3078 test_condvars_base(&unaligned_cv.cv);
3079 test_condvars_consumer_producer();
3080 test_srwlock_base(&aligned_srwlock);
3081 test_srwlock_quirk();
3082#if defined(__i386__) || defined(__x86_64__)
3083 /* unaligned locks only work on x86 platforms */
3084 test_srwlock_base(&unaligned_srwlock.lock);
3085#endif
3086 test_srwlock_example();
3087 test_alertable_wait();
3088 test_apc_deadlock();
3089 test_crit_section();
3090}