configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / kernel32 / tests / sync.c
blobea36fc608473430cc203fbfbe5b719e892fa6cab
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 #define _WIN32_WINNT 0x500
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windef.h>
26 #include <winbase.h>
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);
42 HMODULE kernel32;
43 DWORD r;
44 int i;
45 HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
47 kernel32 = GetModuleHandle("kernel32");
48 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
50 if (!pSignalObjectAndWait)
51 return;
53 /* invalid parameters */
54 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
55 if (r == ERROR_INVALID_FUNCTION)
57 win_skip("SignalObjectAndWait is not implemented\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]);
110 /* semaphores */
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");
136 CloseHandle(file);
139 static void test_mutex(void)
141 DWORD wait_ret;
142 BOOL ret;
143 HANDLE hCreated;
144 HANDLE hOpened;
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)
194 struct item
196 SLIST_ENTRY entry;
197 int value;
198 } item1, item2, item3, *pitem;
200 SLIST_HEADER slist_header;
201 PSLIST_ENTRY entry;
202 USHORT size;
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);
209 HMODULE kernel32;
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 win_skip("some required slist entrypoints were not found, skipping tests\n");
224 return;
227 memset(&slist_header, 0xFF, sizeof(slist_header));
228 pInitializeSListHead(&slist_header);
229 size = pQueryDepthSList(&slist_header);
230 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
232 item1.value = 1;
233 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
234 "previous entry in empty slist wasn't NULL\n");
235 size = pQueryDepthSList(&slist_header);
236 ok(size == 1, "slist with 1 item has size %d\n", size);
238 item2.value = 2;
239 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
240 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
241 if (entry != NULL)
243 pitem = (struct item*) entry;
244 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
246 size = pQueryDepthSList(&slist_header);
247 ok(size == 2, "slist with 2 items has size %d\n", size);
249 item3.value = 3;
250 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
251 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
252 if (entry != NULL)
254 pitem = (struct item*) entry;
255 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
257 size = pQueryDepthSList(&slist_header);
258 ok(size == 3, "slist with 3 items has size %d\n", size);
260 entry = pInterlockedPopEntrySList(&slist_header);
261 ok(entry != NULL, "entry shouldn't be NULL\n");
262 if (entry != NULL)
264 pitem = (struct item*) entry;
265 ok(pitem->value == 3, "unexpected entry removed\n");
267 size = pQueryDepthSList(&slist_header);
268 ok(size == 2, "slist with 2 items has size %d\n", size);
270 entry = pInterlockedFlushSList(&slist_header);
271 size = pQueryDepthSList(&slist_header);
272 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
273 if (size == 0)
275 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
276 "popping empty slist didn't return NULL\n");
278 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
279 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
282 static void test_event(void)
284 HANDLE handle, handle2;
285 SECURITY_ATTRIBUTES sa;
286 SECURITY_DESCRIPTOR sd;
287 ACL acl;
289 /* no sd */
290 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
291 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
292 CloseHandle(handle);
294 sa.nLength = sizeof(sa);
295 sa.lpSecurityDescriptor = &sd;
296 sa.bInheritHandle = FALSE;
298 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
300 /* blank sd */
301 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
302 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
303 CloseHandle(handle);
305 /* sd with NULL dacl */
306 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
307 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
308 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
309 CloseHandle(handle);
311 /* sd with empty dacl */
312 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
313 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
314 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
315 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
316 CloseHandle(handle);
318 /* test case sensitivity */
320 SetLastError(0xdeadbeef);
321 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
322 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
323 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
325 SetLastError(0xdeadbeef);
326 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
327 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
328 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
329 CloseHandle( handle2 );
331 SetLastError(0xdeadbeef);
332 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
333 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
334 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
335 CloseHandle( handle2 );
337 SetLastError(0xdeadbeef);
338 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
339 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
340 CloseHandle( handle2 );
342 SetLastError(0xdeadbeef);
343 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
344 ok( !handle2, "OpenEvent succeeded\n");
345 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
346 GetLastError() == ERROR_INVALID_NAME, /* win9x */
347 "wrong error %u\n", GetLastError());
349 CloseHandle( handle );
352 static void test_semaphore(void)
354 HANDLE handle, handle2;
356 /* test case sensitivity */
358 SetLastError(0xdeadbeef);
359 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
360 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
361 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
363 SetLastError(0xdeadbeef);
364 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
365 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
366 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
367 CloseHandle( handle2 );
369 SetLastError(0xdeadbeef);
370 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
371 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
372 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
373 CloseHandle( handle2 );
375 SetLastError(0xdeadbeef);
376 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
377 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
378 CloseHandle( handle2 );
380 SetLastError(0xdeadbeef);
381 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
382 ok( !handle2, "OpenSemaphore succeeded\n");
383 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
384 GetLastError() == ERROR_INVALID_NAME, /* win9x */
385 "wrong error %u\n", GetLastError());
387 CloseHandle( handle );
390 static void test_waitable_timer(void)
392 HANDLE handle, handle2;
394 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
396 win_skip("{Create,Open}WaitableTimerA() is not available\n");
397 return;
400 /* test case sensitivity */
402 SetLastError(0xdeadbeef);
403 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
404 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
405 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
407 SetLastError(0xdeadbeef);
408 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
409 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
410 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
411 CloseHandle( handle2 );
413 SetLastError(0xdeadbeef);
414 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
415 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
416 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
417 CloseHandle( handle2 );
419 SetLastError(0xdeadbeef);
420 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
421 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
422 CloseHandle( handle2 );
424 SetLastError(0xdeadbeef);
425 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
426 ok( !handle2, "OpenWaitableTimer succeeded\n");
427 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
428 GetLastError() == ERROR_INVALID_NAME, /* win98 */
429 "wrong error %u\n", GetLastError());
431 CloseHandle( handle );
434 static HANDLE sem = 0;
436 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
438 ReleaseSemaphore(sem, 1, NULL);
441 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
443 static void test_iocp_callback(void)
445 char temp_path[MAX_PATH];
446 char filename[MAX_PATH];
447 DWORD ret;
448 BOOL retb;
449 static const char prefix[] = "pfx";
450 HANDLE hFile;
451 HMODULE hmod = GetModuleHandleA("kernel32.dll");
452 DWORD bytesWritten;
453 const char *buffer = "12345678123456781234567812345678";
454 OVERLAPPED overlapped;
456 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
457 if(!p_BindIoCompletionCallback) {
458 win_skip("BindIoCompletionCallback not found in this DLL\n");
459 return;
462 sem = CreateSemaphore(NULL, 0, 1, NULL);
463 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
465 ret = GetTempPathA(MAX_PATH, temp_path);
466 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
467 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
469 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
470 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
472 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
473 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
474 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
476 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
477 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
478 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
480 ret = CloseHandle(hFile);
481 ok( ret, "CloseHandle: error %d\n", GetLastError());
482 ret = DeleteFileA(filename);
483 ok( ret, "DeleteFileA: error %d\n", GetLastError());
485 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
486 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
487 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
489 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
490 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
492 memset(&overlapped, 0, sizeof(overlapped));
493 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
494 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
496 ret = WaitForSingleObject(sem, 5000);
497 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
498 CloseHandle(sem);
500 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
501 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
502 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
503 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
504 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
505 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
507 ret = CloseHandle(hFile);
508 ok( ret, "CloseHandle: error %d\n", GetLastError());
509 ret = DeleteFileA(filename);
510 ok( ret, "DeleteFileA: error %d\n", GetLastError());
512 /* win2k3 requires the Flags parameter to be zero */
513 SetLastError(0xdeadbeef);
514 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
515 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
516 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
517 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
518 if (!retb)
519 ok(GetLastError() == ERROR_INVALID_PARAMETER,
520 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
521 else
522 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
523 ret = CloseHandle(hFile);
524 ok( ret, "CloseHandle: error %d\n", GetLastError());
525 ret = DeleteFileA(filename);
526 ok( ret, "DeleteFileA: error %d\n", GetLastError());
528 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
529 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
530 ok(GetLastError() == ERROR_INVALID_HANDLE ||
531 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
532 "Last error is %d\n", GetLastError());
535 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
537 int *pn = p;
538 ok(timedOut, "Timer callbacks should always time out\n");
539 ++*pn;
542 struct timer_queue_data1
544 int num_calls;
545 int max_calls;
546 HANDLE q, t;
549 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
551 struct timer_queue_data1 *d = p;
552 ok(timedOut, "Timer callbacks should always time out\n");
553 if (d->t && ++d->num_calls == d->max_calls)
555 BOOL ret;
556 SetLastError(0xdeadbeef);
557 /* Note, XP SP2 does *not* do any deadlock checking, so passing
558 INVALID_HANDLE_VALUE here will just hang. */
559 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
560 ok(!ret, "DeleteTimerQueueTimer\n");
561 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
565 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
567 struct timer_queue_data1 *d = p;
568 ok(timedOut, "Timer callbacks should always time out\n");
569 if (d->t && ++d->num_calls == d->max_calls)
571 /* Basically kill the timer since it won't have time to run
572 again. */
573 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
574 ok(ret, "ChangeTimerQueueTimer\n");
578 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
580 struct timer_queue_data1 *d = p;
581 ok(timedOut, "Timer callbacks should always time out\n");
582 if (d->t)
584 /* This tests whether a timer gets flagged for deletion before
585 or after the callback runs. If we start this timer with a
586 period of zero (run once), then ChangeTimerQueueTimer will
587 fail if the timer is already flagged. Hence we really run
588 only once. Otherwise we will run multiple times. */
589 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
590 ok(ret, "ChangeTimerQueueTimer\n");
591 ++d->num_calls;
595 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
597 DWORD_PTR delay = (DWORD_PTR) p;
598 ok(timedOut, "Timer callbacks should always time out\n");
599 if (delay)
600 Sleep(delay);
603 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
605 struct timer_queue_data1 *d = p;
606 ok(timedOut, "Timer callbacks should always time out\n");
607 /* This tests an original implementation bug where a deleted timer may get
608 to run, but it is tricky to set up. */
609 if (d->q && d->num_calls++ == 0)
611 /* First run: delete ourselves, then insert and remove a timer
612 that goes in front of us in the sorted timeout list. Once
613 removed, we will still timeout at the faster timer's due time,
614 but this should be a no-op if we are bug-free. There should
615 not be a second run. We can test the value of num_calls later. */
616 BOOL ret;
617 HANDLE t;
619 /* The delete will pend while we are in this callback. */
620 SetLastError(0xdeadbeef);
621 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
622 ok(!ret, "DeleteTimerQueueTimer\n");
623 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
625 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
626 ok(ret, "CreateTimerQueueTimer\n");
627 ok(t != NULL, "CreateTimerQueueTimer\n");
629 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
630 ok(ret, "DeleteTimerQueueTimer\n");
632 /* Now we stay alive by hanging around in the callback. */
633 Sleep(500);
637 static void test_timer_queue(void)
639 HANDLE q, t1, t2, t3, t4, t5;
640 int n1, n2, n3, n4, n5;
641 struct timer_queue_data1 d1, d2, d3, d4;
642 HANDLE e, et1, et2;
643 BOOL ret;
645 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
646 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
648 win_skip("TimerQueue API not present\n");
649 return;
652 /* Test asynchronous deletion of the queue. */
653 q = pCreateTimerQueue();
654 ok(q != NULL, "CreateTimerQueue\n");
656 SetLastError(0xdeadbeef);
657 ret = pDeleteTimerQueueEx(q, NULL);
658 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
659 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
660 GetLastError());
662 /* Test synchronous deletion of the queue and running timers. */
663 q = pCreateTimerQueue();
664 ok(q != NULL, "CreateTimerQueue\n");
666 /* Called once. */
667 t1 = NULL;
668 n1 = 0;
669 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
670 0, 0);
671 ok(ret, "CreateTimerQueueTimer\n");
672 ok(t1 != NULL, "CreateTimerQueueTimer\n");
674 /* A slow one. */
675 t2 = NULL;
676 n2 = 0;
677 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
678 100, 0);
679 ok(ret, "CreateTimerQueueTimer\n");
680 ok(t2 != NULL, "CreateTimerQueueTimer\n");
682 /* A fast one. */
683 t3 = NULL;
684 n3 = 0;
685 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
686 10, 0);
687 ok(ret, "CreateTimerQueueTimer\n");
688 ok(t3 != NULL, "CreateTimerQueueTimer\n");
690 /* Start really late (it won't start). */
691 t4 = NULL;
692 n4 = 0;
693 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
694 10, 0);
695 ok(ret, "CreateTimerQueueTimer\n");
696 ok(t4 != NULL, "CreateTimerQueueTimer\n");
698 /* Start soon, but delay so long it won't run again. */
699 t5 = NULL;
700 n5 = 0;
701 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
702 10000, 0);
703 ok(ret, "CreateTimerQueueTimer\n");
704 ok(t5 != NULL, "CreateTimerQueueTimer\n");
706 /* Give them a chance to do some work. */
707 Sleep(500);
709 /* Test deleting a once-only timer. */
710 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
711 ok(ret, "DeleteTimerQueueTimer\n");
713 /* A periodic timer. */
714 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
715 ok(ret, "DeleteTimerQueueTimer\n");
717 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
718 ok(ret, "DeleteTimerQueueEx\n");
719 ok(n1 == 1, "Timer callback 1\n");
720 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
721 ok(n4 == 0, "Timer callback 4\n");
722 ok(n5 == 1, "Timer callback 5\n");
724 /* Test synchronous deletion of the timer/queue with event trigger. */
725 e = CreateEvent(NULL, TRUE, FALSE, NULL);
726 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
727 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
728 if (!e || !et1 || !et2)
730 skip("Failed to create timer queue descruction event\n");
731 return;
734 q = pCreateTimerQueue();
735 ok(q != NULL, "CreateTimerQueue\n");
737 /* Run once and finish quickly (should be done when we delete it). */
738 t1 = NULL;
739 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
740 ok(ret, "CreateTimerQueueTimer\n");
741 ok(t1 != NULL, "CreateTimerQueueTimer\n");
743 /* Run once and finish slowly (shouldn't be done when we delete it). */
744 t2 = NULL;
745 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
746 0, 0);
747 ok(ret, "CreateTimerQueueTimer\n");
748 ok(t2 != NULL, "CreateTimerQueueTimer\n");
750 /* Run once and finish quickly (should be done when we delete it). */
751 t3 = NULL;
752 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
753 ok(ret, "CreateTimerQueueTimer\n");
754 ok(t3 != NULL, "CreateTimerQueueTimer\n");
756 /* Run once and finish slowly (shouldn't be done when we delete it). */
757 t4 = NULL;
758 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
759 0, 0);
760 ok(ret, "CreateTimerQueueTimer\n");
761 ok(t4 != NULL, "CreateTimerQueueTimer\n");
763 /* Give them a chance to start. */
764 Sleep(400);
766 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
767 even if the timer is finished. */
768 SetLastError(0xdeadbeef);
769 ret = pDeleteTimerQueueTimer(q, t1, NULL);
770 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
771 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
772 GetLastError());
774 SetLastError(0xdeadbeef);
775 ret = pDeleteTimerQueueTimer(q, t2, NULL);
776 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
777 ok(GetLastError() == ERROR_IO_PENDING,
778 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
779 GetLastError());
781 SetLastError(0xdeadbeef);
782 ret = pDeleteTimerQueueTimer(q, t3, et1);
783 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
784 ok(GetLastError() == 0xdeadbeef,
785 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
786 GetLastError());
787 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
788 "Timer destruction event not triggered\n");
790 SetLastError(0xdeadbeef);
791 ret = pDeleteTimerQueueTimer(q, t4, et2);
792 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
793 ok(GetLastError() == ERROR_IO_PENDING,
794 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
795 GetLastError());
796 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
797 "Timer destruction event not triggered\n");
799 SetLastError(0xdeadbeef);
800 ret = pDeleteTimerQueueEx(q, e);
801 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
802 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
803 GetLastError());
804 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
805 "Queue destruction event not triggered\n");
806 CloseHandle(e);
808 /* Test deleting/changing a timer in execution. */
809 q = pCreateTimerQueue();
810 ok(q != NULL, "CreateTimerQueue\n");
812 /* Test changing a once-only timer before it fires (this is allowed,
813 whereas after it fires you cannot). */
814 n1 = 0;
815 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
816 0, 0);
817 ok(ret, "CreateTimerQueueTimer\n");
818 ok(t1 != NULL, "CreateTimerQueueTimer\n");
819 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
820 ok(ret, "ChangeTimerQueueTimer\n");
822 d2.t = t2 = NULL;
823 d2.num_calls = 0;
824 d2.max_calls = 3;
825 d2.q = q;
826 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
827 10, 0);
828 d2.t = t2;
829 ok(ret, "CreateTimerQueueTimer\n");
830 ok(t2 != NULL, "CreateTimerQueueTimer\n");
832 d3.t = t3 = NULL;
833 d3.num_calls = 0;
834 d3.max_calls = 4;
835 d3.q = q;
836 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
837 10, 0);
838 d3.t = t3;
839 ok(ret, "CreateTimerQueueTimer\n");
840 ok(t3 != NULL, "CreateTimerQueueTimer\n");
842 d4.t = t4 = NULL;
843 d4.num_calls = 0;
844 d4.q = q;
845 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
846 0, 0);
847 d4.t = t4;
848 ok(ret, "CreateTimerQueueTimer\n");
849 ok(t4 != NULL, "CreateTimerQueueTimer\n");
851 Sleep(500);
853 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
854 ok(ret, "DeleteTimerQueueEx\n");
855 ok(n1 == 1, "ChangeTimerQueueTimer\n");
856 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
857 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
858 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
860 /* Test an obscure bug that was in the original implementation. */
861 q = pCreateTimerQueue();
862 ok(q != NULL, "CreateTimerQueue\n");
864 /* All the work is done in the callback. */
865 d1.t = t1 = NULL;
866 d1.num_calls = 0;
867 d1.q = q;
868 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
869 100, WT_EXECUTELONGFUNCTION);
870 d1.t = t1;
871 ok(ret, "CreateTimerQueueTimer\n");
872 ok(t1 != NULL, "CreateTimerQueueTimer\n");
874 Sleep(750);
876 SetLastError(0xdeadbeef);
877 ret = pDeleteTimerQueueEx(q, NULL);
878 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
879 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
880 GetLastError());
881 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
883 /* Test functions on the default timer queue. */
884 t1 = NULL;
885 n1 = 0;
886 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
887 1000, 0);
888 ok(ret, "CreateTimerQueueTimer, default queue\n");
889 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
891 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
892 ok(ret, "ChangeTimerQueueTimer, default queue\n");
894 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
895 ok(ret, "DeleteTimerQueueTimer, default queue\n");
897 /* Try mixing default and non-default queues. Apparently this works. */
898 q = pCreateTimerQueue();
899 ok(q != NULL, "CreateTimerQueue\n");
901 t1 = NULL;
902 n1 = 0;
903 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
904 1000, 0);
905 ok(ret, "CreateTimerQueueTimer\n");
906 ok(t1 != NULL, "CreateTimerQueueTimer\n");
908 t2 = NULL;
909 n2 = 0;
910 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
911 1000, 0);
912 ok(ret, "CreateTimerQueueTimer\n");
913 ok(t2 != NULL, "CreateTimerQueueTimer\n");
915 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
916 ok(ret, "ChangeTimerQueueTimer\n");
918 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
919 ok(ret, "ChangeTimerQueueTimer\n");
921 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
922 ok(ret, "DeleteTimerQueueTimer\n");
924 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
925 ok(ret, "DeleteTimerQueueTimer\n");
927 /* Try to delete the default queue? In any case: not allowed. */
928 SetLastError(0xdeadbeef);
929 ret = pDeleteTimerQueueEx(NULL, NULL);
930 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
931 ok(GetLastError() == ERROR_INVALID_HANDLE,
932 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
933 GetLastError());
935 SetLastError(0xdeadbeef);
936 ret = pDeleteTimerQueueEx(q, NULL);
937 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
938 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
939 GetLastError());
942 START_TEST(sync)
944 HMODULE hdll = GetModuleHandle("kernel32");
945 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
946 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
947 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
948 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
949 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
950 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
951 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
953 test_signalandwait();
954 test_mutex();
955 test_slist();
956 test_event();
957 test_semaphore();
958 test_waitable_timer();
959 test_iocp_callback();
960 test_timer_queue();