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