kernel32/tests: Add tests for Change/DeleteTimerQueueTimer.
[wine/testsucceed.git] / dlls / kernel32 / tests / sync.c
bloba8a1d933784187ff861f6e5e12e9bbf0988b33f3
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 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]);
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, "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];
448 DWORD ret;
449 BOOL retb;
450 static const char prefix[] = "pfx";
451 HANDLE hFile;
452 HMODULE hmod = GetModuleHandleA("kernel32.dll");
453 DWORD bytesWritten;
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");
460 return;
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");
499 CloseHandle(sem);
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);
529 if (!retb)
530 ok(GetLastError() == ERROR_INVALID_PARAMETER,
531 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
532 else
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)
546 int *pn = (int *) p;
547 ok(timedOut, "Timer callbacks should always time out\n");
548 ++*pn;
551 struct timer_queue_data1
553 int num_calls;
554 int max_calls;
555 HANDLE q, t;
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)
564 BOOL ret;
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 todo_wine
571 ok(!ret, "DeleteTimerQueueTimer\n");
572 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
577 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
579 struct timer_queue_data1 *d = p;
580 ok(timedOut, "Timer callbacks should always time out\n");
581 if (d->t && ++d->num_calls == d->max_calls)
583 /* Basically kill the timer since it won't have time to run
584 again. */
585 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
586 todo_wine
587 ok(ret, "ChangeTimerQueueTimer\n");
591 static void test_timer_queue(void)
593 HANDLE q, t1, t2, t3, t4, t5;
594 int n1, n2, n3, n4, n5;
595 struct timer_queue_data1 d2, d3;
596 HANDLE e;
597 BOOL ret;
599 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
600 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
602 skip("TimerQueue API not present\n");
603 return;
606 /* Test asynchronous deletion of the queue. */
607 q = pCreateTimerQueue();
608 todo_wine
609 ok(q != NULL, "CreateTimerQueue\n");
611 SetLastError(0xdeadbeef);
612 ret = pDeleteTimerQueueEx(q, NULL);
613 ok(!ret, "DeleteTimerQueueEx\n");
614 todo_wine
615 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
617 /* Test synchronous deletion of the queue and running timers. */
618 q = pCreateTimerQueue();
619 todo_wine
620 ok(q != NULL, "CreateTimerQueue\n");
622 /* Called once. */
623 t1 = NULL;
624 n1 = 0;
625 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
626 0, 0);
627 ok(ret, "CreateTimerQueueTimer\n");
629 /* A slow one. */
630 t2 = NULL;
631 n2 = 0;
632 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
633 100, 0);
634 ok(ret, "CreateTimerQueueTimer\n");
636 /* A fast one. */
637 t3 = NULL;
638 n3 = 0;
639 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
640 10, 0);
641 ok(ret, "CreateTimerQueueTimer\n");
643 /* Start really late (it won't start). */
644 t4 = NULL;
645 n4 = 0;
646 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
647 10, 0);
648 ok(ret, "CreateTimerQueueTimer\n");
650 /* Start soon, but delay so long it won't run again. */
651 t5 = NULL;
652 n5 = 0;
653 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
654 10000, 0);
655 ok(ret, "CreateTimerQueueTimer\n");
657 /* Give them a chance to do some work. */
658 Sleep(500);
660 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
661 todo_wine
663 ok(ret, "DeleteTimerQueueEx\n");
664 ok(n1 == 1, "Timer callback 1\n");
665 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
667 ok(n4 == 0, "Timer callback 4\n");
668 todo_wine
669 ok(n5 == 1, "Timer callback 5\n");
671 /* Test synchronous deletion of the queue with event trigger. */
672 e = CreateEvent(NULL, TRUE, FALSE, NULL);
673 if (!e)
675 skip("Failed to create timer queue descruction event\n");
676 return;
679 q = pCreateTimerQueue();
680 todo_wine
681 ok(q != NULL, "CreateTimerQueue\n");
683 SetLastError(0xdeadbeef);
684 ret = pDeleteTimerQueueEx(q, e);
685 ok(!ret, "DeleteTimerQueueEx\n");
686 todo_wine
688 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
689 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
690 "Timer destruction event not triggered\n");
692 CloseHandle(e);
694 /* Test deleting/changing a timer in execution. */
695 q = pCreateTimerQueue();
696 todo_wine
697 ok(q != NULL, "CreateTimerQueue\n");
699 d2.t = t2 = NULL;
700 d2.num_calls = 0;
701 d2.max_calls = 3;
702 d2.q = q;
703 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
704 10, 0);
705 d2.t = t2;
706 ok(ret, "CreateTimerQueueTimer\n");
708 d3.t = t3 = NULL;
709 d3.num_calls = 0;
710 d3.max_calls = 4;
711 d3.q = q;
712 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
713 10, 0);
714 d3.t = t3;
715 ok(ret, "CreateTimerQueueTimer\n");
717 Sleep(200);
719 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
720 todo_wine
722 ok(ret, "DeleteTimerQueueEx\n");
723 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
724 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
728 START_TEST(sync)
730 HMODULE hdll = GetModuleHandle("kernel32");
731 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
732 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
733 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
734 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
735 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
736 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
737 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
739 test_signalandwait();
740 test_mutex();
741 test_slist();
742 test_event();
743 test_semaphore();
744 test_waitable_timer();
745 test_iocp_callback();
746 test_timer_queue();