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
25 #define _WIN32_WINNT 0x500
28 #include "wine/test.h"
30 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
31 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
33 static void test_signalandwait(void)
35 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
39 HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
41 kernel32 = GetModuleHandle("kernel32");
42 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
44 if (!pSignalObjectAndWait)
47 /* invalid parameters */
48 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
49 if (r == ERROR_INVALID_FUNCTION)
51 trace("SignalObjectAndWait not implemented, skipping tests\n");
52 return; /* Win98/ME */
54 ok( r == WAIT_FAILED, "should fail\n");
56 event[0] = CreateEvent(NULL, 0, 0, NULL);
57 event[1] = CreateEvent(NULL, 1, 1, NULL);
59 ok( event[0] && event[1], "failed to create event flags\n");
61 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
62 ok( r == WAIT_FAILED, "should fail\n");
64 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
65 ok( r == WAIT_FAILED, "should fail\n");
68 /* valid parameters */
69 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
70 ok( r == WAIT_OBJECT_0, "should succeed\n");
72 /* event[0] is now signalled */
73 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
74 ok( r == WAIT_OBJECT_0, "should succeed\n");
76 /* event[0] is not signalled */
77 r = WaitForSingleObject(event[0], 0);
78 ok( r == WAIT_TIMEOUT, "event was signalled\n");
80 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
81 ok( r == WAIT_OBJECT_0, "should succeed\n");
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");
88 CloseHandle(event[0]);
89 CloseHandle(event[1]);
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++)
95 maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
96 ok( maxevents[i] != 0, "should create enough events\n");
98 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
99 ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
101 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
102 if (maxevents[i]) CloseHandle(maxevents[i]);
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");
109 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
110 ok( r == WAIT_OBJECT_0, "should succeed\n");
112 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
113 ok( r == WAIT_FAILED, "should fail\n");
115 r = ReleaseSemaphore(semaphore[0],1,NULL);
116 ok( r == FALSE, "should fail\n");
118 r = ReleaseSemaphore(semaphore[1],1,NULL);
119 ok( r == TRUE, "should succeed\n");
121 CloseHandle(semaphore[0]);
122 CloseHandle(semaphore[1]);
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");
133 static void test_mutex(void)
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);
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());
155 /* test case sensitivity */
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());
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());
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);
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);
183 CloseHandle(hCreated);
186 static void test_slist(void)
192 } item1, item2, item3, *pitem;
194 SLIST_HEADER slist_header, test_header;
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);
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)
217 skip("some required slist entrypoints were not found, skipping tests\n");
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);
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);
236 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
237 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
240 pitem = (struct item*) entry;
241 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
243 size = pQueryDepthSList(&slist_header);
244 ok(size == 2, "slist with 2 items has size %d\n", size);
247 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
248 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
251 pitem = (struct item*) entry;
252 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
254 size = pQueryDepthSList(&slist_header);
255 ok(size == 3, "slist with 3 items has size %d\n", size);
257 entry = pInterlockedPopEntrySList(&slist_header);
258 ok(entry != NULL, "entry shouldn't be NULL\n");
261 pitem = (struct item*) entry;
262 ok(pitem->value == 3, "unexpected entry removed\n");
264 size = pQueryDepthSList(&slist_header);
265 ok(size == 2, "slist with 2 items has size %d\n", size);
267 entry = pInterlockedFlushSList(&slist_header);
268 size = pQueryDepthSList(&slist_header);
269 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
272 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
273 "popping empty slist didn't return NULL\n");
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");
279 static void test_event(void)
281 HANDLE handle, handle2;
282 SECURITY_ATTRIBUTES sa;
283 SECURITY_DESCRIPTOR sd;
287 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
288 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
291 sa.nLength = sizeof(sa);
292 sa.lpSecurityDescriptor = &sd;
293 sa.bInheritHandle = FALSE;
295 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
298 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
299 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
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());
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());
315 /* test case sensitivity */
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());
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 );
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 );
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 );
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());
346 CloseHandle( handle );
349 static void test_semaphore(void)
351 HANDLE handle, handle2;
353 /* test case sensitivity */
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());
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 );
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 );
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 );
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());
384 CloseHandle( handle );
387 static void test_waitable_timer(void)
389 HANDLE handle, handle2;
391 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
393 skip("{Create,Open}WaitableTimerA() is not available\n");
397 /* test case sensitivity */
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());
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 );
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 );
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 );
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());
426 CloseHandle( handle );
429 static HANDLE sem = 0;
431 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
433 ReleaseSemaphore(sem, 1, NULL);
436 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
438 static void test_iocp_callback(void)
440 char temp_path[MAX_PATH];
441 char filename[MAX_PATH];
444 static const char prefix[] = "pfx";
446 HMODULE hmod = GetModuleHandleA("kernel32.dll");
448 const char *buffer = "12345678123456781234567812345678";
449 OVERLAPPED overlapped;
451 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
452 if(!p_BindIoCompletionCallback) {
453 skip("BindIoCompletionCallback not found in this DLL\n");
457 sem = CreateSemaphore(NULL, 0, 1, NULL);
458 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
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");
464 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
465 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
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());
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());
475 ret = CloseHandle(hFile);
476 ok( ret, "CloseHandle: error %d\n", GetLastError());
477 ret = DeleteFileA(filename);
478 ok( ret, "DeleteFileA: error %d\n", GetLastError());
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());
484 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
485 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
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());
491 ret = WaitForSingleObject(sem, 5000);
492 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
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());
502 ret = CloseHandle(hFile);
503 ok( ret, "CloseHandle: error %d\n", GetLastError());
504 ret = DeleteFileA(filename);
505 ok( ret, "DeleteFileA: error %d\n", GetLastError());
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());
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);
524 ok(GetLastError() == ERROR_INVALID_PARAMETER,
525 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
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());
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());
538 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
541 ok(timedOut, "Timer callbacks should always time out\n");
545 static void test_timer_queue(void)
547 HANDLE q, t1, t2, t3, t4, t5;
548 int n1, n2, n3, n4, n5;
552 /* Test asynchronous deletion of the queue. */
553 q = CreateTimerQueue();
555 ok(q != NULL, "CreateTimerQueue\n");
557 SetLastError(0xdeadbeef);
558 ret = DeleteTimerQueueEx(q, NULL);
559 ok(!ret, "DeleteTimerQueueEx\n");
561 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
563 /* Test synchronous deletion of the queue and running timers. */
564 q = CreateTimerQueue();
566 ok(q != NULL, "CreateTimerQueue\n");
571 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
573 ok(ret, "CreateTimerQueueTimer\n");
578 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
580 ok(ret, "CreateTimerQueueTimer\n");
585 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
587 ok(ret, "CreateTimerQueueTimer\n");
589 /* Start really late (it won't start). */
592 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
594 ok(ret, "CreateTimerQueueTimer\n");
596 /* Start soon, but delay so long it won't run again. */
599 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
601 ok(ret, "CreateTimerQueueTimer\n");
603 /* Give them a chance to do some work. */
606 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
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");
613 ok(n4 == 0, "Timer callback 4\n");
615 ok(n5 == 1, "Timer callback 5\n");
617 /* Test synchronous deletion of the queue with event trigger. */
618 e = CreateEvent(NULL, TRUE, FALSE, NULL);
621 skip("Failed to create timer queue descruction event\n");
625 q = CreateTimerQueue();
627 ok(q != NULL, "CreateTimerQueue\n");
629 SetLastError(0xdeadbeef);
630 ret = DeleteTimerQueueEx(q, e);
631 ok(!ret, "DeleteTimerQueueEx\n");
634 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
635 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
636 "Timer destruction event not triggered\n");
643 HMODULE hdll = GetModuleHandle("kernel32");
644 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
645 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
647 test_signalandwait();
652 test_waitable_timer();
653 test_iocp_callback();