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