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 #define _WIN32_WINNT 0x500
28 #include "wine/test.h"
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);
39 static void test_signalandwait(void)
41 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
44 HANDLE event[2], semaphore[2], file;
46 kernel32 = GetModuleHandle("kernel32");
47 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
49 if (!pSignalObjectAndWait)
52 /* invalid parameters */
53 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
54 if (r == ERROR_INVALID_FUNCTION)
56 win_skip("SignalObjectAndWait is not implemented\n");
57 return; /* Win98/ME */
59 ok( r == WAIT_FAILED, "should fail\n");
61 event[0] = CreateEvent(NULL, 0, 0, NULL);
62 event[1] = CreateEvent(NULL, 1, 1, NULL);
64 ok( event[0] && event[1], "failed to create event flags\n");
66 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
67 ok( r == WAIT_FAILED, "should fail\n");
69 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
70 ok( r == WAIT_FAILED, "should fail\n");
73 /* valid parameters */
74 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
75 ok( r == WAIT_OBJECT_0, "should succeed\n");
77 /* event[0] is now signalled */
78 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
79 ok( r == WAIT_OBJECT_0, "should succeed\n");
81 /* event[0] is not signalled */
82 r = WaitForSingleObject(event[0], 0);
83 ok( r == WAIT_TIMEOUT, "event was signalled\n");
85 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
86 ok( r == WAIT_OBJECT_0, "should succeed\n");
88 /* clear event[1] and check for a timeout */
89 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
90 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
91 ok( r == WAIT_TIMEOUT, "should timeout\n");
93 CloseHandle(event[0]);
94 CloseHandle(event[1]);
97 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
98 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
99 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
101 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
102 ok( r == WAIT_OBJECT_0, "should succeed\n");
104 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
105 ok( r == WAIT_FAILED, "should fail\n");
107 r = ReleaseSemaphore(semaphore[0],1,NULL);
108 ok( r == FALSE, "should fail\n");
110 r = ReleaseSemaphore(semaphore[1],1,NULL);
111 ok( r == TRUE, "should succeed\n");
113 CloseHandle(semaphore[0]);
114 CloseHandle(semaphore[1]);
116 /* try a registry key */
117 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
118 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
119 r = pSignalObjectAndWait(file, file, 0, FALSE);
120 ok( r == WAIT_FAILED, "should fail\n");
121 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
125 static void test_mutex(void)
132 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
133 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
134 wait_ret = WaitForSingleObject(hCreated, INFINITE);
135 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
137 /* yes, opening with just READ_CONTROL access allows us to successfully
138 * call ReleaseMutex */
139 hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
140 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
141 ret = ReleaseMutex(hOpened);
142 todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError());
143 ret = ReleaseMutex(hCreated);
144 todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
145 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
147 /* test case sensitivity */
149 SetLastError(0xdeadbeef);
150 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
151 ok(!hOpened, "OpenMutex succeeded\n");
152 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
154 SetLastError(0xdeadbeef);
155 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
156 ok(!hOpened, "OpenMutex succeeded\n");
157 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
159 SetLastError(0xdeadbeef);
160 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
161 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
162 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
163 CloseHandle(hOpened);
165 SetLastError(0xdeadbeef);
166 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
167 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
168 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
169 CloseHandle(hOpened);
171 CloseHandle(hCreated);
174 static void test_slist(void)
180 } item1, item2, item3, *pitem;
182 SLIST_HEADER slist_header;
186 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
187 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
188 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
189 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
190 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
193 kernel32 = GetModuleHandle("KERNEL32.DLL");
194 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
195 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
196 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
197 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
198 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
199 if (pInitializeSListHead == NULL ||
200 pQueryDepthSList == NULL ||
201 pInterlockedFlushSList == NULL ||
202 pInterlockedPopEntrySList == NULL ||
203 pInterlockedPushEntrySList == NULL)
205 win_skip("some required slist entrypoints were not found, skipping tests\n");
209 memset(&slist_header, 0xFF, sizeof(slist_header));
210 pInitializeSListHead(&slist_header);
211 size = pQueryDepthSList(&slist_header);
212 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
215 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
216 "previous entry in empty slist wasn't NULL\n");
217 size = pQueryDepthSList(&slist_header);
218 ok(size == 1, "slist with 1 item has size %d\n", size);
221 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
222 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
225 pitem = (struct item*) entry;
226 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
228 size = pQueryDepthSList(&slist_header);
229 ok(size == 2, "slist with 2 items has size %d\n", size);
232 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
233 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
236 pitem = (struct item*) entry;
237 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
239 size = pQueryDepthSList(&slist_header);
240 ok(size == 3, "slist with 3 items has size %d\n", size);
242 entry = pInterlockedPopEntrySList(&slist_header);
243 ok(entry != NULL, "entry shouldn't be NULL\n");
246 pitem = (struct item*) entry;
247 ok(pitem->value == 3, "unexpected entry removed\n");
249 size = pQueryDepthSList(&slist_header);
250 ok(size == 2, "slist with 2 items has size %d\n", size);
252 entry = pInterlockedFlushSList(&slist_header);
253 size = pQueryDepthSList(&slist_header);
254 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
257 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
258 "popping empty slist didn't return NULL\n");
260 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
261 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
264 static void test_event(void)
266 HANDLE handle, handle2;
267 SECURITY_ATTRIBUTES sa;
268 SECURITY_DESCRIPTOR sd;
272 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
273 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
276 sa.nLength = sizeof(sa);
277 sa.lpSecurityDescriptor = &sd;
278 sa.bInheritHandle = FALSE;
280 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
283 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
284 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
287 /* sd with NULL dacl */
288 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
289 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
290 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
293 /* sd with empty dacl */
294 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
295 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
296 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
297 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
300 /* test case sensitivity */
302 SetLastError(0xdeadbeef);
303 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
304 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
305 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
307 SetLastError(0xdeadbeef);
308 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
309 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
310 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
311 CloseHandle( handle2 );
313 SetLastError(0xdeadbeef);
314 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
315 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
316 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
317 CloseHandle( handle2 );
319 SetLastError(0xdeadbeef);
320 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
321 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
322 CloseHandle( handle2 );
324 SetLastError(0xdeadbeef);
325 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
326 ok( !handle2, "OpenEvent succeeded\n");
327 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
329 CloseHandle( handle );
332 static void test_semaphore(void)
334 HANDLE handle, handle2;
336 /* test case sensitivity */
338 SetLastError(0xdeadbeef);
339 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
340 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
341 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
343 SetLastError(0xdeadbeef);
344 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
345 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
346 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
347 CloseHandle( handle2 );
349 SetLastError(0xdeadbeef);
350 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
351 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
352 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
353 CloseHandle( handle2 );
355 SetLastError(0xdeadbeef);
356 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
357 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
358 CloseHandle( handle2 );
360 SetLastError(0xdeadbeef);
361 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
362 ok( !handle2, "OpenSemaphore succeeded\n");
363 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
365 CloseHandle( handle );
368 static void test_waitable_timer(void)
370 HANDLE handle, handle2;
372 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
374 win_skip("{Create,Open}WaitableTimerA() is not available\n");
378 /* test case sensitivity */
380 SetLastError(0xdeadbeef);
381 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
382 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
383 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
385 SetLastError(0xdeadbeef);
386 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
387 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
388 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
389 CloseHandle( handle2 );
391 SetLastError(0xdeadbeef);
392 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
393 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
394 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
395 CloseHandle( handle2 );
397 SetLastError(0xdeadbeef);
398 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
399 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
400 CloseHandle( handle2 );
402 SetLastError(0xdeadbeef);
403 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
404 ok( !handle2, "OpenWaitableTimer succeeded\n");
405 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
406 GetLastError() == ERROR_INVALID_NAME, /* win98 */
407 "wrong error %u\n", GetLastError());
409 CloseHandle( handle );
412 static HANDLE sem = 0;
414 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
416 ReleaseSemaphore(sem, 1, NULL);
419 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
421 static void test_iocp_callback(void)
423 char temp_path[MAX_PATH];
424 char filename[MAX_PATH];
427 static const char prefix[] = "pfx";
429 HMODULE hmod = GetModuleHandleA("kernel32.dll");
431 const char *buffer = "12345678123456781234567812345678";
432 OVERLAPPED overlapped;
434 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
435 if(!p_BindIoCompletionCallback) {
436 win_skip("BindIoCompletionCallback not found in this DLL\n");
440 sem = CreateSemaphore(NULL, 0, 1, NULL);
441 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
443 ret = GetTempPathA(MAX_PATH, temp_path);
444 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
445 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
447 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
448 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
450 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
451 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
452 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
454 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
455 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
456 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
458 ret = CloseHandle(hFile);
459 ok( ret, "CloseHandle: error %d\n", GetLastError());
460 ret = DeleteFileA(filename);
461 ok( ret, "DeleteFileA: error %d\n", GetLastError());
463 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
464 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
465 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
467 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
468 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
470 memset(&overlapped, 0, sizeof(overlapped));
471 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
472 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
474 ret = WaitForSingleObject(sem, 5000);
475 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
478 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
479 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
480 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
481 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
482 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
483 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
485 ret = CloseHandle(hFile);
486 ok( ret, "CloseHandle: error %d\n", GetLastError());
487 ret = DeleteFileA(filename);
488 ok( ret, "DeleteFileA: error %d\n", GetLastError());
490 /* win2k3 requires the Flags parameter to be zero */
491 SetLastError(0xdeadbeef);
492 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
493 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
494 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
495 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
497 ok(GetLastError() == ERROR_INVALID_PARAMETER,
498 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
500 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
501 ret = CloseHandle(hFile);
502 ok( ret, "CloseHandle: error %d\n", GetLastError());
503 ret = DeleteFileA(filename);
504 ok( ret, "DeleteFileA: error %d\n", GetLastError());
506 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
507 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
508 ok(GetLastError() == ERROR_INVALID_HANDLE ||
509 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
510 "Last error is %d\n", GetLastError());
513 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
516 ok(timedOut, "Timer callbacks should always time out\n");
520 struct timer_queue_data1
527 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
529 struct timer_queue_data1 *d = p;
530 ok(timedOut, "Timer callbacks should always time out\n");
531 if (d->t && ++d->num_calls == d->max_calls)
534 SetLastError(0xdeadbeef);
535 /* Note, XP SP2 does *not* do any deadlock checking, so passing
536 INVALID_HANDLE_VALUE here will just hang. */
537 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
538 ok(!ret, "DeleteTimerQueueTimer\n");
539 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
543 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
545 struct timer_queue_data1 *d = p;
546 ok(timedOut, "Timer callbacks should always time out\n");
547 if (d->t && ++d->num_calls == d->max_calls)
549 /* Basically kill the timer since it won't have time to run
551 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
552 ok(ret, "ChangeTimerQueueTimer\n");
556 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
558 struct timer_queue_data1 *d = p;
559 ok(timedOut, "Timer callbacks should always time out\n");
562 /* This tests whether a timer gets flagged for deletion before
563 or after the callback runs. If we start this timer with a
564 period of zero (run once), then ChangeTimerQueueTimer will
565 fail if the timer is already flagged. Hence we really run
566 only once. Otherwise we will run multiple times. */
567 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
568 ok(ret, "ChangeTimerQueueTimer\n");
573 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
575 DWORD_PTR delay = (DWORD_PTR) p;
576 ok(timedOut, "Timer callbacks should always time out\n");
581 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
583 struct timer_queue_data1 *d = p;
584 ok(timedOut, "Timer callbacks should always time out\n");
585 /* This tests an original implementation bug where a deleted timer may get
586 to run, but it is tricky to set up. */
587 if (d->q && d->num_calls++ == 0)
589 /* First run: delete ourselves, then insert and remove a timer
590 that goes in front of us in the sorted timeout list. Once
591 removed, we will still timeout at the faster timer's due time,
592 but this should be a no-op if we are bug-free. There should
593 not be a second run. We can test the value of num_calls later. */
597 /* The delete will pend while we are in this callback. */
598 SetLastError(0xdeadbeef);
599 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
600 ok(!ret, "DeleteTimerQueueTimer\n");
601 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
603 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
604 ok(ret, "CreateTimerQueueTimer\n");
605 ok(t != NULL, "CreateTimerQueueTimer\n");
607 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
608 ok(ret, "DeleteTimerQueueTimer\n");
610 /* Now we stay alive by hanging around in the callback. */
615 static void test_timer_queue(void)
617 HANDLE q, t1, t2, t3, t4, t5;
618 int n1, n2, n3, n4, n5;
619 struct timer_queue_data1 d1, d2, d3, d4;
623 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
624 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
626 win_skip("TimerQueue API not present\n");
630 /* Test asynchronous deletion of the queue. */
631 q = pCreateTimerQueue();
632 ok(q != NULL, "CreateTimerQueue\n");
634 SetLastError(0xdeadbeef);
635 ret = pDeleteTimerQueueEx(q, NULL);
636 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
637 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
640 /* Test synchronous deletion of the queue and running timers. */
641 q = pCreateTimerQueue();
642 ok(q != NULL, "CreateTimerQueue\n");
647 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
649 ok(ret, "CreateTimerQueueTimer\n");
650 ok(t1 != NULL, "CreateTimerQueueTimer\n");
655 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
657 ok(ret, "CreateTimerQueueTimer\n");
658 ok(t2 != NULL, "CreateTimerQueueTimer\n");
663 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
665 ok(ret, "CreateTimerQueueTimer\n");
666 ok(t3 != NULL, "CreateTimerQueueTimer\n");
668 /* Start really late (it won't start). */
671 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
673 ok(ret, "CreateTimerQueueTimer\n");
674 ok(t4 != NULL, "CreateTimerQueueTimer\n");
676 /* Start soon, but delay so long it won't run again. */
679 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
681 ok(ret, "CreateTimerQueueTimer\n");
682 ok(t5 != NULL, "CreateTimerQueueTimer\n");
684 /* Give them a chance to do some work. */
687 /* Test deleting a once-only timer. */
688 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
689 ok(ret, "DeleteTimerQueueTimer\n");
691 /* A periodic timer. */
692 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
693 ok(ret, "DeleteTimerQueueTimer\n");
695 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
696 ok(ret, "DeleteTimerQueueEx\n");
697 ok(n1 == 1, "Timer callback 1\n");
698 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
699 ok(n4 == 0, "Timer callback 4\n");
700 ok(n5 == 1, "Timer callback 5\n");
702 /* Test synchronous deletion of the timer/queue with event trigger. */
703 e = CreateEvent(NULL, TRUE, FALSE, NULL);
704 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
705 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
706 if (!e || !et1 || !et2)
708 skip("Failed to create timer queue descruction event\n");
712 q = pCreateTimerQueue();
713 ok(q != NULL, "CreateTimerQueue\n");
715 /* Run once and finish quickly (should be done when we delete it). */
717 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
718 ok(ret, "CreateTimerQueueTimer\n");
719 ok(t1 != NULL, "CreateTimerQueueTimer\n");
721 /* Run once and finish slowly (shouldn't be done when we delete it). */
723 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
725 ok(ret, "CreateTimerQueueTimer\n");
726 ok(t2 != NULL, "CreateTimerQueueTimer\n");
728 /* Run once and finish quickly (should be done when we delete it). */
730 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
731 ok(ret, "CreateTimerQueueTimer\n");
732 ok(t3 != NULL, "CreateTimerQueueTimer\n");
734 /* Run once and finish slowly (shouldn't be done when we delete it). */
736 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
738 ok(ret, "CreateTimerQueueTimer\n");
739 ok(t4 != NULL, "CreateTimerQueueTimer\n");
741 /* Give them a chance to start. */
744 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
745 even if the timer is finished. */
746 SetLastError(0xdeadbeef);
747 ret = pDeleteTimerQueueTimer(q, t1, NULL);
748 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
749 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
752 SetLastError(0xdeadbeef);
753 ret = pDeleteTimerQueueTimer(q, t2, NULL);
754 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
755 ok(GetLastError() == ERROR_IO_PENDING,
756 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
759 SetLastError(0xdeadbeef);
760 ret = pDeleteTimerQueueTimer(q, t3, et1);
761 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
762 ok(GetLastError() == 0xdeadbeef,
763 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
765 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
766 "Timer destruction event not triggered\n");
768 SetLastError(0xdeadbeef);
769 ret = pDeleteTimerQueueTimer(q, t4, et2);
770 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
771 ok(GetLastError() == ERROR_IO_PENDING,
772 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
774 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
775 "Timer destruction event not triggered\n");
777 SetLastError(0xdeadbeef);
778 ret = pDeleteTimerQueueEx(q, e);
779 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
780 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
782 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
783 "Queue destruction event not triggered\n");
786 /* Test deleting/changing a timer in execution. */
787 q = pCreateTimerQueue();
788 ok(q != NULL, "CreateTimerQueue\n");
790 /* Test changing a once-only timer before it fires (this is allowed,
791 whereas after it fires you cannot). */
793 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
795 ok(ret, "CreateTimerQueueTimer\n");
796 ok(t1 != NULL, "CreateTimerQueueTimer\n");
797 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
798 ok(ret, "ChangeTimerQueueTimer\n");
804 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
807 ok(ret, "CreateTimerQueueTimer\n");
808 ok(t2 != NULL, "CreateTimerQueueTimer\n");
814 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
817 ok(ret, "CreateTimerQueueTimer\n");
818 ok(t3 != NULL, "CreateTimerQueueTimer\n");
823 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
826 ok(ret, "CreateTimerQueueTimer\n");
827 ok(t4 != NULL, "CreateTimerQueueTimer\n");
831 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
832 ok(ret, "DeleteTimerQueueEx\n");
833 ok(n1 == 1, "ChangeTimerQueueTimer\n");
834 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
835 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
836 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
838 /* Test an obscure bug that was in the original implementation. */
839 q = pCreateTimerQueue();
840 ok(q != NULL, "CreateTimerQueue\n");
842 /* All the work is done in the callback. */
846 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
847 100, WT_EXECUTELONGFUNCTION);
849 ok(ret, "CreateTimerQueueTimer\n");
850 ok(t1 != NULL, "CreateTimerQueueTimer\n");
854 SetLastError(0xdeadbeef);
855 ret = pDeleteTimerQueueEx(q, NULL);
856 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
857 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
859 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
861 /* Test functions on the default timer queue. */
864 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
866 ok(ret, "CreateTimerQueueTimer, default queue\n");
867 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
869 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
870 ok(ret, "ChangeTimerQueueTimer, default queue\n");
872 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
873 ok(ret, "DeleteTimerQueueTimer, default queue\n");
875 /* Try mixing default and non-default queues. Apparently this works. */
876 q = pCreateTimerQueue();
877 ok(q != NULL, "CreateTimerQueue\n");
881 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
883 ok(ret, "CreateTimerQueueTimer\n");
884 ok(t1 != NULL, "CreateTimerQueueTimer\n");
888 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
890 ok(ret, "CreateTimerQueueTimer\n");
891 ok(t2 != NULL, "CreateTimerQueueTimer\n");
893 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
894 ok(ret, "ChangeTimerQueueTimer\n");
896 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
897 ok(ret, "ChangeTimerQueueTimer\n");
899 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
900 ok(ret, "DeleteTimerQueueTimer\n");
902 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
903 ok(ret, "DeleteTimerQueueTimer\n");
905 /* Try to delete the default queue? In any case: not allowed. */
906 SetLastError(0xdeadbeef);
907 ret = pDeleteTimerQueueEx(NULL, NULL);
908 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
909 ok(GetLastError() == ERROR_INVALID_HANDLE,
910 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
913 SetLastError(0xdeadbeef);
914 ret = pDeleteTimerQueueEx(q, NULL);
915 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
916 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
920 static HANDLE modify_handle(HANDLE handle, DWORD modify)
922 DWORD tmp = HandleToULong(handle);
924 return ULongToHandle(tmp);
927 static void test_WaitForSingleObject(void)
929 HANDLE signaled, nonsignaled, invalid;
932 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
933 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
934 invalid = (HANDLE) 0xdeadbee0;
936 /* invalid handle with different values for lower 2 bits */
937 SetLastError(0xdeadbeef);
938 ret = WaitForSingleObject(invalid, 0);
939 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
940 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
942 SetLastError(0xdeadbeef);
943 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
944 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
945 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
947 SetLastError(0xdeadbeef);
948 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
949 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
950 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
952 SetLastError(0xdeadbeef);
953 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
954 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
955 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
957 /* valid handle with different values for lower 2 bits */
958 SetLastError(0xdeadbeef);
959 ret = WaitForSingleObject(nonsignaled, 0);
960 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
961 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
963 SetLastError(0xdeadbeef);
964 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
965 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
966 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
968 SetLastError(0xdeadbeef);
969 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
970 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
971 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
973 SetLastError(0xdeadbeef);
974 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
975 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
976 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
978 /* valid handle with different values for lower 2 bits */
979 SetLastError(0xdeadbeef);
980 ret = WaitForSingleObject(signaled, 0);
981 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
982 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
984 SetLastError(0xdeadbeef);
985 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
986 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
987 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
989 SetLastError(0xdeadbeef);
990 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
991 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
992 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
994 SetLastError(0xdeadbeef);
995 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
996 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
997 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
999 CloseHandle(signaled);
1000 CloseHandle(nonsignaled);
1003 static void test_WaitForMultipleObjects(void)
1007 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1009 /* create the maximum number of events and make sure
1010 * we can wait on that many */
1011 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1013 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1014 ok( maxevents[i] != 0, "should create enough events\n");
1017 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1018 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1019 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1020 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1021 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1022 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1023 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1025 /* the lowest index is checked first and remaining events are untouched */
1026 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1027 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1030 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1031 if (maxevents[i]) CloseHandle(maxevents[i]);
1036 HMODULE hdll = GetModuleHandle("kernel32");
1037 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1038 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1039 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1040 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1041 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1042 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1043 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1045 test_signalandwait();
1050 test_waitable_timer();
1051 test_iocp_callback();
1053 test_WaitForSingleObject();
1054 test_WaitForMultipleObjects();