Release 1.4.1.
[wine] / dlls / kernel32 / tests / sync.c
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 #define _WIN32_WINNT 0x500
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windef.h>
26 #include <winbase.h>
27
28 #include "wine/test.h"
29
30 static BOOL   (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
31 static HANDLE (WINAPI *pCreateTimerQueue)(void);
32 static BOOL   (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
33                                                PVOID, DWORD, DWORD, ULONG);
34 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
35 static BOOL   (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
36 static BOOL   (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
37 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
38
39 static void test_signalandwait(void)
40 {
41     DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
42     HMODULE kernel32;
43     DWORD r;
44     HANDLE event[2], semaphore[2], file;
45
46     kernel32 = GetModuleHandle("kernel32");
47     pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
48
49     if (!pSignalObjectAndWait)
50         return;
51
52     /* invalid parameters */
53     r = pSignalObjectAndWait(NULL, NULL, 0, 0);
54     if (r == ERROR_INVALID_FUNCTION)
55     {
56         win_skip("SignalObjectAndWait is not implemented\n");
57         return; /* Win98/ME */
58     }
59     ok( r == WAIT_FAILED, "should fail\n");
60
61     event[0] = CreateEvent(NULL, 0, 0, NULL);
62     event[1] = CreateEvent(NULL, 1, 1, NULL);
63
64     ok( event[0] && event[1], "failed to create event flags\n");
65
66     r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
67     ok( r == WAIT_FAILED, "should fail\n");
68
69     r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
70     ok( r == WAIT_FAILED, "should fail\n");
71
72
73     /* valid parameters */
74     r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
75     ok( r == WAIT_OBJECT_0, "should succeed\n");
76
77     /* event[0] is now signalled */
78     r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
79     ok( r == WAIT_OBJECT_0, "should succeed\n");
80
81     /* event[0] is not signalled */
82     r = WaitForSingleObject(event[0], 0);
83     ok( r == WAIT_TIMEOUT, "event was signalled\n");
84
85     r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
86     ok( r == WAIT_OBJECT_0, "should succeed\n");
87
88     /* clear event[1] and check for a timeout */
89     ok(ResetEvent(event[1]), "failed to clear event[1]\n");
90     r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
91     ok( r == WAIT_TIMEOUT, "should timeout\n");
92
93     CloseHandle(event[0]);
94     CloseHandle(event[1]);
95
96     /* semaphores */
97     semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
98     semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
99     ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
100
101     r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
102     ok( r == WAIT_OBJECT_0, "should succeed\n");
103
104     r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
105     ok( r == WAIT_FAILED, "should fail\n");
106
107     r = ReleaseSemaphore(semaphore[0],1,NULL);
108     ok( r == FALSE, "should fail\n");
109
110     r = ReleaseSemaphore(semaphore[1],1,NULL);
111     ok( r == TRUE, "should succeed\n");
112
113     CloseHandle(semaphore[0]);
114     CloseHandle(semaphore[1]);
115
116     /* try a registry key */
117     file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
118         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
119     r = pSignalObjectAndWait(file, file, 0, FALSE);
120     ok( r == WAIT_FAILED, "should fail\n");
121     ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
122     CloseHandle(file);
123 }
124
125 static void test_mutex(void)
126 {
127     DWORD wait_ret;
128     BOOL ret;
129     HANDLE hCreated;
130     HANDLE hOpened;
131     int i;
132     DWORD failed = 0;
133
134     hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
135     ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
136
137     hOpened = OpenMutex(0, FALSE, "WineTestMutex");
138     ok(hOpened == NULL, "OpenMutex succeeded\n");
139
140     hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
141     ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
142     wait_ret = WaitForSingleObject(hOpened, INFINITE);
143     ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
144     CloseHandle(hOpened);
145
146     for(i=0; i < 31; i++)
147     {
148         wait_ret = WaitForSingleObject(hCreated, INFINITE);
149         ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
150     }
151
152     hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
153     ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
154     wait_ret = WaitForSingleObject(hOpened, INFINITE);
155     ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
156     CloseHandle(hOpened);
157
158     for (i = 0; i < 32; i++)
159     {
160         hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
161         if(hOpened != NULL)
162         {
163             ret = ReleaseMutex(hOpened);
164             ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
165             CloseHandle(hOpened);
166         }
167         else
168         {
169             ReleaseMutex(hCreated);
170             failed |=0x1 << i;
171         }
172     }
173
174     ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
175
176     ret = ReleaseMutex(hCreated);
177     ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
178         "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
179
180     /* test case sensitivity */
181
182     SetLastError(0xdeadbeef);
183     hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
184     ok(!hOpened, "OpenMutex succeeded\n");
185     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
186
187     SetLastError(0xdeadbeef);
188     hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
189     ok(!hOpened, "OpenMutex succeeded\n");
190     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
191
192     SetLastError(0xdeadbeef);
193     hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
194     ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
195     ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
196     CloseHandle(hOpened);
197
198     SetLastError(0xdeadbeef);
199     hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
200     ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
201     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
202     CloseHandle(hOpened);
203
204     CloseHandle(hCreated);
205 }
206
207 static void test_slist(void)
208 {
209     struct item
210     {
211         SLIST_ENTRY entry;
212         int value;
213     } item1, item2, item3, *pitem;
214
215     SLIST_HEADER slist_header;
216     PSLIST_ENTRY entry;
217     USHORT size;
218
219     VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
220     USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
221     PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
222     PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
223     PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
224     HMODULE kernel32;
225
226     kernel32 = GetModuleHandle("KERNEL32.DLL");
227     pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
228     pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
229     pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
230     pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
231     pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
232     if (pInitializeSListHead == NULL ||
233         pQueryDepthSList == NULL ||
234         pInterlockedFlushSList == NULL ||
235         pInterlockedPopEntrySList == NULL ||
236         pInterlockedPushEntrySList == NULL)
237     {
238         win_skip("some required slist entrypoints were not found, skipping tests\n");
239         return;
240     }
241
242     memset(&slist_header, 0xFF, sizeof(slist_header));
243     pInitializeSListHead(&slist_header);
244     size = pQueryDepthSList(&slist_header);
245     ok(size == 0, "initially created slist has size %d, expected 0\n", size);
246
247     item1.value = 1;
248     ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
249         "previous entry in empty slist wasn't NULL\n");
250     size = pQueryDepthSList(&slist_header);
251     ok(size == 1, "slist with 1 item has size %d\n", size);
252
253     item2.value = 2;
254     entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
255     ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
256     if (entry != NULL)
257     {
258         pitem = (struct item*) entry;
259         ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
260     }
261     size = pQueryDepthSList(&slist_header);
262     ok(size == 2, "slist with 2 items has size %d\n", size);
263
264     item3.value = 3;
265     entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
266     ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
267     if (entry != NULL)
268     {
269         pitem = (struct item*) entry;
270         ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
271     }
272     size = pQueryDepthSList(&slist_header);
273     ok(size == 3, "slist with 3 items has size %d\n", size);
274
275     entry = pInterlockedPopEntrySList(&slist_header);
276     ok(entry != NULL, "entry shouldn't be NULL\n");
277     if (entry != NULL)
278     {
279         pitem = (struct item*) entry;
280         ok(pitem->value == 3, "unexpected entry removed\n");
281     }
282     size = pQueryDepthSList(&slist_header);
283     ok(size == 2, "slist with 2 items has size %d\n", size);
284
285     entry = pInterlockedFlushSList(&slist_header);
286     size = pQueryDepthSList(&slist_header);
287     ok(size == 0, "flushed slist should be empty, size is %d\n", size);
288     if (size == 0)
289     {
290         ok(pInterlockedPopEntrySList(&slist_header) == NULL,
291             "popping empty slist didn't return NULL\n");
292     }
293     ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
294     ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
295 }
296
297 static void test_event(void)
298 {
299     HANDLE handle, handle2;
300     SECURITY_ATTRIBUTES sa;
301     SECURITY_DESCRIPTOR sd;
302     ACL acl;
303
304     /* no sd */
305     handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
306     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
307     CloseHandle(handle);
308
309     sa.nLength = sizeof(sa);
310     sa.lpSecurityDescriptor = &sd;
311     sa.bInheritHandle = FALSE;
312
313     InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
314
315     /* blank sd */
316     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
317     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
318     CloseHandle(handle);
319
320     /* sd with NULL dacl */
321     SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
322     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
323     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
324     CloseHandle(handle);
325
326     /* sd with empty dacl */
327     InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
328     SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
329     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
330     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
331     CloseHandle(handle);
332
333     /* test case sensitivity */
334
335     SetLastError(0xdeadbeef);
336     handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
337     ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
338     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
339
340     SetLastError(0xdeadbeef);
341     handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
342     ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
343     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
344     CloseHandle( handle2 );
345
346     SetLastError(0xdeadbeef);
347     handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
348     ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
349     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
350     CloseHandle( handle2 );
351
352     SetLastError(0xdeadbeef);
353     handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
354     ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
355     CloseHandle( handle2 );
356
357     SetLastError(0xdeadbeef);
358     handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
359     ok( !handle2, "OpenEvent succeeded\n");
360     ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
361
362     CloseHandle( handle );
363 }
364
365 static void test_semaphore(void)
366 {
367     HANDLE handle, handle2;
368
369     /* test case sensitivity */
370
371     SetLastError(0xdeadbeef);
372     handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
373     ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
374     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
375
376     SetLastError(0xdeadbeef);
377     handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
378     ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
379     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
380     CloseHandle( handle2 );
381
382     SetLastError(0xdeadbeef);
383     handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
384     ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
385     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
386     CloseHandle( handle2 );
387
388     SetLastError(0xdeadbeef);
389     handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
390     ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
391     CloseHandle( handle2 );
392
393     SetLastError(0xdeadbeef);
394     handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
395     ok( !handle2, "OpenSemaphore succeeded\n");
396     ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
397
398     CloseHandle( handle );
399 }
400
401 static void test_waitable_timer(void)
402 {
403     HANDLE handle, handle2;
404
405     if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
406     {
407         win_skip("{Create,Open}WaitableTimerA() is not available\n");
408         return;
409     }
410
411     /* test case sensitivity */
412
413     SetLastError(0xdeadbeef);
414     handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
415     ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
416     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
417
418     SetLastError(0xdeadbeef);
419     handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
420     ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
421     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
422     CloseHandle( handle2 );
423
424     SetLastError(0xdeadbeef);
425     handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
426     ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
427     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
428     CloseHandle( handle2 );
429
430     SetLastError(0xdeadbeef);
431     handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
432     ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
433     CloseHandle( handle2 );
434
435     SetLastError(0xdeadbeef);
436     handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
437     ok( !handle2, "OpenWaitableTimer succeeded\n");
438     ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
439         GetLastError() == ERROR_INVALID_NAME, /* win98 */
440         "wrong error %u\n", GetLastError());
441
442     CloseHandle( handle );
443 }
444
445 static HANDLE sem = 0;
446
447 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
448 {
449     ReleaseSemaphore(sem, 1, NULL);
450 }
451
452 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
453
454 static void test_iocp_callback(void)
455 {
456     char temp_path[MAX_PATH];
457     char filename[MAX_PATH];
458     DWORD ret;
459     BOOL retb;
460     static const char prefix[] = "pfx";
461     HANDLE hFile;
462     HMODULE hmod = GetModuleHandleA("kernel32.dll");
463     DWORD bytesWritten;
464     const char *buffer = "12345678123456781234567812345678";
465     OVERLAPPED overlapped;
466
467     p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
468     if(!p_BindIoCompletionCallback) {
469         win_skip("BindIoCompletionCallback not found in this DLL\n");
470         return;
471     }
472
473     sem = CreateSemaphore(NULL, 0, 1, NULL);
474     ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
475
476     ret = GetTempPathA(MAX_PATH, temp_path);
477     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
478     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
479
480     ret = GetTempFileNameA(temp_path, prefix, 0, filename);
481     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
482
483     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
484                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
485     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
486
487     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
488     ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
489     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
490
491     ret = CloseHandle(hFile);
492     ok( ret, "CloseHandle: error %d\n", GetLastError());
493     ret = DeleteFileA(filename);
494     ok( ret, "DeleteFileA: error %d\n", GetLastError());
495
496     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
497                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
498     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
499
500     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
501     ok(retb == TRUE, "BindIoCompletionCallback failed\n");
502
503     memset(&overlapped, 0, sizeof(overlapped));
504     retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
505     ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
506
507     ret = WaitForSingleObject(sem, 5000);
508     ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
509     CloseHandle(sem);
510
511     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
512     ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
513     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
514     retb = p_BindIoCompletionCallback(hFile, NULL, 0);
515     ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
516     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
517
518     ret = CloseHandle(hFile);
519     ok( ret, "CloseHandle: error %d\n", GetLastError());
520     ret = DeleteFileA(filename);
521     ok( ret, "DeleteFileA: error %d\n", GetLastError());
522
523     /* win2k3 requires the Flags parameter to be zero */
524     SetLastError(0xdeadbeef);
525     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
526                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
527     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
528     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
529     if (!retb)
530         ok(GetLastError() == ERROR_INVALID_PARAMETER,
531            "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
532     else
533         ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
534     ret = CloseHandle(hFile);
535     ok( ret, "CloseHandle: error %d\n", GetLastError());
536     ret = DeleteFileA(filename);
537     ok( ret, "DeleteFileA: error %d\n", GetLastError());
538
539     retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
540     ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
541     ok(GetLastError() == ERROR_INVALID_HANDLE ||
542        GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
543        "Last error is %d\n", GetLastError());
544 }
545
546 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
547 {
548     int *pn = p;
549     ok(timedOut, "Timer callbacks should always time out\n");
550     ++*pn;
551 }
552
553 struct timer_queue_data1
554 {
555     int num_calls;
556     int max_calls;
557     HANDLE q, t;
558 };
559
560 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
561 {
562     struct timer_queue_data1 *d = p;
563     ok(timedOut, "Timer callbacks should always time out\n");
564     if (d->t && ++d->num_calls == d->max_calls)
565     {
566         BOOL ret;
567         SetLastError(0xdeadbeef);
568         /* Note, XP SP2 does *not* do any deadlock checking, so passing
569            INVALID_HANDLE_VALUE here will just hang.  */
570         ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
571         ok(!ret, "DeleteTimerQueueTimer\n");
572         ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
573     }
574 }
575
576 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
577 {
578     struct timer_queue_data1 *d = p;
579     ok(timedOut, "Timer callbacks should always time out\n");
580     if (d->t && ++d->num_calls == d->max_calls)
581     {
582         /* Basically kill the timer since it won't have time to run
583            again.  */
584         BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
585         ok(ret, "ChangeTimerQueueTimer\n");
586     }
587 }
588
589 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
590 {
591     struct timer_queue_data1 *d = p;
592     ok(timedOut, "Timer callbacks should always time out\n");
593     if (d->t)
594     {
595         /* This tests whether a timer gets flagged for deletion before
596            or after the callback runs.  If we start this timer with a
597            period of zero (run once), then ChangeTimerQueueTimer will
598            fail if the timer is already flagged.  Hence we really run
599            only once.  Otherwise we will run multiple times.  */
600         BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
601         ok(ret, "ChangeTimerQueueTimer\n");
602         ++d->num_calls;
603     }
604 }
605
606 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
607 {
608     DWORD_PTR delay = (DWORD_PTR) p;
609     ok(timedOut, "Timer callbacks should always time out\n");
610     if (delay)
611         Sleep(delay);
612 }
613
614 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
615 {
616     struct timer_queue_data1 *d = p;
617     ok(timedOut, "Timer callbacks should always time out\n");
618     /* This tests an original implementation bug where a deleted timer may get
619        to run, but it is tricky to set up.  */
620     if (d->q && d->num_calls++ == 0)
621     {
622         /* First run: delete ourselves, then insert and remove a timer
623            that goes in front of us in the sorted timeout list.  Once
624            removed, we will still timeout at the faster timer's due time,
625            but this should be a no-op if we are bug-free.  There should
626            not be a second run.  We can test the value of num_calls later.  */
627         BOOL ret;
628         HANDLE t;
629
630         /* The delete will pend while we are in this callback.  */
631         SetLastError(0xdeadbeef);
632         ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
633         ok(!ret, "DeleteTimerQueueTimer\n");
634         ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
635
636         ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
637         ok(ret, "CreateTimerQueueTimer\n");
638         ok(t != NULL, "CreateTimerQueueTimer\n");
639
640         ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
641         ok(ret, "DeleteTimerQueueTimer\n");
642
643         /* Now we stay alive by hanging around in the callback.  */
644         Sleep(500);
645     }
646 }
647
648 static void test_timer_queue(void)
649 {
650     HANDLE q, t1, t2, t3, t4, t5;
651     int n1, n2, n3, n4, n5;
652     struct timer_queue_data1 d1, d2, d3, d4;
653     HANDLE e, et1, et2;
654     BOOL ret;
655
656     if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
657         || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
658     {
659         win_skip("TimerQueue API not present\n");
660         return;
661     }
662
663     /* Test asynchronous deletion of the queue. */
664     q = pCreateTimerQueue();
665     ok(q != NULL, "CreateTimerQueue\n");
666
667     SetLastError(0xdeadbeef);
668     ret = pDeleteTimerQueueEx(q, NULL);
669     ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
670        "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
671        GetLastError());
672
673     /* Test synchronous deletion of the queue and running timers. */
674     q = pCreateTimerQueue();
675     ok(q != NULL, "CreateTimerQueue\n");
676
677     /* Called once.  */
678     t1 = NULL;
679     n1 = 0;
680     ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
681                                  0, 0);
682     ok(ret, "CreateTimerQueueTimer\n");
683     ok(t1 != NULL, "CreateTimerQueueTimer\n");
684
685     /* A slow one.  */
686     t2 = NULL;
687     n2 = 0;
688     ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
689                                  100, 0);
690     ok(ret, "CreateTimerQueueTimer\n");
691     ok(t2 != NULL, "CreateTimerQueueTimer\n");
692
693     /* A fast one.  */
694     t3 = NULL;
695     n3 = 0;
696     ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
697                                  10, 0);
698     ok(ret, "CreateTimerQueueTimer\n");
699     ok(t3 != NULL, "CreateTimerQueueTimer\n");
700
701     /* Start really late (it won't start).  */
702     t4 = NULL;
703     n4 = 0;
704     ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
705                                  10, 0);
706     ok(ret, "CreateTimerQueueTimer\n");
707     ok(t4 != NULL, "CreateTimerQueueTimer\n");
708
709     /* Start soon, but delay so long it won't run again.  */
710     t5 = NULL;
711     n5 = 0;
712     ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
713                                  10000, 0);
714     ok(ret, "CreateTimerQueueTimer\n");
715     ok(t5 != NULL, "CreateTimerQueueTimer\n");
716
717     /* Give them a chance to do some work.  */
718     Sleep(500);
719
720     /* Test deleting a once-only timer.  */
721     ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
722     ok(ret, "DeleteTimerQueueTimer\n");
723
724     /* A periodic timer.  */
725     ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
726     ok(ret, "DeleteTimerQueueTimer\n");
727
728     ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
729     ok(ret, "DeleteTimerQueueEx\n");
730     ok(n1 == 1, "Timer callback 1\n");
731     ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
732     ok(n4 == 0, "Timer callback 4\n");
733     ok(n5 == 1, "Timer callback 5\n");
734
735     /* Test synchronous deletion of the timer/queue with event trigger. */
736     e = CreateEvent(NULL, TRUE, FALSE, NULL);
737     et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
738     et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
739     if (!e || !et1 || !et2)
740     {
741         skip("Failed to create timer queue descruction event\n");
742         return;
743     }
744
745     q = pCreateTimerQueue();
746     ok(q != NULL, "CreateTimerQueue\n");
747
748     /* Run once and finish quickly (should be done when we delete it).  */
749     t1 = NULL;
750     ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
751     ok(ret, "CreateTimerQueueTimer\n");
752     ok(t1 != NULL, "CreateTimerQueueTimer\n");
753
754     /* Run once and finish slowly (shouldn't be done when we delete it).  */
755     t2 = NULL;
756     ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
757                                  0, 0);
758     ok(ret, "CreateTimerQueueTimer\n");
759     ok(t2 != NULL, "CreateTimerQueueTimer\n");
760
761     /* Run once and finish quickly (should be done when we delete it).  */
762     t3 = NULL;
763     ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
764     ok(ret, "CreateTimerQueueTimer\n");
765     ok(t3 != NULL, "CreateTimerQueueTimer\n");
766
767     /* Run once and finish slowly (shouldn't be done when we delete it).  */
768     t4 = NULL;
769     ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
770                                  0, 0);
771     ok(ret, "CreateTimerQueueTimer\n");
772     ok(t4 != NULL, "CreateTimerQueueTimer\n");
773
774     /* Give them a chance to start.  */
775     Sleep(400);
776
777     /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
778        even if the timer is finished.  */
779     SetLastError(0xdeadbeef);
780     ret = pDeleteTimerQueueTimer(q, t1, NULL);
781     ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
782        "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
783        GetLastError());
784
785     SetLastError(0xdeadbeef);
786     ret = pDeleteTimerQueueTimer(q, t2, NULL);
787     ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
788     ok(GetLastError() == ERROR_IO_PENDING,
789        "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
790        GetLastError());
791
792     SetLastError(0xdeadbeef);
793     ret = pDeleteTimerQueueTimer(q, t3, et1);
794     ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
795     ok(GetLastError() == 0xdeadbeef,
796        "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
797        GetLastError());
798     ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
799        "Timer destruction event not triggered\n");
800
801     SetLastError(0xdeadbeef);
802     ret = pDeleteTimerQueueTimer(q, t4, et2);
803     ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
804     ok(GetLastError() == ERROR_IO_PENDING,
805        "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
806        GetLastError());
807     ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
808        "Timer destruction event not triggered\n");
809
810     SetLastError(0xdeadbeef);
811     ret = pDeleteTimerQueueEx(q, e);
812     ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
813        "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
814        GetLastError());
815     ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
816        "Queue destruction event not triggered\n");
817     CloseHandle(e);
818
819     /* Test deleting/changing a timer in execution.  */
820     q = pCreateTimerQueue();
821     ok(q != NULL, "CreateTimerQueue\n");
822
823     /* Test changing a once-only timer before it fires (this is allowed,
824        whereas after it fires you cannot).  */
825     n1 = 0;
826     ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
827                                  0, 0);
828     ok(ret, "CreateTimerQueueTimer\n");
829     ok(t1 != NULL, "CreateTimerQueueTimer\n");
830     ret = pChangeTimerQueueTimer(q, t1, 0, 0);
831     ok(ret, "ChangeTimerQueueTimer\n");
832
833     d2.t = t2 = NULL;
834     d2.num_calls = 0;
835     d2.max_calls = 3;
836     d2.q = q;
837     ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
838                                  10, 0);
839     d2.t = t2;
840     ok(ret, "CreateTimerQueueTimer\n");
841     ok(t2 != NULL, "CreateTimerQueueTimer\n");
842
843     d3.t = t3 = NULL;
844     d3.num_calls = 0;
845     d3.max_calls = 4;
846     d3.q = q;
847     ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
848                                  10, 0);
849     d3.t = t3;
850     ok(ret, "CreateTimerQueueTimer\n");
851     ok(t3 != NULL, "CreateTimerQueueTimer\n");
852
853     d4.t = t4 = NULL;
854     d4.num_calls = 0;
855     d4.q = q;
856     ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
857                                  0, 0);
858     d4.t = t4;
859     ok(ret, "CreateTimerQueueTimer\n");
860     ok(t4 != NULL, "CreateTimerQueueTimer\n");
861
862     Sleep(500);
863
864     ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
865     ok(ret, "DeleteTimerQueueEx\n");
866     ok(n1 == 1, "ChangeTimerQueueTimer\n");
867     ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
868     ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
869     ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
870
871     /* Test an obscure bug that was in the original implementation.  */
872     q = pCreateTimerQueue();
873     ok(q != NULL, "CreateTimerQueue\n");
874
875     /* All the work is done in the callback.  */
876     d1.t = t1 = NULL;
877     d1.num_calls = 0;
878     d1.q = q;
879     ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
880                                  100, WT_EXECUTELONGFUNCTION);
881     d1.t = t1;
882     ok(ret, "CreateTimerQueueTimer\n");
883     ok(t1 != NULL, "CreateTimerQueueTimer\n");
884
885     Sleep(750);
886
887     SetLastError(0xdeadbeef);
888     ret = pDeleteTimerQueueEx(q, NULL);
889     ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
890        "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
891        GetLastError());
892     ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
893
894     /* Test functions on the default timer queue.  */
895     t1 = NULL;
896     n1 = 0;
897     ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
898                                  1000, 0);
899     ok(ret, "CreateTimerQueueTimer, default queue\n");
900     ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
901
902     ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
903     ok(ret, "ChangeTimerQueueTimer, default queue\n");
904
905     ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
906     ok(ret, "DeleteTimerQueueTimer, default queue\n");
907
908     /* Try mixing default and non-default queues.  Apparently this works.  */
909     q = pCreateTimerQueue();
910     ok(q != NULL, "CreateTimerQueue\n");
911
912     t1 = NULL;
913     n1 = 0;
914     ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
915                                  1000, 0);
916     ok(ret, "CreateTimerQueueTimer\n");
917     ok(t1 != NULL, "CreateTimerQueueTimer\n");
918
919     t2 = NULL;
920     n2 = 0;
921     ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
922                                  1000, 0);
923     ok(ret, "CreateTimerQueueTimer\n");
924     ok(t2 != NULL, "CreateTimerQueueTimer\n");
925
926     ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
927     ok(ret, "ChangeTimerQueueTimer\n");
928
929     ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
930     ok(ret, "ChangeTimerQueueTimer\n");
931
932     ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
933     ok(ret, "DeleteTimerQueueTimer\n");
934
935     ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
936     ok(ret, "DeleteTimerQueueTimer\n");
937
938     /* Try to delete the default queue?  In any case: not allowed.  */
939     SetLastError(0xdeadbeef);
940     ret = pDeleteTimerQueueEx(NULL, NULL);
941     ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
942     ok(GetLastError() == ERROR_INVALID_HANDLE,
943        "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
944        GetLastError());
945
946     SetLastError(0xdeadbeef);
947     ret = pDeleteTimerQueueEx(q, NULL);
948     ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
949        "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
950        GetLastError());
951 }
952
953 static HANDLE modify_handle(HANDLE handle, DWORD modify)
954 {
955     DWORD tmp = HandleToULong(handle);
956     tmp |= modify;
957     return ULongToHandle(tmp);
958 }
959
960 static void test_WaitForSingleObject(void)
961 {
962     HANDLE signaled, nonsignaled, invalid;
963     DWORD ret;
964
965     signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
966     nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
967     invalid = (HANDLE) 0xdeadbee0;
968
969     /* invalid handle with different values for lower 2 bits */
970     SetLastError(0xdeadbeef);
971     ret = WaitForSingleObject(invalid, 0);
972     ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
973     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
974
975     SetLastError(0xdeadbeef);
976     ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
977     ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
978     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
979
980     SetLastError(0xdeadbeef);
981     ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
982     ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
983     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
984
985     SetLastError(0xdeadbeef);
986     ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
987     ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
988     ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
989
990     /* valid handle with different values for lower 2 bits */
991     SetLastError(0xdeadbeef);
992     ret = WaitForSingleObject(nonsignaled, 0);
993     ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
994     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
995
996     SetLastError(0xdeadbeef);
997     ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
998     ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
999     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1000
1001     SetLastError(0xdeadbeef);
1002     ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1003     ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1004     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1005
1006     SetLastError(0xdeadbeef);
1007     ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1008     ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1009     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1010
1011     /* valid handle with different values for lower 2 bits */
1012     SetLastError(0xdeadbeef);
1013     ret = WaitForSingleObject(signaled, 0);
1014     ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1015     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1016
1017     SetLastError(0xdeadbeef);
1018     ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1019     ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1020     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1021
1022     SetLastError(0xdeadbeef);
1023     ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1024     ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1025     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1026
1027     SetLastError(0xdeadbeef);
1028     ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1029     ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1030     ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1031
1032     CloseHandle(signaled);
1033     CloseHandle(nonsignaled);
1034 }
1035
1036 static void test_WaitForMultipleObjects(void)
1037 {
1038     DWORD r;
1039     int i;
1040     HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1041
1042     /* create the maximum number of events and make sure
1043      * we can wait on that many */
1044     for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1045     {
1046         maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1047         ok( maxevents[i] != 0, "should create enough events\n");
1048     }
1049
1050     /* a manual-reset event remains signaled, an auto-reset event is cleared */
1051     r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1052     ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1053     r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1054     ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1055     ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1056     for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1057     {
1058         /* the lowest index is checked first and remaining events are untouched */
1059         r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1060         ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1061     }
1062
1063     for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1064         if (maxevents[i]) CloseHandle(maxevents[i]);
1065 }
1066
1067 START_TEST(sync)
1068 {
1069     HMODULE hdll = GetModuleHandle("kernel32");
1070     pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1071     pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1072     pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1073     pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1074     pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1075     pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1076     pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1077
1078     test_signalandwait();
1079     test_mutex();
1080     test_slist();
1081     test_event();
1082     test_semaphore();
1083     test_waitable_timer();
1084     test_iocp_callback();
1085     test_timer_queue();
1086     test_WaitForSingleObject();
1087     test_WaitForMultipleObjects();
1088 }