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