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
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);
46 HANDLE event[2], semaphore[2], file;
48 kernel32 = GetModuleHandle("kernel32");
49 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
51 if (!pSignalObjectAndWait)
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]);
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");
127 static void test_mutex(void)
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");
148 ok(hOpened == NULL, "OpenMutex succeeded\n");
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");
178 SetLastError(0xdeadbeef);
179 ret = ReleaseMutex(hOpened);
180 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
181 CloseHandle(hOpened);
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);
188 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
189 ReleaseMutex(hCreated);
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)
235 } item1, item2, item3, *pitem;
237 SLIST_HEADER slist_header;
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);
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");
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);
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);
276 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
277 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
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);
287 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
288 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
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");
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);
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;
329 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
330 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
333 sa.nLength = sizeof(sa);
334 sa.lpSecurityDescriptor = &sd;
335 sa.bInheritHandle = FALSE;
337 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
340 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
341 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
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());
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());
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" );
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 );
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");
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");
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];
517 static const char prefix[] = "pfx";
519 HMODULE hmod = GetModuleHandleA("kernel32.dll");
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");
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");
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);
587 ok(GetLastError() == ERROR_INVALID_PARAMETER,
588 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
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)
606 ok(timedOut, "Timer callbacks should always time out\n");
610 struct timer_queue_data1
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)
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
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");
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");
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");
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. */
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. */
705 static void test_timer_queue(void)
707 HANDLE q, t0, t1, t2, t3, t4, t5;
708 int n0, n1, n2, n3, n4, n5;
709 struct timer_queue_data1 d1, d2, d3, d4;
713 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
714 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
716 win_skip("TimerQueue API not present\n");
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",
730 /* Test synchronous deletion of the queue and running timers. */
731 q = pCreateTimerQueue();
732 ok(q != NULL, "CreateTimerQueue\n");
737 ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0,
739 ok(ret, "CreateTimerQueueTimer\n");
740 ok(t0 != NULL, "CreateTimerQueueTimer\n");
741 ret0 = pDeleteTimerQueueTimer(q, t0, NULL);
742 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
743 broken(ret0), /* Win 2000 & XP & 2003 */
744 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
749 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
751 ok(ret, "CreateTimerQueueTimer\n");
752 ok(t1 != NULL, "CreateTimerQueueTimer\n");
757 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
759 ok(ret, "CreateTimerQueueTimer\n");
760 ok(t2 != NULL, "CreateTimerQueueTimer\n");
765 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
767 ok(ret, "CreateTimerQueueTimer\n");
768 ok(t3 != NULL, "CreateTimerQueueTimer\n");
770 /* Start really late (it won't start). */
773 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
775 ok(ret, "CreateTimerQueueTimer\n");
776 ok(t4 != NULL, "CreateTimerQueueTimer\n");
778 /* Start soon, but delay so long it won't run again. */
781 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
783 ok(ret, "CreateTimerQueueTimer\n");
784 ok(t5 != NULL, "CreateTimerQueueTimer\n");
786 /* Give them a chance to do some work. */
789 /* Test deleting a once-only timer. */
790 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
791 ok(ret, "DeleteTimerQueueTimer\n");
793 /* A periodic timer. */
794 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
795 ok(ret, "DeleteTimerQueueTimer\n");
797 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
798 ok(ret, "DeleteTimerQueueEx\n");
800 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
801 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
802 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
803 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
804 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
806 /* Test synchronous deletion of the timer/queue with event trigger. */
807 e = CreateEvent(NULL, TRUE, FALSE, NULL);
808 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
809 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
810 if (!e || !et1 || !et2)
812 skip("Failed to create timer queue descruction event\n");
816 q = pCreateTimerQueue();
817 ok(q != NULL, "CreateTimerQueue\n");
819 /* Run once and finish quickly (should be done when we delete it). */
821 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
822 ok(ret, "CreateTimerQueueTimer\n");
823 ok(t1 != NULL, "CreateTimerQueueTimer\n");
825 /* Run once and finish slowly (shouldn't be done when we delete it). */
827 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
829 ok(ret, "CreateTimerQueueTimer\n");
830 ok(t2 != NULL, "CreateTimerQueueTimer\n");
832 /* Run once and finish quickly (should be done when we delete it). */
834 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
835 ok(ret, "CreateTimerQueueTimer\n");
836 ok(t3 != NULL, "CreateTimerQueueTimer\n");
838 /* Run once and finish slowly (shouldn't be done when we delete it). */
840 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
842 ok(ret, "CreateTimerQueueTimer\n");
843 ok(t4 != NULL, "CreateTimerQueueTimer\n");
845 /* Give them a chance to start. */
848 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
849 even if the timer is finished. */
850 SetLastError(0xdeadbeef);
851 ret = pDeleteTimerQueueTimer(q, t1, NULL);
852 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
853 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
856 SetLastError(0xdeadbeef);
857 ret = pDeleteTimerQueueTimer(q, t2, NULL);
858 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
859 ok(GetLastError() == ERROR_IO_PENDING,
860 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
863 SetLastError(0xdeadbeef);
864 ret = pDeleteTimerQueueTimer(q, t3, et1);
865 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
866 ok(GetLastError() == 0xdeadbeef,
867 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
869 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
870 "Timer destruction event not triggered\n");
872 SetLastError(0xdeadbeef);
873 ret = pDeleteTimerQueueTimer(q, t4, et2);
874 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
875 ok(GetLastError() == ERROR_IO_PENDING,
876 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
878 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
879 "Timer destruction event not triggered\n");
881 SetLastError(0xdeadbeef);
882 ret = pDeleteTimerQueueEx(q, e);
883 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
884 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
886 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
887 "Queue destruction event not triggered\n");
890 /* Test deleting/changing a timer in execution. */
891 q = pCreateTimerQueue();
892 ok(q != NULL, "CreateTimerQueue\n");
894 /* Test changing a once-only timer before it fires (this is allowed,
895 whereas after it fires you cannot). */
897 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
899 ok(ret, "CreateTimerQueueTimer\n");
900 ok(t1 != NULL, "CreateTimerQueueTimer\n");
901 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
902 ok(ret, "ChangeTimerQueueTimer\n");
908 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
911 ok(ret, "CreateTimerQueueTimer\n");
912 ok(t2 != NULL, "CreateTimerQueueTimer\n");
918 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
921 ok(ret, "CreateTimerQueueTimer\n");
922 ok(t3 != NULL, "CreateTimerQueueTimer\n");
927 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
930 ok(ret, "CreateTimerQueueTimer\n");
931 ok(t4 != NULL, "CreateTimerQueueTimer\n");
935 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
936 ok(ret, "DeleteTimerQueueEx\n");
937 ok(n1 == 1, "ChangeTimerQueueTimer\n");
938 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
939 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
940 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
942 /* Test an obscure bug that was in the original implementation. */
943 q = pCreateTimerQueue();
944 ok(q != NULL, "CreateTimerQueue\n");
946 /* All the work is done in the callback. */
950 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
951 100, WT_EXECUTELONGFUNCTION);
953 ok(ret, "CreateTimerQueueTimer\n");
954 ok(t1 != NULL, "CreateTimerQueueTimer\n");
958 SetLastError(0xdeadbeef);
959 ret = pDeleteTimerQueueEx(q, NULL);
960 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
961 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
963 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
965 /* Test functions on the default timer queue. */
968 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
970 ok(ret, "CreateTimerQueueTimer, default queue\n");
971 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
973 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
974 ok(ret, "ChangeTimerQueueTimer, default queue\n");
976 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
977 ok(ret, "DeleteTimerQueueTimer, default queue\n");
979 /* Try mixing default and non-default queues. Apparently this works. */
980 q = pCreateTimerQueue();
981 ok(q != NULL, "CreateTimerQueue\n");
985 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
987 ok(ret, "CreateTimerQueueTimer\n");
988 ok(t1 != NULL, "CreateTimerQueueTimer\n");
992 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
994 ok(ret, "CreateTimerQueueTimer\n");
995 ok(t2 != NULL, "CreateTimerQueueTimer\n");
997 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
998 ok(ret, "ChangeTimerQueueTimer\n");
1000 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
1001 ok(ret, "ChangeTimerQueueTimer\n");
1003 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1004 ok(ret, "DeleteTimerQueueTimer\n");
1006 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1007 ok(ret, "DeleteTimerQueueTimer\n");
1009 /* Try to delete the default queue? In any case: not allowed. */
1010 SetLastError(0xdeadbeef);
1011 ret = pDeleteTimerQueueEx(NULL, NULL);
1012 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1013 ok(GetLastError() == ERROR_INVALID_HANDLE,
1014 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1017 SetLastError(0xdeadbeef);
1018 ret = pDeleteTimerQueueEx(q, NULL);
1019 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1020 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1024 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1026 DWORD tmp = HandleToULong(handle);
1028 return ULongToHandle(tmp);
1031 static void test_WaitForSingleObject(void)
1033 HANDLE signaled, nonsignaled, invalid;
1036 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1037 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1038 invalid = (HANDLE) 0xdeadbee0;
1040 /* invalid handle with different values for lower 2 bits */
1041 SetLastError(0xdeadbeef);
1042 ret = WaitForSingleObject(invalid, 0);
1043 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1044 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1046 SetLastError(0xdeadbeef);
1047 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1048 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1049 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1051 SetLastError(0xdeadbeef);
1052 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1053 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1054 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1056 SetLastError(0xdeadbeef);
1057 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1058 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1059 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1061 /* valid handle with different values for lower 2 bits */
1062 SetLastError(0xdeadbeef);
1063 ret = WaitForSingleObject(nonsignaled, 0);
1064 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1065 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1067 SetLastError(0xdeadbeef);
1068 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1069 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1070 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1072 SetLastError(0xdeadbeef);
1073 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1074 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1075 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1077 SetLastError(0xdeadbeef);
1078 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1079 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1080 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1082 /* valid handle with different values for lower 2 bits */
1083 SetLastError(0xdeadbeef);
1084 ret = WaitForSingleObject(signaled, 0);
1085 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1086 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1088 SetLastError(0xdeadbeef);
1089 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1090 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1091 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1093 SetLastError(0xdeadbeef);
1094 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1095 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1096 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1098 SetLastError(0xdeadbeef);
1099 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1100 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1101 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1103 CloseHandle(signaled);
1104 CloseHandle(nonsignaled);
1107 static void test_WaitForMultipleObjects(void)
1111 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1113 /* create the maximum number of events and make sure
1114 * we can wait on that many */
1115 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1117 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1118 ok( maxevents[i] != 0, "should create enough events\n");
1121 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1122 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1123 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1124 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1125 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1126 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1127 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1129 /* the lowest index is checked first and remaining events are untouched */
1130 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1131 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1134 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1135 if (maxevents[i]) CloseHandle(maxevents[i]);
1140 HMODULE hdll = GetModuleHandle("kernel32");
1141 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1142 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1143 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1144 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1145 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1146 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1147 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1148 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1149 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1151 test_signalandwait();
1156 test_waitable_timer();
1157 test_iocp_callback();
1159 test_WaitForSingleObject();
1160 test_WaitForMultipleObjects();