msi: Set all folders' source paths to the root directory if the source type is compre...
[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 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <windef.h>
25 #define _WIN32_WINNT 0x500
26 #include <winbase.h>
27
28 #include "wine/test.h"
29
30 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
31 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
32
33 static void test_signalandwait(void)
34 {
35     DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
36     HMODULE kernel32;
37     DWORD r;
38     int i;
39     HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
40
41     kernel32 = GetModuleHandle("kernel32");
42     pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
43
44     if (!pSignalObjectAndWait)
45         return;
46
47     /* invalid parameters */
48     r = pSignalObjectAndWait(NULL, NULL, 0, 0);
49     if (r == ERROR_INVALID_FUNCTION)
50     {
51         trace("SignalObjectAndWait not implemented, skipping tests\n");
52         return; /* Win98/ME */
53     }
54     ok( r == WAIT_FAILED, "should fail\n");
55
56     event[0] = CreateEvent(NULL, 0, 0, NULL);
57     event[1] = CreateEvent(NULL, 1, 1, NULL);
58
59     ok( event[0] && event[1], "failed to create event flags\n");
60
61     r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
62     ok( r == WAIT_FAILED, "should fail\n");
63
64     r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
65     ok( r == WAIT_FAILED, "should fail\n");
66
67
68     /* valid parameters */
69     r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
70     ok( r == WAIT_OBJECT_0, "should succeed\n");
71
72     /* event[0] is now signalled */
73     r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
74     ok( r == WAIT_OBJECT_0, "should succeed\n");
75
76     /* event[0] is not signalled */
77     r = WaitForSingleObject(event[0], 0);
78     ok( r == WAIT_TIMEOUT, "event was signalled\n");
79
80     r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
81     ok( r == WAIT_OBJECT_0, "should succeed\n");
82
83     /* clear event[1] and check for a timeout */
84     ok(ResetEvent(event[1]), "failed to clear event[1]\n");
85     r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
86     ok( r == WAIT_TIMEOUT, "should timeout\n");
87
88     CloseHandle(event[0]);
89     CloseHandle(event[1]);
90
91     /* create the maximum number of events and make sure 
92      * we can wait on that many */
93     for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
94     {
95         maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
96         ok( maxevents[i] != 0, "should create enough events\n");
97     }
98     r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
99     ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
100
101     for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
102         if (maxevents[i]) CloseHandle(maxevents[i]);
103
104     /* semaphores */
105     semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
106     semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
107     ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
108
109     r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
110     ok( r == WAIT_OBJECT_0, "should succeed\n");
111
112     r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
113     ok( r == WAIT_FAILED, "should fail\n");
114
115     r = ReleaseSemaphore(semaphore[0],1,NULL);
116     ok( r == FALSE, "should fail\n");
117
118     r = ReleaseSemaphore(semaphore[1],1,NULL);
119     ok( r == TRUE, "should succeed\n");
120
121     CloseHandle(semaphore[0]);
122     CloseHandle(semaphore[1]);
123
124     /* try a registry key */
125     file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 
126         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
127     r = pSignalObjectAndWait(file, file, 0, FALSE);
128     ok( r == WAIT_FAILED, "should fail\n");
129     ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
130     CloseHandle(file);
131 }
132
133 static void test_mutex(void)
134 {
135     DWORD wait_ret;
136     BOOL ret;
137     HANDLE hCreated;
138     HANDLE hOpened;
139
140     hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
141     ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
142     wait_ret = WaitForSingleObject(hCreated, INFINITE);
143     ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
144
145     /* yes, opening with just READ_CONTROL access allows us to successfully
146      * call ReleaseMutex */
147     hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
148     ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
149     ret = ReleaseMutex(hOpened);
150     todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError());
151     ret = ReleaseMutex(hCreated);
152     todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
153         "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
154
155     /* test case sensitivity */
156
157     SetLastError(0xdeadbeef);
158     hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
159     ok(!hOpened, "OpenMutex succeeded\n");
160     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
161        GetLastError() == ERROR_INVALID_NAME, /* win9x */
162        "wrong error %u\n", GetLastError());
163
164     SetLastError(0xdeadbeef);
165     hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
166     ok(!hOpened, "OpenMutex succeeded\n");
167     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
168        GetLastError() == ERROR_INVALID_NAME, /* win9x */
169        "wrong error %u\n", GetLastError());
170
171     SetLastError(0xdeadbeef);
172     hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
173     ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
174     ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
175     CloseHandle(hOpened);
176
177     SetLastError(0xdeadbeef);
178     hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
179     ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
180     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
181     CloseHandle(hOpened);
182
183     CloseHandle(hCreated);
184 }
185
186 static void test_slist(void)
187 {
188     struct item
189     {
190         SLIST_ENTRY entry;
191         int value;
192     } item1, item2, item3, *pitem;
193
194     SLIST_HEADER slist_header, test_header;
195     PSLIST_ENTRY entry;
196     USHORT size;
197
198     VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
199     USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
200     PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
201     PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
202     PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
203     HMODULE kernel32;
204
205     kernel32 = GetModuleHandle("KERNEL32.DLL");
206     pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
207     pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
208     pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
209     pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
210     pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
211     if (pInitializeSListHead == NULL ||
212         pQueryDepthSList == NULL ||
213         pInterlockedFlushSList == NULL ||
214         pInterlockedPopEntrySList == NULL ||
215         pInterlockedPushEntrySList == NULL)
216     {
217         skip("some required slist entrypoints were not found, skipping tests\n");
218         return;
219     }
220
221     memset(&test_header, 0, sizeof(test_header));
222     memset(&slist_header, 0xFF, sizeof(slist_header));
223     pInitializeSListHead(&slist_header);
224     ok(memcmp(&test_header, &slist_header, sizeof(SLIST_HEADER)) == 0,
225         "InitializeSListHead didn't zero-fill list header\n");
226     size = pQueryDepthSList(&slist_header);
227     ok(size == 0, "initially created slist has size %d, expected 0\n", size);
228
229     item1.value = 1;
230     ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
231         "previous entry in empty slist wasn't NULL\n");
232     size = pQueryDepthSList(&slist_header);
233     ok(size == 1, "slist with 1 item has size %d\n", size);
234
235     item2.value = 2;
236     entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
237     ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
238     if (entry != NULL)
239     {
240         pitem = (struct item*) entry;
241         ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
242     }
243     size = pQueryDepthSList(&slist_header);
244     ok(size == 2, "slist with 2 items has size %d\n", size);
245
246     item3.value = 3;
247     entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
248     ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
249     if (entry != NULL)
250     {
251         pitem = (struct item*) entry;
252         ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
253     }
254     size = pQueryDepthSList(&slist_header);
255     ok(size == 3, "slist with 3 items has size %d\n", size);
256
257     entry = pInterlockedPopEntrySList(&slist_header);
258     ok(entry != NULL, "entry shouldn't be NULL\n");
259     if (entry != NULL)
260     {
261         pitem = (struct item*) entry;
262         ok(pitem->value == 3, "unexpected entry removed\n");
263     }
264     size = pQueryDepthSList(&slist_header);
265     ok(size == 2, "slist with 2 items has size %d\n", size);
266
267     entry = pInterlockedFlushSList(&slist_header);
268     size = pQueryDepthSList(&slist_header);
269     ok(size == 0, "flushed slist should be empty, size is %d\n", size);
270     if (size == 0)
271     {
272         ok(pInterlockedPopEntrySList(&slist_header) == NULL,
273             "popping empty slist didn't return NULL\n");
274     }
275     ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
276     ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
277 }
278
279 static void test_event(void)
280 {
281     HANDLE handle, handle2;
282     SECURITY_ATTRIBUTES sa;
283     SECURITY_DESCRIPTOR sd;
284     ACL acl;
285
286     /* no sd */
287     handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
288     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
289     CloseHandle(handle);
290
291     sa.nLength = sizeof(sa);
292     sa.lpSecurityDescriptor = &sd;
293     sa.bInheritHandle = FALSE;
294
295     InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
296
297     /* blank sd */
298     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
299     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
300     CloseHandle(handle);
301
302     /* sd with NULL dacl */
303     SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
304     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
305     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
306     CloseHandle(handle);
307
308     /* sd with empty dacl */
309     InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
310     SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
311     handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
312     ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
313     CloseHandle(handle);
314
315     /* test case sensitivity */
316
317     SetLastError(0xdeadbeef);
318     handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
319     ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
320     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
321
322     SetLastError(0xdeadbeef);
323     handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
324     ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
325     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
326     CloseHandle( handle2 );
327
328     SetLastError(0xdeadbeef);
329     handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
330     ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
331     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
332     CloseHandle( handle2 );
333
334     SetLastError(0xdeadbeef);
335     handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
336     ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
337     CloseHandle( handle2 );
338
339     SetLastError(0xdeadbeef);
340     handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
341     ok( !handle2, "OpenEvent succeeded\n");
342     ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
343         GetLastError() == ERROR_INVALID_NAME, /* win9x */
344         "wrong error %u\n", GetLastError());
345
346     CloseHandle( handle );
347 }
348
349 static void test_semaphore(void)
350 {
351     HANDLE handle, handle2;
352
353     /* test case sensitivity */
354
355     SetLastError(0xdeadbeef);
356     handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
357     ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
358     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
359
360     SetLastError(0xdeadbeef);
361     handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
362     ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
363     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
364     CloseHandle( handle2 );
365
366     SetLastError(0xdeadbeef);
367     handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
368     ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
369     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
370     CloseHandle( handle2 );
371
372     SetLastError(0xdeadbeef);
373     handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
374     ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
375     CloseHandle( handle2 );
376
377     SetLastError(0xdeadbeef);
378     handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
379     ok( !handle2, "OpenSemaphore succeeded\n");
380     ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
381         GetLastError() == ERROR_INVALID_NAME, /* win9x */
382         "wrong error %u\n", GetLastError());
383
384     CloseHandle( handle );
385 }
386
387 static void test_waitable_timer(void)
388 {
389     HANDLE handle, handle2;
390
391     if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
392     {
393         skip("{Create,Open}WaitableTimerA() is not available\n");
394         return;
395     }
396
397     /* test case sensitivity */
398
399     SetLastError(0xdeadbeef);
400     handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
401     ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
402     ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
403
404     SetLastError(0xdeadbeef);
405     handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
406     ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
407     ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
408     CloseHandle( handle2 );
409
410     SetLastError(0xdeadbeef);
411     handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
412     ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
413     ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
414     CloseHandle( handle2 );
415
416     SetLastError(0xdeadbeef);
417     handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
418     ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
419     CloseHandle( handle2 );
420
421     SetLastError(0xdeadbeef);
422     handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
423     ok( !handle2, "OpenWaitableTimer succeeded\n");
424     ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
425
426     CloseHandle( handle );
427 }
428
429 static HANDLE sem = 0;
430
431 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
432 {
433     ReleaseSemaphore(sem, 1, NULL);
434 }
435
436 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
437
438 static void test_iocp_callback(void)
439 {
440     char temp_path[MAX_PATH];
441     char filename[MAX_PATH];
442     DWORD ret;
443     BOOL retb;
444     static const char prefix[] = "pfx";
445     HANDLE hFile;
446     HMODULE hmod = GetModuleHandleA("kernel32.dll");
447     DWORD bytesWritten;
448     const char *buffer = "12345678123456781234567812345678";
449     OVERLAPPED overlapped;
450
451     p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
452     if(!p_BindIoCompletionCallback) {
453         skip("BindIoCompletionCallback not found in this DLL\n");
454         return;
455     }
456
457     sem = CreateSemaphore(NULL, 0, 1, NULL);
458     ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
459
460     ret = GetTempPathA(MAX_PATH, temp_path);
461     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
462     ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
463
464     ret = GetTempFileNameA(temp_path, prefix, 0, filename);
465     ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
466
467     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
468                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
469     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
470
471     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
472     ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
473     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
474
475     ret = CloseHandle(hFile);
476     ok( ret, "CloseHandle: error %d\n", GetLastError());
477     ret = DeleteFileA(filename);
478     ok( ret, "DeleteFileA: error %d\n", GetLastError());
479
480     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
481                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
482     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
483
484     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
485     ok(retb == TRUE, "BindIoCompletionCallback failed\n");
486
487     memset(&overlapped, 0, sizeof(overlapped));
488     retb = WriteFile(hFile, (const void *) buffer, 4, &bytesWritten, &overlapped);
489     ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
490
491     ret = WaitForSingleObject(sem, 5000);
492     ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
493     CloseHandle(sem);
494
495     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
496     ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
497     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
498     retb = p_BindIoCompletionCallback(hFile, NULL, 0);
499     ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
500     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
501
502     ret = CloseHandle(hFile);
503     ok( ret, "CloseHandle: error %d\n", GetLastError());
504     ret = DeleteFileA(filename);
505     ok( ret, "DeleteFileA: error %d\n", GetLastError());
506
507     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
508                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
509     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
510     retb = p_BindIoCompletionCallback(hFile, NULL, 0);
511     ok(retb == TRUE, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
512     ret = CloseHandle(hFile);
513     ok( ret, "CloseHandle: error %d\n", GetLastError());
514     ret = DeleteFileA(filename);
515     ok( ret, "DeleteFileA: error %d\n", GetLastError());
516
517     /* win2k3 requires the Flags parameter to be zero */
518     SetLastError(0xdeadbeef);
519     hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
520                         CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
521     ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
522     retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
523     if (!retb)
524         ok(GetLastError() == ERROR_INVALID_PARAMETER,
525            "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
526     else
527         ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
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     retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
534     ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
535     ok(GetLastError() == ERROR_INVALID_HANDLE, "Last error is %d\n", GetLastError());
536 }
537
538 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
539 {
540     int *pn = (int *) p;
541     ok(timedOut, "Timer callbacks should always time out\n");
542     ++*pn;
543 }
544
545 static void test_timer_queue(void)
546 {
547     HANDLE q, t1, t2, t3, t4, t5;
548     int n1, n2, n3, n4, n5;
549     HANDLE e;
550     BOOL ret;
551
552     /* Test asynchronous deletion of the queue. */
553     q = CreateTimerQueue();
554     todo_wine
555     ok(q != NULL, "CreateTimerQueue\n");
556
557     SetLastError(0xdeadbeef);
558     ret = DeleteTimerQueueEx(q, NULL);
559     ok(!ret, "DeleteTimerQueueEx\n");
560     todo_wine
561     ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
562
563     /* Test synchronous deletion of the queue and running timers. */
564     q = CreateTimerQueue();
565     todo_wine
566     ok(q != NULL, "CreateTimerQueue\n");
567
568     /* Called once.  */
569     t1 = NULL;
570     n1 = 0;
571     ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
572                                 0, 0);
573     ok(ret, "CreateTimerQueueTimer\n");
574
575     /* A slow one.  */
576     t2 = NULL;
577     n2 = 0;
578     ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
579                                 100, 0);
580     ok(ret, "CreateTimerQueueTimer\n");
581
582     /* A fast one.  */
583     t3 = NULL;
584     n3 = 0;
585     ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
586                                 10, 0);
587     ok(ret, "CreateTimerQueueTimer\n");
588
589     /* Start really late (it won't start).  */
590     t4 = NULL;
591     n4 = 0;
592     ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
593                                 10, 0);
594     ok(ret, "CreateTimerQueueTimer\n");
595
596     /* Start soon, but delay so long it won't run again.  */
597     t5 = NULL;
598     n5 = 0;
599     ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
600                                 10000, 0);
601     ok(ret, "CreateTimerQueueTimer\n");
602
603     /* Give them a chance to do some work.  */
604     Sleep(500);
605
606     ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
607     todo_wine
608     {
609     ok(ret, "DeleteTimerQueueEx\n");
610     ok(n1 == 1, "Timer callback 1\n");
611     ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
612     }
613     ok(n4 == 0, "Timer callback 4\n");
614     todo_wine
615     ok(n5 == 1, "Timer callback 5\n");
616
617     /* Test synchronous deletion of the queue with event trigger. */
618     e = CreateEvent(NULL, TRUE, FALSE, NULL);
619     if (!e)
620     {
621         skip("Failed to create timer queue descruction event\n");
622         return;
623     }
624
625     q = CreateTimerQueue();
626     todo_wine
627     ok(q != NULL, "CreateTimerQueue\n");
628
629     SetLastError(0xdeadbeef);
630     ret = DeleteTimerQueueEx(q, e);
631     ok(!ret, "DeleteTimerQueueEx\n");
632     todo_wine
633     {
634     ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
635     ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
636        "Timer destruction event not triggered\n");
637     }
638     CloseHandle(e);
639 }
640
641 START_TEST(sync)
642 {
643     HMODULE hdll = GetModuleHandle("kernel32");
644     pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
645     pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
646
647     test_signalandwait();
648     test_mutex();
649     test_slist();
650     test_event();
651     test_semaphore();
652     test_waitable_timer();
653     test_iocp_callback();
654     test_timer_queue();
655 }