push decde5eed3d79f9d889b4d757f73e86ce6ff9241
[wine/hacks.git] / dlls / kernel32 / tests / sync.c
blobc7a949c4ee4fd5d77378c544ef251ff6d0bae79f
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 ok(!ret, "DeleteTimerQueueTimer\n");
570 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
574 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
576 struct timer_queue_data1 *d = p;
577 ok(timedOut, "Timer callbacks should always time out\n");
578 if (d->t && ++d->num_calls == d->max_calls)
580 /* Basically kill the timer since it won't have time to run
581 again. */
582 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
583 ok(ret, "ChangeTimerQueueTimer\n");
587 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
589 struct timer_queue_data1 *d = p;
590 ok(timedOut, "Timer callbacks should always time out\n");
591 if (d->t)
593 /* This tests whether a timer gets flagged for deletion before
594 or after the callback runs. If we start this timer with a
595 period of zero (run once), then ChangeTimerQueueTimer will
596 fail if the timer is already flagged. Hence we really run
597 only once. Otherwise we will run multiple times. */
598 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
599 ok(ret, "ChangeTimerQueueTimer\n");
600 ++d->num_calls;
604 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
606 DWORD delay = (DWORD) p;
607 ok(timedOut, "Timer callbacks should always time out\n");
608 if (delay)
609 Sleep(delay);
612 static void test_timer_queue(void)
614 HANDLE q, t1, t2, t3, t4, t5;
615 int n1, n2, n3, n4, n5;
616 struct timer_queue_data1 d2, d3, d4;
617 HANDLE e, et1, et2;
618 BOOL ret;
620 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
621 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
623 skip("TimerQueue API not present\n");
624 return;
627 /* Test asynchronous deletion of the queue. */
628 q = pCreateTimerQueue();
629 ok(q != NULL, "CreateTimerQueue\n");
631 SetLastError(0xdeadbeef);
632 ret = pDeleteTimerQueueEx(q, NULL);
633 ok(!ret, "DeleteTimerQueueEx\n");
634 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
636 /* Test synchronous deletion of the queue and running timers. */
637 q = pCreateTimerQueue();
638 ok(q != NULL, "CreateTimerQueue\n");
640 /* Called once. */
641 t1 = NULL;
642 n1 = 0;
643 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
644 0, 0);
645 ok(ret, "CreateTimerQueueTimer\n");
646 ok(t1 != NULL, "CreateTimerQueueTimer\n");
648 /* A slow one. */
649 t2 = NULL;
650 n2 = 0;
651 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
652 100, 0);
653 ok(ret, "CreateTimerQueueTimer\n");
654 ok(t2 != NULL, "CreateTimerQueueTimer\n");
656 /* A fast one. */
657 t3 = NULL;
658 n3 = 0;
659 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
660 10, 0);
661 ok(ret, "CreateTimerQueueTimer\n");
662 ok(t3 != NULL, "CreateTimerQueueTimer\n");
664 /* Start really late (it won't start). */
665 t4 = NULL;
666 n4 = 0;
667 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
668 10, 0);
669 ok(ret, "CreateTimerQueueTimer\n");
670 ok(t4 != NULL, "CreateTimerQueueTimer\n");
672 /* Start soon, but delay so long it won't run again. */
673 t5 = NULL;
674 n5 = 0;
675 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
676 10000, 0);
677 ok(ret, "CreateTimerQueueTimer\n");
678 ok(t5 != NULL, "CreateTimerQueueTimer\n");
680 /* Give them a chance to do some work. */
681 Sleep(500);
683 /* Test deleting a once-only timer. */
684 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
685 ok(ret, "DeleteTimerQueueTimer\n");
687 /* A periodic timer. */
688 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
689 ok(ret, "DeleteTimerQueueTimer\n");
691 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
692 ok(ret, "DeleteTimerQueueEx\n");
693 ok(n1 == 1, "Timer callback 1\n");
694 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
695 ok(n4 == 0, "Timer callback 4\n");
696 ok(n5 == 1, "Timer callback 5\n");
698 /* Test synchronous deletion of the timer/queue with event trigger. */
699 e = CreateEvent(NULL, TRUE, FALSE, NULL);
700 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
701 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
702 if (!e || !et1 || !et2)
704 skip("Failed to create timer queue descruction event\n");
705 return;
708 q = pCreateTimerQueue();
709 ok(q != NULL, "CreateTimerQueue\n");
711 /* Run once and finish quickly (should be done when we delete it). */
712 t1 = NULL;
713 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, (PVOID) 0, 0,
714 0, 0);
715 ok(ret, "CreateTimerQueueTimer\n");
716 ok(t1 != NULL, "CreateTimerQueueTimer\n");
718 /* Run once and finish slowly (shouldn't be done when we delete it). */
719 t2 = NULL;
720 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
721 0, 0);
722 ok(ret, "CreateTimerQueueTimer\n");
723 ok(t2 != NULL, "CreateTimerQueueTimer\n");
725 /* Run once and finish quickly (should be done when we delete it). */
726 t3 = NULL;
727 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, (PVOID) 0, 0,
728 0, 0);
729 ok(ret, "CreateTimerQueueTimer\n");
730 ok(t3 != NULL, "CreateTimerQueueTimer\n");
732 /* Run once and finish slowly (shouldn't be done when we delete it). */
733 t4 = NULL;
734 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
735 0, 0);
736 ok(ret, "CreateTimerQueueTimer\n");
737 ok(t4 != NULL, "CreateTimerQueueTimer\n");
739 /* Give them a chance to start. */
740 Sleep(400);
742 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
743 even if the timer is finished. */
744 SetLastError(0xdeadbeef);
745 ret = pDeleteTimerQueueTimer(q, t1, NULL);
746 ok(!ret, "DeleteTimerQueueTimer\n");
747 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
749 SetLastError(0xdeadbeef);
750 ret = pDeleteTimerQueueTimer(q, t2, NULL);
751 ok(!ret, "DeleteTimerQueueTimer\n");
752 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
754 SetLastError(0xdeadbeef);
755 ret = pDeleteTimerQueueTimer(q, t3, et1);
756 ok(ret, "DeleteTimerQueueTimer\n");
757 ok(GetLastError() == 0xdeadbeef, "DeleteTimerQueueTimer\n");
758 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
759 "Timer destruction event not triggered\n");
761 SetLastError(0xdeadbeef);
762 ret = pDeleteTimerQueueTimer(q, t4, et2);
763 ok(!ret, "DeleteTimerQueueTimer\n");
764 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
765 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
766 "Timer destruction event not triggered\n");
768 SetLastError(0xdeadbeef);
769 ret = pDeleteTimerQueueEx(q, e);
770 ok(!ret, "DeleteTimerQueueEx\n");
771 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n");
772 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
773 "Queue destruction event not triggered\n");
774 CloseHandle(e);
776 /* Test deleting/changing a timer in execution. */
777 q = pCreateTimerQueue();
778 ok(q != NULL, "CreateTimerQueue\n");
780 /* Test changing a once-only timer before it fires (this is allowed,
781 whereas after it fires you cannot). */
782 n1 = 0;
783 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
784 0, 0);
785 ok(ret, "CreateTimerQueueTimer\n");
786 ok(t1 != NULL, "CreateTimerQueueTimer\n");
787 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
788 ok(ret, "ChangeTimerQueueTimer\n");
790 d2.t = t2 = NULL;
791 d2.num_calls = 0;
792 d2.max_calls = 3;
793 d2.q = q;
794 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
795 10, 0);
796 d2.t = t2;
797 ok(ret, "CreateTimerQueueTimer\n");
798 ok(t2 != NULL, "CreateTimerQueueTimer\n");
800 d3.t = t3 = NULL;
801 d3.num_calls = 0;
802 d3.max_calls = 4;
803 d3.q = q;
804 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
805 10, 0);
806 d3.t = t3;
807 ok(ret, "CreateTimerQueueTimer\n");
808 ok(t3 != NULL, "CreateTimerQueueTimer\n");
810 d4.t = t4 = NULL;
811 d4.num_calls = 0;
812 d4.q = q;
813 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
814 0, 0);
815 d4.t = t4;
816 ok(ret, "CreateTimerQueueTimer\n");
817 ok(t4 != NULL, "CreateTimerQueueTimer\n");
819 Sleep(200);
821 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
822 ok(ret, "DeleteTimerQueueEx\n");
823 ok(n1 == 1, "ChangeTimerQueueTimer\n");
824 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
825 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
826 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
829 START_TEST(sync)
831 HMODULE hdll = GetModuleHandle("kernel32");
832 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
833 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
834 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
835 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
836 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
837 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
838 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
840 test_signalandwait();
841 test_mutex();
842 test_slist();
843 test_event();
844 test_semaphore();
845 test_waitable_timer();
846 test_iocp_callback();
847 test_timer_queue();