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 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);
45 HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
47 kernel32 = GetModuleHandle("kernel32");
48 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
50 if (!pSignalObjectAndWait)
53 /* invalid parameters */
54 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
55 if (r == ERROR_INVALID_FUNCTION)
57 trace("SignalObjectAndWait not implemented, skipping tests\n");
58 return; /* Win98/ME */
60 ok( r == WAIT_FAILED, "should fail\n");
62 event[0] = CreateEvent(NULL, 0, 0, NULL);
63 event[1] = CreateEvent(NULL, 1, 1, NULL);
65 ok( event[0] && event[1], "failed to create event flags\n");
67 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
68 ok( r == WAIT_FAILED, "should fail\n");
70 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
71 ok( r == WAIT_FAILED, "should fail\n");
74 /* valid parameters */
75 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
76 ok( r == WAIT_OBJECT_0, "should succeed\n");
78 /* event[0] is now signalled */
79 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
80 ok( r == WAIT_OBJECT_0, "should succeed\n");
82 /* event[0] is not signalled */
83 r = WaitForSingleObject(event[0], 0);
84 ok( r == WAIT_TIMEOUT, "event was signalled\n");
86 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
87 ok( r == WAIT_OBJECT_0, "should succeed\n");
89 /* clear event[1] and check for a timeout */
90 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
91 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
92 ok( r == WAIT_TIMEOUT, "should timeout\n");
94 CloseHandle(event[0]);
95 CloseHandle(event[1]);
97 /* create the maximum number of events and make sure
98 * we can wait on that many */
99 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
101 maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
102 ok( maxevents[i] != 0, "should create enough events\n");
104 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
105 ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
107 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
108 if (maxevents[i]) CloseHandle(maxevents[i]);
111 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
112 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
113 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
115 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
116 ok( r == WAIT_OBJECT_0, "should succeed\n");
118 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
119 ok( r == WAIT_FAILED, "should fail\n");
121 r = ReleaseSemaphore(semaphore[0],1,NULL);
122 ok( r == FALSE, "should fail\n");
124 r = ReleaseSemaphore(semaphore[1],1,NULL);
125 ok( r == TRUE, "should succeed\n");
127 CloseHandle(semaphore[0]);
128 CloseHandle(semaphore[1]);
130 /* try a registry key */
131 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
132 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
133 r = pSignalObjectAndWait(file, file, 0, FALSE);
134 ok( r == WAIT_FAILED, "should fail\n");
135 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
139 static void test_mutex(void)
146 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
147 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
148 wait_ret = WaitForSingleObject(hCreated, INFINITE);
149 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
151 /* yes, opening with just READ_CONTROL access allows us to successfully
152 * call ReleaseMutex */
153 hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex");
154 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
155 ret = ReleaseMutex(hOpened);
156 todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError());
157 ret = ReleaseMutex(hCreated);
158 todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
159 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
161 /* test case sensitivity */
163 SetLastError(0xdeadbeef);
164 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
165 ok(!hOpened, "OpenMutex succeeded\n");
166 ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
167 GetLastError() == ERROR_INVALID_NAME, /* win9x */
168 "wrong error %u\n", GetLastError());
170 SetLastError(0xdeadbeef);
171 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
172 ok(!hOpened, "OpenMutex succeeded\n");
173 ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
174 GetLastError() == ERROR_INVALID_NAME, /* win9x */
175 "wrong error %u\n", GetLastError());
177 SetLastError(0xdeadbeef);
178 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
179 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
180 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
181 CloseHandle(hOpened);
183 SetLastError(0xdeadbeef);
184 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
185 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
186 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
187 CloseHandle(hOpened);
189 CloseHandle(hCreated);
192 static void test_slist(void)
198 } item1, item2, item3, *pitem;
200 SLIST_HEADER slist_header, test_header;
204 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
205 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
206 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
207 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
208 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
211 kernel32 = GetModuleHandle("KERNEL32.DLL");
212 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
213 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
214 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
215 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
216 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
217 if (pInitializeSListHead == NULL ||
218 pQueryDepthSList == NULL ||
219 pInterlockedFlushSList == NULL ||
220 pInterlockedPopEntrySList == NULL ||
221 pInterlockedPushEntrySList == NULL)
223 skip("some required slist entrypoints were not found, skipping tests\n");
227 memset(&test_header, 0, sizeof(test_header));
228 memset(&slist_header, 0xFF, sizeof(slist_header));
229 pInitializeSListHead(&slist_header);
230 ok(memcmp(&test_header, &slist_header, sizeof(SLIST_HEADER)) == 0,
231 "InitializeSListHead didn't zero-fill list header\n");
232 size = pQueryDepthSList(&slist_header);
233 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
236 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
237 "previous entry in empty slist wasn't NULL\n");
238 size = pQueryDepthSList(&slist_header);
239 ok(size == 1, "slist with 1 item has size %d\n", size);
242 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
243 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
246 pitem = (struct item*) entry;
247 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
249 size = pQueryDepthSList(&slist_header);
250 ok(size == 2, "slist with 2 items has size %d\n", size);
253 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
254 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
257 pitem = (struct item*) entry;
258 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
260 size = pQueryDepthSList(&slist_header);
261 ok(size == 3, "slist with 3 items has size %d\n", size);
263 entry = pInterlockedPopEntrySList(&slist_header);
264 ok(entry != NULL, "entry shouldn't be NULL\n");
267 pitem = (struct item*) entry;
268 ok(pitem->value == 3, "unexpected entry removed\n");
270 size = pQueryDepthSList(&slist_header);
271 ok(size == 2, "slist with 2 items has size %d\n", size);
273 entry = pInterlockedFlushSList(&slist_header);
274 size = pQueryDepthSList(&slist_header);
275 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
278 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
279 "popping empty slist didn't return NULL\n");
281 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
282 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
285 static void test_event(void)
287 HANDLE handle, handle2;
288 SECURITY_ATTRIBUTES sa;
289 SECURITY_DESCRIPTOR sd;
293 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
294 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
297 sa.nLength = sizeof(sa);
298 sa.lpSecurityDescriptor = &sd;
299 sa.bInheritHandle = FALSE;
301 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
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 NULL dacl */
309 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
310 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
311 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
314 /* sd with empty dacl */
315 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
316 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
317 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
318 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
321 /* test case sensitivity */
323 SetLastError(0xdeadbeef);
324 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
325 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
326 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
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() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
332 CloseHandle( handle2 );
334 SetLastError(0xdeadbeef);
335 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
336 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
337 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
338 CloseHandle( handle2 );
340 SetLastError(0xdeadbeef);
341 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
342 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
343 CloseHandle( handle2 );
345 SetLastError(0xdeadbeef);
346 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
347 ok( !handle2, "OpenEvent succeeded\n");
348 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
349 GetLastError() == ERROR_INVALID_NAME, /* win9x */
350 "wrong error %u\n", GetLastError());
352 CloseHandle( handle );
355 static void test_semaphore(void)
357 HANDLE handle, handle2;
359 /* test case sensitivity */
361 SetLastError(0xdeadbeef);
362 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
363 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
364 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
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() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
370 CloseHandle( handle2 );
372 SetLastError(0xdeadbeef);
373 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
374 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
375 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
376 CloseHandle( handle2 );
378 SetLastError(0xdeadbeef);
379 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
380 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
381 CloseHandle( handle2 );
383 SetLastError(0xdeadbeef);
384 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
385 ok( !handle2, "OpenSemaphore succeeded\n");
386 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
387 GetLastError() == ERROR_INVALID_NAME, /* win9x */
388 "wrong error %u\n", GetLastError());
390 CloseHandle( handle );
393 static void test_waitable_timer(void)
395 HANDLE handle, handle2;
397 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
399 skip("{Create,Open}WaitableTimerA() is not available\n");
403 /* test case sensitivity */
405 SetLastError(0xdeadbeef);
406 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
407 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
408 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
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() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
414 CloseHandle( handle2 );
416 SetLastError(0xdeadbeef);
417 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
418 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
419 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
420 CloseHandle( handle2 );
422 SetLastError(0xdeadbeef);
423 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
424 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
425 CloseHandle( handle2 );
427 SetLastError(0xdeadbeef);
428 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
429 ok( !handle2, "OpenWaitableTimer succeeded\n");
430 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
432 CloseHandle( handle );
435 static HANDLE sem = 0;
437 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
439 ReleaseSemaphore(sem, 1, NULL);
442 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
444 static void test_iocp_callback(void)
446 char temp_path[MAX_PATH];
447 char filename[MAX_PATH];
450 static const char prefix[] = "pfx";
452 HMODULE hmod = GetModuleHandleA("kernel32.dll");
454 const char *buffer = "12345678123456781234567812345678";
455 OVERLAPPED overlapped;
457 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
458 if(!p_BindIoCompletionCallback) {
459 skip("BindIoCompletionCallback not found in this DLL\n");
463 sem = CreateSemaphore(NULL, 0, 1, NULL);
464 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
466 ret = GetTempPathA(MAX_PATH, temp_path);
467 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
468 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
470 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
471 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
473 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
474 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
475 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
477 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
478 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
479 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
481 ret = CloseHandle(hFile);
482 ok( ret, "CloseHandle: error %d\n", GetLastError());
483 ret = DeleteFileA(filename);
484 ok( ret, "DeleteFileA: error %d\n", GetLastError());
486 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
487 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
488 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
490 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
491 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
493 memset(&overlapped, 0, sizeof(overlapped));
494 retb = WriteFile(hFile, (const void *) buffer, 4, &bytesWritten, &overlapped);
495 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
497 ret = WaitForSingleObject(sem, 5000);
498 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
501 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
502 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
503 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
504 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
505 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
506 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
508 ret = CloseHandle(hFile);
509 ok( ret, "CloseHandle: error %d\n", GetLastError());
510 ret = DeleteFileA(filename);
511 ok( ret, "DeleteFileA: error %d\n", GetLastError());
513 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
514 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
515 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
516 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
517 ok(retb == TRUE, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
518 ret = CloseHandle(hFile);
519 ok( ret, "CloseHandle: error %d\n", GetLastError());
520 ret = DeleteFileA(filename);
521 ok( ret, "DeleteFileA: error %d\n", GetLastError());
523 /* win2k3 requires the Flags parameter to be zero */
524 SetLastError(0xdeadbeef);
525 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
526 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
527 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
528 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
530 ok(GetLastError() == ERROR_INVALID_PARAMETER,
531 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
533 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
534 ret = CloseHandle(hFile);
535 ok( ret, "CloseHandle: error %d\n", GetLastError());
536 ret = DeleteFileA(filename);
537 ok( ret, "DeleteFileA: error %d\n", GetLastError());
539 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
540 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
541 ok(GetLastError() == ERROR_INVALID_HANDLE, "Last error is %d\n", GetLastError());
544 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
547 ok(timedOut, "Timer callbacks should always time out\n");
551 struct timer_queue_data1
558 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
560 struct timer_queue_data1 *d = p;
561 ok(timedOut, "Timer callbacks should always time out\n");
562 if (d->t && ++d->num_calls == d->max_calls)
565 SetLastError(0xdeadbeef);
566 /* Note, XP SP2 does *not* do any deadlock checking, so passing
567 INVALID_HANDLE_VALUE here will just hang. */
568 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
569 ok(!ret, "DeleteTimerQueueTimer\n");
570 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
574 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
576 struct timer_queue_data1 *d = p;
577 ok(timedOut, "Timer callbacks should always time out\n");
578 if (d->t && ++d->num_calls == d->max_calls)
580 /* Basically kill the timer since it won't have time to run
582 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
583 ok(ret, "ChangeTimerQueueTimer\n");
587 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
589 struct timer_queue_data1 *d = p;
590 ok(timedOut, "Timer callbacks should always time out\n");
593 /* This tests whether a timer gets flagged for deletion before
594 or after the callback runs. If we start this timer with a
595 period of zero (run once), then ChangeTimerQueueTimer will
596 fail if the timer is already flagged. Hence we really run
597 only once. Otherwise we will run multiple times. */
598 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
599 ok(ret, "ChangeTimerQueueTimer\n");
604 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
606 DWORD delay = (DWORD) p;
607 ok(timedOut, "Timer callbacks should always time out\n");
612 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
614 struct timer_queue_data1 *d = p;
615 ok(timedOut, "Timer callbacks should always time out\n");
616 /* This tests an original implementation bug where a deleted timer may get
617 to run, but it is tricky to set up. */
618 if (d->q && d->num_calls++ == 0)
620 /* First run: delete ourselves, then insert and remove a timer
621 that goes in front of us in the sorted timeout list. Once
622 removed, we will still timeout at the faster timer's due time,
623 but this should be a no-op if we are bug-free. There should
624 not be a second run. We can test the value of num_calls later. */
628 /* The delete will pend while we are in this callback. */
629 SetLastError(0xdeadbeef);
630 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
631 ok(!ret, "DeleteTimerQueueTimer\n");
632 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
634 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
635 ok(ret, "CreateTimerQueueTimer\n");
636 ok(t != NULL, "CreateTimerQueueTimer\n");
638 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
639 ok(ret, "DeleteTimerQueueTimer\n");
641 /* Now we stay alive by hanging around in the callback. */
646 static void test_timer_queue(void)
648 HANDLE q, t1, t2, t3, t4, t5;
649 int n1, n2, n3, n4, n5;
650 struct timer_queue_data1 d1, d2, d3, d4;
654 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
655 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
657 skip("TimerQueue API not present\n");
661 /* Test asynchronous deletion of the queue. */
662 q = pCreateTimerQueue();
663 ok(q != NULL, "CreateTimerQueue\n");
665 SetLastError(0xdeadbeef);
666 ret = pDeleteTimerQueueEx(q, NULL);
667 ok(!ret, "DeleteTimerQueueEx\n");
668 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
670 /* Test synchronous deletion of the queue and running timers. */
671 q = pCreateTimerQueue();
672 ok(q != NULL, "CreateTimerQueue\n");
677 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
679 ok(ret, "CreateTimerQueueTimer\n");
680 ok(t1 != NULL, "CreateTimerQueueTimer\n");
685 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
687 ok(ret, "CreateTimerQueueTimer\n");
688 ok(t2 != NULL, "CreateTimerQueueTimer\n");
693 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
695 ok(ret, "CreateTimerQueueTimer\n");
696 ok(t3 != NULL, "CreateTimerQueueTimer\n");
698 /* Start really late (it won't start). */
701 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
703 ok(ret, "CreateTimerQueueTimer\n");
704 ok(t4 != NULL, "CreateTimerQueueTimer\n");
706 /* Start soon, but delay so long it won't run again. */
709 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
711 ok(ret, "CreateTimerQueueTimer\n");
712 ok(t5 != NULL, "CreateTimerQueueTimer\n");
714 /* Give them a chance to do some work. */
717 /* Test deleting a once-only timer. */
718 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
719 ok(ret, "DeleteTimerQueueTimer\n");
721 /* A periodic timer. */
722 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
723 ok(ret, "DeleteTimerQueueTimer\n");
725 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
726 ok(ret, "DeleteTimerQueueEx\n");
727 ok(n1 == 1, "Timer callback 1\n");
728 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
729 ok(n4 == 0, "Timer callback 4\n");
730 ok(n5 == 1, "Timer callback 5\n");
732 /* Test synchronous deletion of the timer/queue with event trigger. */
733 e = CreateEvent(NULL, TRUE, FALSE, NULL);
734 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
735 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
736 if (!e || !et1 || !et2)
738 skip("Failed to create timer queue descruction event\n");
742 q = pCreateTimerQueue();
743 ok(q != NULL, "CreateTimerQueue\n");
745 /* Run once and finish quickly (should be done when we delete it). */
747 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, (PVOID) 0, 0,
749 ok(ret, "CreateTimerQueueTimer\n");
750 ok(t1 != NULL, "CreateTimerQueueTimer\n");
752 /* Run once and finish slowly (shouldn't be done when we delete it). */
754 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
756 ok(ret, "CreateTimerQueueTimer\n");
757 ok(t2 != NULL, "CreateTimerQueueTimer\n");
759 /* Run once and finish quickly (should be done when we delete it). */
761 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, (PVOID) 0, 0,
763 ok(ret, "CreateTimerQueueTimer\n");
764 ok(t3 != NULL, "CreateTimerQueueTimer\n");
766 /* Run once and finish slowly (shouldn't be done when we delete it). */
768 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
770 ok(ret, "CreateTimerQueueTimer\n");
771 ok(t4 != NULL, "CreateTimerQueueTimer\n");
773 /* Give them a chance to start. */
776 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
777 even if the timer is finished. */
778 SetLastError(0xdeadbeef);
779 ret = pDeleteTimerQueueTimer(q, t1, NULL);
780 ok(!ret, "DeleteTimerQueueTimer\n");
781 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
783 SetLastError(0xdeadbeef);
784 ret = pDeleteTimerQueueTimer(q, t2, NULL);
785 ok(!ret, "DeleteTimerQueueTimer\n");
786 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
788 SetLastError(0xdeadbeef);
789 ret = pDeleteTimerQueueTimer(q, t3, et1);
790 ok(ret, "DeleteTimerQueueTimer\n");
791 ok(GetLastError() == 0xdeadbeef, "DeleteTimerQueueTimer\n");
792 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
793 "Timer destruction event not triggered\n");
795 SetLastError(0xdeadbeef);
796 ret = pDeleteTimerQueueTimer(q, t4, et2);
797 ok(!ret, "DeleteTimerQueueTimer\n");
798 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
799 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
800 "Timer destruction event not triggered\n");
802 SetLastError(0xdeadbeef);
803 ret = pDeleteTimerQueueEx(q, e);
804 ok(!ret, "DeleteTimerQueueEx\n");
805 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
806 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
807 "Queue destruction event not triggered\n");
810 /* Test deleting/changing a timer in execution. */
811 q = pCreateTimerQueue();
812 ok(q != NULL, "CreateTimerQueue\n");
814 /* Test changing a once-only timer before it fires (this is allowed,
815 whereas after it fires you cannot). */
817 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
819 ok(ret, "CreateTimerQueueTimer\n");
820 ok(t1 != NULL, "CreateTimerQueueTimer\n");
821 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
822 ok(ret, "ChangeTimerQueueTimer\n");
828 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
831 ok(ret, "CreateTimerQueueTimer\n");
832 ok(t2 != NULL, "CreateTimerQueueTimer\n");
838 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
841 ok(ret, "CreateTimerQueueTimer\n");
842 ok(t3 != NULL, "CreateTimerQueueTimer\n");
847 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
850 ok(ret, "CreateTimerQueueTimer\n");
851 ok(t4 != NULL, "CreateTimerQueueTimer\n");
855 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
856 ok(ret, "DeleteTimerQueueEx\n");
857 ok(n1 == 1, "ChangeTimerQueueTimer\n");
858 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
859 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
860 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
862 /* Test an obscure bug that was in the original implementation. */
863 q = pCreateTimerQueue();
864 ok(q != NULL, "CreateTimerQueue\n");
866 /* All the work is done in the callback. */
870 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
871 100, WT_EXECUTELONGFUNCTION);
873 ok(ret, "CreateTimerQueueTimer\n");
874 ok(t1 != NULL, "CreateTimerQueueTimer\n");
878 SetLastError(0xdeadbeef);
879 ret = pDeleteTimerQueueEx(q, NULL);
880 ok(!ret, "DeleteTimerQueueEx\n");
881 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
882 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
884 /* Test functions on the default timer queue. */
887 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
889 ok(ret, "CreateTimerQueueTimer, default queue\n");
890 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
892 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
893 ok(ret, "ChangeTimerQueueTimer, default queue\n");
895 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
896 ok(ret, "DeleteTimerQueueTimer, default queue\n");
898 /* Try mixing default and non-default queues. Apparently this works. */
899 q = pCreateTimerQueue();
900 ok(q != NULL, "CreateTimerQueue\n");
904 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
906 ok(ret, "CreateTimerQueueTimer\n");
907 ok(t1 != NULL, "CreateTimerQueueTimer\n");
911 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
913 ok(ret, "CreateTimerQueueTimer\n");
914 ok(t2 != NULL, "CreateTimerQueueTimer\n");
916 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
917 ok(ret, "ChangeTimerQueueTimer\n");
919 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
920 ok(ret, "ChangeTimerQueueTimer\n");
922 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
923 ok(ret, "DeleteTimerQueueTimer\n");
925 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
926 ok(ret, "DeleteTimerQueueTimer\n");
928 /* Try to delete the default queue? In any case: not allowed. */
929 SetLastError(0xdeadbeef);
930 ret = pDeleteTimerQueueEx(NULL, NULL);
931 ok(!ret, "DeleteTimerQueueEx\n");
932 ok(GetLastError() == ERROR_INVALID_HANDLE, "DeleteTimerQueueEx\n");
934 SetLastError(0xdeadbeef);
935 ret = pDeleteTimerQueueEx(q, NULL);
936 ok(!ret, "DeleteTimerQueueEx\n");
937 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
942 HMODULE hdll = GetModuleHandle("kernel32");
943 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
944 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
945 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
946 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
947 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
948 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
949 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
951 test_signalandwait();
956 test_waitable_timer();
957 test_iocp_callback();