push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / kernel32 / tests / sync.c
blobade9b74d04afac4afd0de5a44c9c0e23a81db909
1 /*
2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <windef.h>
25 #define _WIN32_WINNT 0x500
26 #include <winbase.h>
28 #include "wine/test.h"
30 static 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 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, test_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 skip("some required slist entrypoints were not found, skipping tests\n");
224 return;
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);
235 item1.value = 1;
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);
241 item2.value = 2;
242 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
243 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
244 if (entry != NULL)
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);
252 item3.value = 3;
253 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
254 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
255 if (entry != NULL)
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");
265 if (entry != NULL)
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);
276 if (size == 0)
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;
290 ACL acl;
292 /* no sd */
293 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
294 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
295 CloseHandle(handle);
297 sa.nLength = sizeof(sa);
298 sa.lpSecurityDescriptor = &sd;
299 sa.bInheritHandle = FALSE;
301 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
303 /* blank sd */
304 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
305 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
306 CloseHandle(handle);
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());
312 CloseHandle(handle);
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());
319 CloseHandle(handle);
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");
400 return;
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 ||
431 GetLastError() == ERROR_INVALID_NAME, /* win98 */
432 "wrong error %u\n", GetLastError());
434 CloseHandle( handle );
437 static HANDLE sem = 0;
439 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
441 ReleaseSemaphore(sem, 1, NULL);
444 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
446 static void test_iocp_callback(void)
448 char temp_path[MAX_PATH];
449 char filename[MAX_PATH];
450 DWORD ret;
451 BOOL retb;
452 static const char prefix[] = "pfx";
453 HANDLE hFile;
454 HMODULE hmod = GetModuleHandleA("kernel32.dll");
455 DWORD bytesWritten;
456 const char *buffer = "12345678123456781234567812345678";
457 OVERLAPPED overlapped;
459 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
460 if(!p_BindIoCompletionCallback) {
461 skip("BindIoCompletionCallback not found in this DLL\n");
462 return;
465 sem = CreateSemaphore(NULL, 0, 1, NULL);
466 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
468 ret = GetTempPathA(MAX_PATH, temp_path);
469 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
470 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
472 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
473 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
475 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
476 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
477 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
479 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
480 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
481 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
483 ret = CloseHandle(hFile);
484 ok( ret, "CloseHandle: error %d\n", GetLastError());
485 ret = DeleteFileA(filename);
486 ok( ret, "DeleteFileA: error %d\n", GetLastError());
488 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
489 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
490 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
492 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
493 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
495 memset(&overlapped, 0, sizeof(overlapped));
496 retb = WriteFile(hFile, (const void *) buffer, 4, &bytesWritten, &overlapped);
497 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
499 ret = WaitForSingleObject(sem, 5000);
500 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
501 CloseHandle(sem);
503 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
504 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
505 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
506 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
507 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
508 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
510 ret = CloseHandle(hFile);
511 ok( ret, "CloseHandle: error %d\n", GetLastError());
512 ret = DeleteFileA(filename);
513 ok( ret, "DeleteFileA: error %d\n", GetLastError());
515 /* win2k3 requires the Flags parameter to be zero */
516 SetLastError(0xdeadbeef);
517 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
518 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
519 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
520 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
521 if (!retb)
522 ok(GetLastError() == ERROR_INVALID_PARAMETER,
523 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
524 else
525 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
526 ret = CloseHandle(hFile);
527 ok( ret, "CloseHandle: error %d\n", GetLastError());
528 ret = DeleteFileA(filename);
529 ok( ret, "DeleteFileA: error %d\n", GetLastError());
531 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
532 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
533 ok(GetLastError() == ERROR_INVALID_HANDLE ||
534 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
535 "Last error is %d\n", GetLastError());
538 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
540 int *pn = (int *) p;
541 ok(timedOut, "Timer callbacks should always time out\n");
542 ++*pn;
545 struct timer_queue_data1
547 int num_calls;
548 int max_calls;
549 HANDLE q, t;
552 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
554 struct timer_queue_data1 *d = p;
555 ok(timedOut, "Timer callbacks should always time out\n");
556 if (d->t && ++d->num_calls == d->max_calls)
558 BOOL ret;
559 SetLastError(0xdeadbeef);
560 /* Note, XP SP2 does *not* do any deadlock checking, so passing
561 INVALID_HANDLE_VALUE here will just hang. */
562 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
563 ok(!ret, "DeleteTimerQueueTimer\n");
564 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
568 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
570 struct timer_queue_data1 *d = p;
571 ok(timedOut, "Timer callbacks should always time out\n");
572 if (d->t && ++d->num_calls == d->max_calls)
574 /* Basically kill the timer since it won't have time to run
575 again. */
576 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
577 ok(ret, "ChangeTimerQueueTimer\n");
581 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
583 struct timer_queue_data1 *d = p;
584 ok(timedOut, "Timer callbacks should always time out\n");
585 if (d->t)
587 /* This tests whether a timer gets flagged for deletion before
588 or after the callback runs. If we start this timer with a
589 period of zero (run once), then ChangeTimerQueueTimer will
590 fail if the timer is already flagged. Hence we really run
591 only once. Otherwise we will run multiple times. */
592 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
593 ok(ret, "ChangeTimerQueueTimer\n");
594 ++d->num_calls;
598 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
600 DWORD delay = (DWORD) p;
601 ok(timedOut, "Timer callbacks should always time out\n");
602 if (delay)
603 Sleep(delay);
606 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
608 struct timer_queue_data1 *d = p;
609 ok(timedOut, "Timer callbacks should always time out\n");
610 /* This tests an original implementation bug where a deleted timer may get
611 to run, but it is tricky to set up. */
612 if (d->q && d->num_calls++ == 0)
614 /* First run: delete ourselves, then insert and remove a timer
615 that goes in front of us in the sorted timeout list. Once
616 removed, we will still timeout at the faster timer's due time,
617 but this should be a no-op if we are bug-free. There should
618 not be a second run. We can test the value of num_calls later. */
619 BOOL ret;
620 HANDLE t;
622 /* The delete will pend while we are in this callback. */
623 SetLastError(0xdeadbeef);
624 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
625 ok(!ret, "DeleteTimerQueueTimer\n");
626 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
628 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
629 ok(ret, "CreateTimerQueueTimer\n");
630 ok(t != NULL, "CreateTimerQueueTimer\n");
632 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
633 ok(ret, "DeleteTimerQueueTimer\n");
635 /* Now we stay alive by hanging around in the callback. */
636 Sleep(500);
640 static void test_timer_queue(void)
642 HANDLE q, t1, t2, t3, t4, t5;
643 int n1, n2, n3, n4, n5;
644 struct timer_queue_data1 d1, d2, d3, d4;
645 HANDLE e, et1, et2;
646 BOOL ret;
648 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
649 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
651 skip("TimerQueue API not present\n");
652 return;
655 /* Test asynchronous deletion of the queue. */
656 q = pCreateTimerQueue();
657 ok(q != NULL, "CreateTimerQueue\n");
659 SetLastError(0xdeadbeef);
660 ret = pDeleteTimerQueueEx(q, NULL);
661 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
662 ok(GetLastError() == ERROR_IO_PENDING,
663 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
664 GetLastError());
666 /* Test synchronous deletion of the queue and running timers. */
667 q = pCreateTimerQueue();
668 ok(q != NULL, "CreateTimerQueue\n");
670 /* Called once. */
671 t1 = NULL;
672 n1 = 0;
673 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
674 0, 0);
675 ok(ret, "CreateTimerQueueTimer\n");
676 ok(t1 != NULL, "CreateTimerQueueTimer\n");
678 /* A slow one. */
679 t2 = NULL;
680 n2 = 0;
681 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
682 100, 0);
683 ok(ret, "CreateTimerQueueTimer\n");
684 ok(t2 != NULL, "CreateTimerQueueTimer\n");
686 /* A fast one. */
687 t3 = NULL;
688 n3 = 0;
689 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
690 10, 0);
691 ok(ret, "CreateTimerQueueTimer\n");
692 ok(t3 != NULL, "CreateTimerQueueTimer\n");
694 /* Start really late (it won't start). */
695 t4 = NULL;
696 n4 = 0;
697 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
698 10, 0);
699 ok(ret, "CreateTimerQueueTimer\n");
700 ok(t4 != NULL, "CreateTimerQueueTimer\n");
702 /* Start soon, but delay so long it won't run again. */
703 t5 = NULL;
704 n5 = 0;
705 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
706 10000, 0);
707 ok(ret, "CreateTimerQueueTimer\n");
708 ok(t5 != NULL, "CreateTimerQueueTimer\n");
710 /* Give them a chance to do some work. */
711 Sleep(500);
713 /* Test deleting a once-only timer. */
714 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
715 ok(ret, "DeleteTimerQueueTimer\n");
717 /* A periodic timer. */
718 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
719 ok(ret, "DeleteTimerQueueTimer\n");
721 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
722 ok(ret, "DeleteTimerQueueEx\n");
723 ok(n1 == 1, "Timer callback 1\n");
724 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
725 ok(n4 == 0, "Timer callback 4\n");
726 ok(n5 == 1, "Timer callback 5\n");
728 /* Test synchronous deletion of the timer/queue with event trigger. */
729 e = CreateEvent(NULL, TRUE, FALSE, NULL);
730 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
731 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
732 if (!e || !et1 || !et2)
734 skip("Failed to create timer queue descruction event\n");
735 return;
738 q = pCreateTimerQueue();
739 ok(q != NULL, "CreateTimerQueue\n");
741 /* Run once and finish quickly (should be done when we delete it). */
742 t1 = NULL;
743 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
744 ok(ret, "CreateTimerQueueTimer\n");
745 ok(t1 != NULL, "CreateTimerQueueTimer\n");
747 /* Run once and finish slowly (shouldn't be done when we delete it). */
748 t2 = NULL;
749 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
750 0, 0);
751 ok(ret, "CreateTimerQueueTimer\n");
752 ok(t2 != NULL, "CreateTimerQueueTimer\n");
754 /* Run once and finish quickly (should be done when we delete it). */
755 t3 = NULL;
756 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
757 ok(ret, "CreateTimerQueueTimer\n");
758 ok(t3 != NULL, "CreateTimerQueueTimer\n");
760 /* Run once and finish slowly (shouldn't be done when we delete it). */
761 t4 = NULL;
762 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
763 0, 0);
764 ok(ret, "CreateTimerQueueTimer\n");
765 ok(t4 != NULL, "CreateTimerQueueTimer\n");
767 /* Give them a chance to start. */
768 Sleep(400);
770 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
771 even if the timer is finished. */
772 SetLastError(0xdeadbeef);
773 ret = pDeleteTimerQueueTimer(q, t1, NULL);
774 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
775 ok(GetLastError() == ERROR_IO_PENDING,
776 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
777 GetLastError());
779 SetLastError(0xdeadbeef);
780 ret = pDeleteTimerQueueTimer(q, t2, NULL);
781 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
782 ok(GetLastError() == ERROR_IO_PENDING,
783 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
784 GetLastError());
786 SetLastError(0xdeadbeef);
787 ret = pDeleteTimerQueueTimer(q, t3, et1);
788 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
789 ok(GetLastError() == 0xdeadbeef,
790 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
791 GetLastError());
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 call was expected to fail\n");
798 ok(GetLastError() == ERROR_IO_PENDING,
799 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
800 GetLastError());
801 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
802 "Timer destruction event not triggered\n");
804 SetLastError(0xdeadbeef);
805 ret = pDeleteTimerQueueEx(q, e);
806 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
807 ok(GetLastError() == ERROR_IO_PENDING,
808 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
809 GetLastError());
810 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
811 "Queue destruction event not triggered\n");
812 CloseHandle(e);
814 /* Test deleting/changing a timer in execution. */
815 q = pCreateTimerQueue();
816 ok(q != NULL, "CreateTimerQueue\n");
818 /* Test changing a once-only timer before it fires (this is allowed,
819 whereas after it fires you cannot). */
820 n1 = 0;
821 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
822 0, 0);
823 ok(ret, "CreateTimerQueueTimer\n");
824 ok(t1 != NULL, "CreateTimerQueueTimer\n");
825 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
826 ok(ret, "ChangeTimerQueueTimer\n");
828 d2.t = t2 = NULL;
829 d2.num_calls = 0;
830 d2.max_calls = 3;
831 d2.q = q;
832 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
833 10, 0);
834 d2.t = t2;
835 ok(ret, "CreateTimerQueueTimer\n");
836 ok(t2 != NULL, "CreateTimerQueueTimer\n");
838 d3.t = t3 = NULL;
839 d3.num_calls = 0;
840 d3.max_calls = 4;
841 d3.q = q;
842 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
843 10, 0);
844 d3.t = t3;
845 ok(ret, "CreateTimerQueueTimer\n");
846 ok(t3 != NULL, "CreateTimerQueueTimer\n");
848 d4.t = t4 = NULL;
849 d4.num_calls = 0;
850 d4.q = q;
851 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
852 0, 0);
853 d4.t = t4;
854 ok(ret, "CreateTimerQueueTimer\n");
855 ok(t4 != NULL, "CreateTimerQueueTimer\n");
857 Sleep(200);
859 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
860 ok(ret, "DeleteTimerQueueEx\n");
861 ok(n1 == 1, "ChangeTimerQueueTimer\n");
862 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
863 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
864 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
866 /* Test an obscure bug that was in the original implementation. */
867 q = pCreateTimerQueue();
868 ok(q != NULL, "CreateTimerQueue\n");
870 /* All the work is done in the callback. */
871 d1.t = t1 = NULL;
872 d1.num_calls = 0;
873 d1.q = q;
874 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
875 100, WT_EXECUTELONGFUNCTION);
876 d1.t = t1;
877 ok(ret, "CreateTimerQueueTimer\n");
878 ok(t1 != NULL, "CreateTimerQueueTimer\n");
880 Sleep(750);
882 SetLastError(0xdeadbeef);
883 ret = pDeleteTimerQueueEx(q, NULL);
884 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
885 ok(GetLastError() == ERROR_IO_PENDING,
886 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
887 GetLastError());
888 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
890 /* Test functions on the default timer queue. */
891 t1 = NULL;
892 n1 = 0;
893 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
894 1000, 0);
895 ok(ret, "CreateTimerQueueTimer, default queue\n");
896 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
898 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
899 ok(ret, "ChangeTimerQueueTimer, default queue\n");
901 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
902 ok(ret, "DeleteTimerQueueTimer, default queue\n");
904 /* Try mixing default and non-default queues. Apparently this works. */
905 q = pCreateTimerQueue();
906 ok(q != NULL, "CreateTimerQueue\n");
908 t1 = NULL;
909 n1 = 0;
910 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
911 1000, 0);
912 ok(ret, "CreateTimerQueueTimer\n");
913 ok(t1 != NULL, "CreateTimerQueueTimer\n");
915 t2 = NULL;
916 n2 = 0;
917 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
918 1000, 0);
919 ok(ret, "CreateTimerQueueTimer\n");
920 ok(t2 != NULL, "CreateTimerQueueTimer\n");
922 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
923 ok(ret, "ChangeTimerQueueTimer\n");
925 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
926 ok(ret, "ChangeTimerQueueTimer\n");
928 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
929 ok(ret, "DeleteTimerQueueTimer\n");
931 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
932 ok(ret, "DeleteTimerQueueTimer\n");
934 /* Try to delete the default queue? In any case: not allowed. */
935 SetLastError(0xdeadbeef);
936 ret = pDeleteTimerQueueEx(NULL, NULL);
937 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
938 ok(GetLastError() == ERROR_INVALID_HANDLE,
939 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
940 GetLastError());
942 SetLastError(0xdeadbeef);
943 ret = pDeleteTimerQueueEx(q, NULL);
944 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
945 ok(GetLastError() == ERROR_IO_PENDING,
946 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
947 GetLastError());
950 START_TEST(sync)
952 HMODULE hdll = GetModuleHandle("kernel32");
953 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
954 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
955 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
956 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
957 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
958 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
959 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
961 test_signalandwait();
962 test_mutex();
963 test_slist();
964 test_event();
965 test_semaphore();
966 test_waitable_timer();
967 test_iocp_callback();
968 test_timer_queue();