kernel32/tests: Improve some traces for the CreateTimerQueueTimer() tests.
[wine/multimedia.git] / dlls / kernel32 / tests / sync.c
blob5cf5269cfe46e76fc9cf861b0079c400d26f8e84
1 /*
2 * Synchronization tests
4 * Copyright 2005 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define _WIN32_WINNT 0x500
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windef.h>
26 #include <winbase.h>
28 #include "wine/test.h"
30 static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
31 static HANDLE (WINAPI *pCreateTimerQueue)(void);
32 static BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
33 PVOID, DWORD, DWORD, ULONG);
34 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
35 static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
36 static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
37 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
38 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE);
39 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL);
41 static void test_signalandwait(void)
43 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
44 HMODULE kernel32;
45 DWORD r;
46 HANDLE event[2], semaphore[2], file;
48 kernel32 = GetModuleHandle("kernel32");
49 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
51 if (!pSignalObjectAndWait)
52 return;
54 /* invalid parameters */
55 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
56 if (r == ERROR_INVALID_FUNCTION)
58 win_skip("SignalObjectAndWait is not implemented\n");
59 return; /* Win98/ME */
61 ok( r == WAIT_FAILED, "should fail\n");
63 event[0] = CreateEvent(NULL, 0, 0, NULL);
64 event[1] = CreateEvent(NULL, 1, 1, NULL);
66 ok( event[0] && event[1], "failed to create event flags\n");
68 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
69 ok( r == WAIT_FAILED, "should fail\n");
71 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
72 ok( r == WAIT_FAILED, "should fail\n");
75 /* valid parameters */
76 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
77 ok( r == WAIT_OBJECT_0, "should succeed\n");
79 /* event[0] is now signalled */
80 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
81 ok( r == WAIT_OBJECT_0, "should succeed\n");
83 /* event[0] is not signalled */
84 r = WaitForSingleObject(event[0], 0);
85 ok( r == WAIT_TIMEOUT, "event was signalled\n");
87 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
88 ok( r == WAIT_OBJECT_0, "should succeed\n");
90 /* clear event[1] and check for a timeout */
91 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
92 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
93 ok( r == WAIT_TIMEOUT, "should timeout\n");
95 CloseHandle(event[0]);
96 CloseHandle(event[1]);
98 /* semaphores */
99 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
100 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
101 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
103 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
104 ok( r == WAIT_OBJECT_0, "should succeed\n");
106 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
107 ok( r == WAIT_FAILED, "should fail\n");
109 r = ReleaseSemaphore(semaphore[0],1,NULL);
110 ok( r == FALSE, "should fail\n");
112 r = ReleaseSemaphore(semaphore[1],1,NULL);
113 ok( r == TRUE, "should succeed\n");
115 CloseHandle(semaphore[0]);
116 CloseHandle(semaphore[1]);
118 /* try a registry key */
119 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
120 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
121 r = pSignalObjectAndWait(file, file, 0, FALSE);
122 ok( r == WAIT_FAILED, "should fail\n");
123 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
124 CloseHandle(file);
127 static void test_mutex(void)
129 DWORD wait_ret;
130 BOOL ret;
131 HANDLE hCreated;
132 HANDLE hOpened;
133 int i;
134 DWORD failed = 0;
136 SetLastError(0xdeadbeef);
137 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
138 ok(hOpened == NULL, "OpenMutex succeeded\n");
139 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
141 SetLastError(0xdeadbeef);
142 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
143 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
145 SetLastError(0xdeadbeef);
146 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
147 todo_wine
148 ok(hOpened == NULL, "OpenMutex succeeded\n");
149 todo_wine
150 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
152 SetLastError(0xdeadbeef);
153 hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
154 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
155 wait_ret = WaitForSingleObject(hOpened, INFINITE);
156 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
157 CloseHandle(hOpened);
159 for(i=0; i < 31; i++)
161 wait_ret = WaitForSingleObject(hCreated, INFINITE);
162 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
165 SetLastError(0xdeadbeef);
166 hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
167 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
168 wait_ret = WaitForSingleObject(hOpened, INFINITE);
169 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
170 CloseHandle(hOpened);
172 for (i = 0; i < 32; i++)
174 SetLastError(0xdeadbeef);
175 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
176 if(hOpened != NULL)
178 SetLastError(0xdeadbeef);
179 ret = ReleaseMutex(hOpened);
180 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
181 CloseHandle(hOpened);
183 else
185 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
186 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
187 else
188 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
189 ReleaseMutex(hCreated);
190 failed |=0x1 << i;
194 todo_wine
195 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
197 SetLastError(0xdeadbeef);
198 ret = ReleaseMutex(hCreated);
199 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
200 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
202 /* test case sensitivity */
204 SetLastError(0xdeadbeef);
205 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
206 ok(!hOpened, "OpenMutex succeeded\n");
207 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
209 SetLastError(0xdeadbeef);
210 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
211 ok(!hOpened, "OpenMutex succeeded\n");
212 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
214 SetLastError(0xdeadbeef);
215 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
216 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
217 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
218 CloseHandle(hOpened);
220 SetLastError(0xdeadbeef);
221 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
222 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
223 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
224 CloseHandle(hOpened);
226 CloseHandle(hCreated);
229 static void test_slist(void)
231 struct item
233 SLIST_ENTRY entry;
234 int value;
235 } item1, item2, item3, *pitem;
237 SLIST_HEADER slist_header;
238 PSLIST_ENTRY entry;
239 USHORT size;
241 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
242 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
243 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
244 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
245 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
246 HMODULE kernel32;
248 kernel32 = GetModuleHandle("KERNEL32.DLL");
249 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
250 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
251 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
252 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
253 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
254 if (pInitializeSListHead == NULL ||
255 pQueryDepthSList == NULL ||
256 pInterlockedFlushSList == NULL ||
257 pInterlockedPopEntrySList == NULL ||
258 pInterlockedPushEntrySList == NULL)
260 win_skip("some required slist entrypoints were not found, skipping tests\n");
261 return;
264 memset(&slist_header, 0xFF, sizeof(slist_header));
265 pInitializeSListHead(&slist_header);
266 size = pQueryDepthSList(&slist_header);
267 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
269 item1.value = 1;
270 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
271 "previous entry in empty slist wasn't NULL\n");
272 size = pQueryDepthSList(&slist_header);
273 ok(size == 1, "slist with 1 item has size %d\n", size);
275 item2.value = 2;
276 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
277 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
278 if (entry != NULL)
280 pitem = (struct item*) entry;
281 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
283 size = pQueryDepthSList(&slist_header);
284 ok(size == 2, "slist with 2 items has size %d\n", size);
286 item3.value = 3;
287 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
288 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
289 if (entry != NULL)
291 pitem = (struct item*) entry;
292 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
294 size = pQueryDepthSList(&slist_header);
295 ok(size == 3, "slist with 3 items has size %d\n", size);
297 entry = pInterlockedPopEntrySList(&slist_header);
298 ok(entry != NULL, "entry shouldn't be NULL\n");
299 if (entry != NULL)
301 pitem = (struct item*) entry;
302 ok(pitem->value == 3, "unexpected entry removed\n");
304 size = pQueryDepthSList(&slist_header);
305 ok(size == 2, "slist with 2 items has size %d\n", size);
307 entry = pInterlockedFlushSList(&slist_header);
308 size = pQueryDepthSList(&slist_header);
309 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
310 if (size == 0)
312 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
313 "popping empty slist didn't return NULL\n");
315 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
316 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
319 static void test_event(void)
321 HANDLE handle, handle2;
322 SECURITY_ATTRIBUTES sa;
323 SECURITY_DESCRIPTOR sd;
324 ACL acl;
325 DWORD ret;
326 BOOL val;
328 /* no sd */
329 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
330 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
331 CloseHandle(handle);
333 sa.nLength = sizeof(sa);
334 sa.lpSecurityDescriptor = &sd;
335 sa.bInheritHandle = FALSE;
337 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
339 /* blank sd */
340 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
341 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
342 CloseHandle(handle);
344 /* sd with NULL dacl */
345 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
346 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
347 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
348 CloseHandle(handle);
350 /* sd with empty dacl */
351 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
352 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
353 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
354 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
355 CloseHandle(handle);
357 /* test case sensitivity */
359 SetLastError(0xdeadbeef);
360 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
361 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
362 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
364 SetLastError(0xdeadbeef);
365 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
366 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
367 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
368 CloseHandle( handle2 );
370 SetLastError(0xdeadbeef);
371 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
372 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
373 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
374 CloseHandle( handle2 );
376 SetLastError(0xdeadbeef);
377 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
378 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
379 CloseHandle( handle2 );
381 SetLastError(0xdeadbeef);
382 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
383 ok( !handle2, "OpenEvent succeeded\n");
384 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
386 CloseHandle( handle );
388 /* resource notifications are events too */
390 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
392 trace( "memory resource notifications not supported\n" );
393 return;
395 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
396 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
397 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
398 ret = pQueryMemoryResourceNotification( handle, &val );
399 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
400 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
402 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
403 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
404 ret = WaitForSingleObject( handle, 10 );
405 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
407 val = ~0;
408 ret = pQueryMemoryResourceNotification( handle, &val );
409 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
410 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
411 ret = CloseHandle( handle );
412 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
414 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
415 val = ~0;
416 ret = pQueryMemoryResourceNotification( handle, &val );
417 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
418 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
419 CloseHandle( handle );
422 static void test_semaphore(void)
424 HANDLE handle, handle2;
426 /* test case sensitivity */
428 SetLastError(0xdeadbeef);
429 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
430 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
431 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
433 SetLastError(0xdeadbeef);
434 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
435 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
436 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
437 CloseHandle( handle2 );
439 SetLastError(0xdeadbeef);
440 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
441 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
442 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
443 CloseHandle( handle2 );
445 SetLastError(0xdeadbeef);
446 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
447 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
448 CloseHandle( handle2 );
450 SetLastError(0xdeadbeef);
451 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
452 ok( !handle2, "OpenSemaphore succeeded\n");
453 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
455 CloseHandle( handle );
458 static void test_waitable_timer(void)
460 HANDLE handle, handle2;
462 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
464 win_skip("{Create,Open}WaitableTimerA() is not available\n");
465 return;
468 /* test case sensitivity */
470 SetLastError(0xdeadbeef);
471 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
472 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
473 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
475 SetLastError(0xdeadbeef);
476 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
477 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
478 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
479 CloseHandle( handle2 );
481 SetLastError(0xdeadbeef);
482 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
483 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
484 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
485 CloseHandle( handle2 );
487 SetLastError(0xdeadbeef);
488 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
489 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
490 CloseHandle( handle2 );
492 SetLastError(0xdeadbeef);
493 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
494 ok( !handle2, "OpenWaitableTimer succeeded\n");
495 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
496 GetLastError() == ERROR_INVALID_NAME, /* win98 */
497 "wrong error %u\n", GetLastError());
499 CloseHandle( handle );
502 static HANDLE sem = 0;
504 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
506 ReleaseSemaphore(sem, 1, NULL);
509 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
511 static void test_iocp_callback(void)
513 char temp_path[MAX_PATH];
514 char filename[MAX_PATH];
515 DWORD ret;
516 BOOL retb;
517 static const char prefix[] = "pfx";
518 HANDLE hFile;
519 HMODULE hmod = GetModuleHandleA("kernel32.dll");
520 DWORD bytesWritten;
521 const char *buffer = "12345678123456781234567812345678";
522 OVERLAPPED overlapped;
524 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
525 if(!p_BindIoCompletionCallback) {
526 win_skip("BindIoCompletionCallback not found in this DLL\n");
527 return;
530 sem = CreateSemaphore(NULL, 0, 1, NULL);
531 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
533 ret = GetTempPathA(MAX_PATH, temp_path);
534 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
535 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
537 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
538 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
540 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
541 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
542 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
544 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
545 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
546 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
548 ret = CloseHandle(hFile);
549 ok( ret, "CloseHandle: error %d\n", GetLastError());
550 ret = DeleteFileA(filename);
551 ok( ret, "DeleteFileA: error %d\n", GetLastError());
553 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
554 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
555 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
557 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
558 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
560 memset(&overlapped, 0, sizeof(overlapped));
561 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
562 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
564 ret = WaitForSingleObject(sem, 5000);
565 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
566 CloseHandle(sem);
568 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
569 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
570 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
571 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
572 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
573 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
575 ret = CloseHandle(hFile);
576 ok( ret, "CloseHandle: error %d\n", GetLastError());
577 ret = DeleteFileA(filename);
578 ok( ret, "DeleteFileA: error %d\n", GetLastError());
580 /* win2k3 requires the Flags parameter to be zero */
581 SetLastError(0xdeadbeef);
582 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
583 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
584 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
585 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
586 if (!retb)
587 ok(GetLastError() == ERROR_INVALID_PARAMETER,
588 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
589 else
590 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
591 ret = CloseHandle(hFile);
592 ok( ret, "CloseHandle: error %d\n", GetLastError());
593 ret = DeleteFileA(filename);
594 ok( ret, "DeleteFileA: error %d\n", GetLastError());
596 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
597 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
598 ok(GetLastError() == ERROR_INVALID_HANDLE ||
599 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
600 "Last error is %d\n", GetLastError());
603 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
605 int *pn = p;
606 ok(timedOut, "Timer callbacks should always time out\n");
607 ++*pn;
610 struct timer_queue_data1
612 int num_calls;
613 int max_calls;
614 HANDLE q, t;
617 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
619 struct timer_queue_data1 *d = p;
620 ok(timedOut, "Timer callbacks should always time out\n");
621 if (d->t && ++d->num_calls == d->max_calls)
623 BOOL ret;
624 SetLastError(0xdeadbeef);
625 /* Note, XP SP2 does *not* do any deadlock checking, so passing
626 INVALID_HANDLE_VALUE here will just hang. */
627 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
628 ok(!ret, "DeleteTimerQueueTimer\n");
629 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
633 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
635 struct timer_queue_data1 *d = p;
636 ok(timedOut, "Timer callbacks should always time out\n");
637 if (d->t && ++d->num_calls == d->max_calls)
639 /* Basically kill the timer since it won't have time to run
640 again. */
641 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
642 ok(ret, "ChangeTimerQueueTimer\n");
646 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
648 struct timer_queue_data1 *d = p;
649 ok(timedOut, "Timer callbacks should always time out\n");
650 if (d->t)
652 /* This tests whether a timer gets flagged for deletion before
653 or after the callback runs. If we start this timer with a
654 period of zero (run once), then ChangeTimerQueueTimer will
655 fail if the timer is already flagged. Hence we really run
656 only once. Otherwise we will run multiple times. */
657 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
658 ok(ret, "ChangeTimerQueueTimer\n");
659 ++d->num_calls;
663 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
665 DWORD_PTR delay = (DWORD_PTR) p;
666 ok(timedOut, "Timer callbacks should always time out\n");
667 if (delay)
668 Sleep(delay);
671 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
673 struct timer_queue_data1 *d = p;
674 ok(timedOut, "Timer callbacks should always time out\n");
675 /* This tests an original implementation bug where a deleted timer may get
676 to run, but it is tricky to set up. */
677 if (d->q && d->num_calls++ == 0)
679 /* First run: delete ourselves, then insert and remove a timer
680 that goes in front of us in the sorted timeout list. Once
681 removed, we will still timeout at the faster timer's due time,
682 but this should be a no-op if we are bug-free. There should
683 not be a second run. We can test the value of num_calls later. */
684 BOOL ret;
685 HANDLE t;
687 /* The delete will pend while we are in this callback. */
688 SetLastError(0xdeadbeef);
689 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
690 ok(!ret, "DeleteTimerQueueTimer\n");
691 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
693 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
694 ok(ret, "CreateTimerQueueTimer\n");
695 ok(t != NULL, "CreateTimerQueueTimer\n");
697 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
698 ok(ret, "DeleteTimerQueueTimer\n");
700 /* Now we stay alive by hanging around in the callback. */
701 Sleep(500);
705 static void test_timer_queue(void)
707 HANDLE q, t1, t2, t3, t4, t5;
708 int n1, n2, n3, n4, n5;
709 struct timer_queue_data1 d1, d2, d3, d4;
710 HANDLE e, et1, et2;
711 BOOL ret;
713 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
714 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
716 win_skip("TimerQueue API not present\n");
717 return;
720 /* Test asynchronous deletion of the queue. */
721 q = pCreateTimerQueue();
722 ok(q != NULL, "CreateTimerQueue\n");
724 SetLastError(0xdeadbeef);
725 ret = pDeleteTimerQueueEx(q, NULL);
726 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
727 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
728 GetLastError());
730 /* Test synchronous deletion of the queue and running timers. */
731 q = pCreateTimerQueue();
732 ok(q != NULL, "CreateTimerQueue\n");
734 /* Called once. */
735 t1 = NULL;
736 n1 = 0;
737 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
738 0, 0);
739 ok(ret, "CreateTimerQueueTimer\n");
740 ok(t1 != NULL, "CreateTimerQueueTimer\n");
742 /* A slow one. */
743 t2 = NULL;
744 n2 = 0;
745 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
746 100, 0);
747 ok(ret, "CreateTimerQueueTimer\n");
748 ok(t2 != NULL, "CreateTimerQueueTimer\n");
750 /* A fast one. */
751 t3 = NULL;
752 n3 = 0;
753 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
754 10, 0);
755 ok(ret, "CreateTimerQueueTimer\n");
756 ok(t3 != NULL, "CreateTimerQueueTimer\n");
758 /* Start really late (it won't start). */
759 t4 = NULL;
760 n4 = 0;
761 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
762 10, 0);
763 ok(ret, "CreateTimerQueueTimer\n");
764 ok(t4 != NULL, "CreateTimerQueueTimer\n");
766 /* Start soon, but delay so long it won't run again. */
767 t5 = NULL;
768 n5 = 0;
769 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
770 10000, 0);
771 ok(ret, "CreateTimerQueueTimer\n");
772 ok(t5 != NULL, "CreateTimerQueueTimer\n");
774 /* Give them a chance to do some work. */
775 Sleep(500);
777 /* Test deleting a once-only timer. */
778 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
779 ok(ret, "DeleteTimerQueueTimer\n");
781 /* A periodic timer. */
782 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
783 ok(ret, "DeleteTimerQueueTimer\n");
785 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
786 ok(ret, "DeleteTimerQueueEx\n");
787 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
788 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
789 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
790 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
792 /* Test synchronous deletion of the timer/queue with event trigger. */
793 e = CreateEvent(NULL, TRUE, FALSE, NULL);
794 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
795 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
796 if (!e || !et1 || !et2)
798 skip("Failed to create timer queue descruction event\n");
799 return;
802 q = pCreateTimerQueue();
803 ok(q != NULL, "CreateTimerQueue\n");
805 /* Run once and finish quickly (should be done when we delete it). */
806 t1 = NULL;
807 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
808 ok(ret, "CreateTimerQueueTimer\n");
809 ok(t1 != NULL, "CreateTimerQueueTimer\n");
811 /* Run once and finish slowly (shouldn't be done when we delete it). */
812 t2 = NULL;
813 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
814 0, 0);
815 ok(ret, "CreateTimerQueueTimer\n");
816 ok(t2 != NULL, "CreateTimerQueueTimer\n");
818 /* Run once and finish quickly (should be done when we delete it). */
819 t3 = NULL;
820 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
821 ok(ret, "CreateTimerQueueTimer\n");
822 ok(t3 != NULL, "CreateTimerQueueTimer\n");
824 /* Run once and finish slowly (shouldn't be done when we delete it). */
825 t4 = NULL;
826 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
827 0, 0);
828 ok(ret, "CreateTimerQueueTimer\n");
829 ok(t4 != NULL, "CreateTimerQueueTimer\n");
831 /* Give them a chance to start. */
832 Sleep(400);
834 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
835 even if the timer is finished. */
836 SetLastError(0xdeadbeef);
837 ret = pDeleteTimerQueueTimer(q, t1, NULL);
838 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
839 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
840 GetLastError());
842 SetLastError(0xdeadbeef);
843 ret = pDeleteTimerQueueTimer(q, t2, NULL);
844 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
845 ok(GetLastError() == ERROR_IO_PENDING,
846 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
847 GetLastError());
849 SetLastError(0xdeadbeef);
850 ret = pDeleteTimerQueueTimer(q, t3, et1);
851 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
852 ok(GetLastError() == 0xdeadbeef,
853 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
854 GetLastError());
855 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
856 "Timer destruction event not triggered\n");
858 SetLastError(0xdeadbeef);
859 ret = pDeleteTimerQueueTimer(q, t4, et2);
860 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
861 ok(GetLastError() == ERROR_IO_PENDING,
862 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
863 GetLastError());
864 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
865 "Timer destruction event not triggered\n");
867 SetLastError(0xdeadbeef);
868 ret = pDeleteTimerQueueEx(q, e);
869 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
870 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
871 GetLastError());
872 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
873 "Queue destruction event not triggered\n");
874 CloseHandle(e);
876 /* Test deleting/changing a timer in execution. */
877 q = pCreateTimerQueue();
878 ok(q != NULL, "CreateTimerQueue\n");
880 /* Test changing a once-only timer before it fires (this is allowed,
881 whereas after it fires you cannot). */
882 n1 = 0;
883 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
884 0, 0);
885 ok(ret, "CreateTimerQueueTimer\n");
886 ok(t1 != NULL, "CreateTimerQueueTimer\n");
887 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
888 ok(ret, "ChangeTimerQueueTimer\n");
890 d2.t = t2 = NULL;
891 d2.num_calls = 0;
892 d2.max_calls = 3;
893 d2.q = q;
894 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
895 10, 0);
896 d2.t = t2;
897 ok(ret, "CreateTimerQueueTimer\n");
898 ok(t2 != NULL, "CreateTimerQueueTimer\n");
900 d3.t = t3 = NULL;
901 d3.num_calls = 0;
902 d3.max_calls = 4;
903 d3.q = q;
904 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
905 10, 0);
906 d3.t = t3;
907 ok(ret, "CreateTimerQueueTimer\n");
908 ok(t3 != NULL, "CreateTimerQueueTimer\n");
910 d4.t = t4 = NULL;
911 d4.num_calls = 0;
912 d4.q = q;
913 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
914 0, 0);
915 d4.t = t4;
916 ok(ret, "CreateTimerQueueTimer\n");
917 ok(t4 != NULL, "CreateTimerQueueTimer\n");
919 Sleep(500);
921 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
922 ok(ret, "DeleteTimerQueueEx\n");
923 ok(n1 == 1, "ChangeTimerQueueTimer\n");
924 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
925 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
926 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
928 /* Test an obscure bug that was in the original implementation. */
929 q = pCreateTimerQueue();
930 ok(q != NULL, "CreateTimerQueue\n");
932 /* All the work is done in the callback. */
933 d1.t = t1 = NULL;
934 d1.num_calls = 0;
935 d1.q = q;
936 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
937 100, WT_EXECUTELONGFUNCTION);
938 d1.t = t1;
939 ok(ret, "CreateTimerQueueTimer\n");
940 ok(t1 != NULL, "CreateTimerQueueTimer\n");
942 Sleep(750);
944 SetLastError(0xdeadbeef);
945 ret = pDeleteTimerQueueEx(q, NULL);
946 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
947 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
948 GetLastError());
949 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
951 /* Test functions on the default timer queue. */
952 t1 = NULL;
953 n1 = 0;
954 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
955 1000, 0);
956 ok(ret, "CreateTimerQueueTimer, default queue\n");
957 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
959 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
960 ok(ret, "ChangeTimerQueueTimer, default queue\n");
962 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
963 ok(ret, "DeleteTimerQueueTimer, default queue\n");
965 /* Try mixing default and non-default queues. Apparently this works. */
966 q = pCreateTimerQueue();
967 ok(q != NULL, "CreateTimerQueue\n");
969 t1 = NULL;
970 n1 = 0;
971 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
972 1000, 0);
973 ok(ret, "CreateTimerQueueTimer\n");
974 ok(t1 != NULL, "CreateTimerQueueTimer\n");
976 t2 = NULL;
977 n2 = 0;
978 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
979 1000, 0);
980 ok(ret, "CreateTimerQueueTimer\n");
981 ok(t2 != NULL, "CreateTimerQueueTimer\n");
983 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
984 ok(ret, "ChangeTimerQueueTimer\n");
986 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
987 ok(ret, "ChangeTimerQueueTimer\n");
989 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
990 ok(ret, "DeleteTimerQueueTimer\n");
992 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
993 ok(ret, "DeleteTimerQueueTimer\n");
995 /* Try to delete the default queue? In any case: not allowed. */
996 SetLastError(0xdeadbeef);
997 ret = pDeleteTimerQueueEx(NULL, NULL);
998 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
999 ok(GetLastError() == ERROR_INVALID_HANDLE,
1000 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1001 GetLastError());
1003 SetLastError(0xdeadbeef);
1004 ret = pDeleteTimerQueueEx(q, NULL);
1005 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1006 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1007 GetLastError());
1010 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1012 DWORD tmp = HandleToULong(handle);
1013 tmp |= modify;
1014 return ULongToHandle(tmp);
1017 static void test_WaitForSingleObject(void)
1019 HANDLE signaled, nonsignaled, invalid;
1020 DWORD ret;
1022 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1023 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1024 invalid = (HANDLE) 0xdeadbee0;
1026 /* invalid handle with different values for lower 2 bits */
1027 SetLastError(0xdeadbeef);
1028 ret = WaitForSingleObject(invalid, 0);
1029 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1030 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1032 SetLastError(0xdeadbeef);
1033 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1034 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1035 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1037 SetLastError(0xdeadbeef);
1038 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1039 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1040 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1042 SetLastError(0xdeadbeef);
1043 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1044 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1045 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1047 /* valid handle with different values for lower 2 bits */
1048 SetLastError(0xdeadbeef);
1049 ret = WaitForSingleObject(nonsignaled, 0);
1050 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1051 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1053 SetLastError(0xdeadbeef);
1054 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1055 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1056 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1058 SetLastError(0xdeadbeef);
1059 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1060 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1061 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1063 SetLastError(0xdeadbeef);
1064 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1065 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1066 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1068 /* valid handle with different values for lower 2 bits */
1069 SetLastError(0xdeadbeef);
1070 ret = WaitForSingleObject(signaled, 0);
1071 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1072 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1074 SetLastError(0xdeadbeef);
1075 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1076 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1077 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1079 SetLastError(0xdeadbeef);
1080 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1081 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1082 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1084 SetLastError(0xdeadbeef);
1085 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1086 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1087 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1089 CloseHandle(signaled);
1090 CloseHandle(nonsignaled);
1093 static void test_WaitForMultipleObjects(void)
1095 DWORD r;
1096 int i;
1097 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1099 /* create the maximum number of events and make sure
1100 * we can wait on that many */
1101 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1103 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1104 ok( maxevents[i] != 0, "should create enough events\n");
1107 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1108 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1109 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1110 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1111 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1112 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1113 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1115 /* the lowest index is checked first and remaining events are untouched */
1116 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1117 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1120 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1121 if (maxevents[i]) CloseHandle(maxevents[i]);
1124 START_TEST(sync)
1126 HMODULE hdll = GetModuleHandle("kernel32");
1127 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1128 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1129 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1130 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1131 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1132 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1133 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1134 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1135 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1137 test_signalandwait();
1138 test_mutex();
1139 test_slist();
1140 test_event();
1141 test_semaphore();
1142 test_waitable_timer();
1143 test_iocp_callback();
1144 test_timer_queue();
1145 test_WaitForSingleObject();
1146 test_WaitForMultipleObjects();