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);
40 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
41 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
43 static void test_signalandwait(void)
45 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
48 HANDLE event[2], semaphore[2], file;
50 kernel32 = GetModuleHandle("kernel32");
51 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
53 if (!pSignalObjectAndWait)
56 /* invalid parameters */
57 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
58 if (r == ERROR_INVALID_FUNCTION)
60 win_skip("SignalObjectAndWait is not implemented\n");
61 return; /* Win98/ME */
63 ok( r == WAIT_FAILED, "should fail\n");
65 event[0] = CreateEvent(NULL, 0, 0, NULL);
66 event[1] = CreateEvent(NULL, 1, 1, NULL);
68 ok( event[0] && event[1], "failed to create event flags\n");
70 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
71 ok( r == WAIT_FAILED, "should fail\n");
73 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
74 ok( r == WAIT_FAILED, "should fail\n");
77 /* valid parameters */
78 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
79 ok( r == WAIT_OBJECT_0, "should succeed\n");
81 /* event[0] is now signalled */
82 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
83 ok( r == WAIT_OBJECT_0, "should succeed\n");
85 /* event[0] is not signalled */
86 r = WaitForSingleObject(event[0], 0);
87 ok( r == WAIT_TIMEOUT, "event was signalled\n");
89 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
90 ok( r == WAIT_OBJECT_0, "should succeed\n");
92 /* clear event[1] and check for a timeout */
93 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
94 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
95 ok( r == WAIT_TIMEOUT, "should timeout\n");
97 CloseHandle(event[0]);
98 CloseHandle(event[1]);
101 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
102 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
103 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
105 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
106 ok( r == WAIT_OBJECT_0, "should succeed\n");
108 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
109 ok( r == WAIT_FAILED, "should fail\n");
111 r = ReleaseSemaphore(semaphore[0],1,NULL);
112 ok( r == FALSE, "should fail\n");
114 r = ReleaseSemaphore(semaphore[1],1,NULL);
115 ok( r == TRUE, "should succeed\n");
117 CloseHandle(semaphore[0]);
118 CloseHandle(semaphore[1]);
120 /* try a registry key */
121 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
122 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
123 r = pSignalObjectAndWait(file, file, 0, FALSE);
124 ok( r == WAIT_FAILED, "should fail\n");
125 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
129 static void test_mutex(void)
138 SetLastError(0xdeadbeef);
139 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
140 ok(hOpened == NULL, "OpenMutex succeeded\n");
141 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
143 SetLastError(0xdeadbeef);
144 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
145 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
147 SetLastError(0xdeadbeef);
148 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
150 ok(hOpened == NULL, "OpenMutex succeeded\n");
152 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
154 SetLastError(0xdeadbeef);
155 hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
156 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
157 wait_ret = WaitForSingleObject(hOpened, INFINITE);
158 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
159 CloseHandle(hOpened);
161 for(i=0; i < 31; i++)
163 wait_ret = WaitForSingleObject(hCreated, INFINITE);
164 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
167 SetLastError(0xdeadbeef);
168 hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
169 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
170 wait_ret = WaitForSingleObject(hOpened, INFINITE);
171 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
172 CloseHandle(hOpened);
174 for (i = 0; i < 32; i++)
176 SetLastError(0xdeadbeef);
177 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
180 SetLastError(0xdeadbeef);
181 ret = ReleaseMutex(hOpened);
182 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
183 CloseHandle(hOpened);
187 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
188 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
190 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
191 ReleaseMutex(hCreated);
197 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
199 SetLastError(0xdeadbeef);
200 ret = ReleaseMutex(hCreated);
201 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
202 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
204 /* test case sensitivity */
206 SetLastError(0xdeadbeef);
207 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
208 ok(!hOpened, "OpenMutex succeeded\n");
209 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
211 SetLastError(0xdeadbeef);
212 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
213 ok(!hOpened, "OpenMutex succeeded\n");
214 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
216 SetLastError(0xdeadbeef);
217 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
218 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
219 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
220 CloseHandle(hOpened);
222 SetLastError(0xdeadbeef);
223 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
224 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
225 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
226 CloseHandle(hOpened);
228 CloseHandle(hCreated);
231 static void test_slist(void)
237 } item1, item2, item3, *pitem;
239 SLIST_HEADER slist_header;
243 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
244 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
245 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
246 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
247 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
250 kernel32 = GetModuleHandle("KERNEL32.DLL");
251 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
252 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
253 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
254 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
255 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
256 if (pInitializeSListHead == NULL ||
257 pQueryDepthSList == NULL ||
258 pInterlockedFlushSList == NULL ||
259 pInterlockedPopEntrySList == NULL ||
260 pInterlockedPushEntrySList == NULL)
262 win_skip("some required slist entrypoints were not found, skipping tests\n");
266 memset(&slist_header, 0xFF, sizeof(slist_header));
267 pInitializeSListHead(&slist_header);
268 size = pQueryDepthSList(&slist_header);
269 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
272 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
273 "previous entry in empty slist wasn't NULL\n");
274 size = pQueryDepthSList(&slist_header);
275 ok(size == 1, "slist with 1 item has size %d\n", size);
278 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
279 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
282 pitem = (struct item*) entry;
283 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
285 size = pQueryDepthSList(&slist_header);
286 ok(size == 2, "slist with 2 items has size %d\n", size);
289 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
290 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
293 pitem = (struct item*) entry;
294 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
296 size = pQueryDepthSList(&slist_header);
297 ok(size == 3, "slist with 3 items has size %d\n", size);
299 entry = pInterlockedPopEntrySList(&slist_header);
300 ok(entry != NULL, "entry shouldn't be NULL\n");
303 pitem = (struct item*) entry;
304 ok(pitem->value == 3, "unexpected entry removed\n");
306 size = pQueryDepthSList(&slist_header);
307 ok(size == 2, "slist with 2 items has size %d\n", size);
309 entry = pInterlockedFlushSList(&slist_header);
310 size = pQueryDepthSList(&slist_header);
311 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
314 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
315 "popping empty slist didn't return NULL\n");
317 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
318 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
321 static void test_event(void)
323 HANDLE handle, handle2;
324 SECURITY_ATTRIBUTES sa;
325 SECURITY_DESCRIPTOR sd;
331 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
332 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
335 sa.nLength = sizeof(sa);
336 sa.lpSecurityDescriptor = &sd;
337 sa.bInheritHandle = FALSE;
339 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
342 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
343 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
346 /* sd with NULL dacl */
347 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
348 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
349 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
352 /* sd with empty dacl */
353 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
354 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
355 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
356 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
359 /* test case sensitivity */
361 SetLastError(0xdeadbeef);
362 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
363 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
364 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
366 SetLastError(0xdeadbeef);
367 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
368 ok( handle2 != NULL, "CreateEvent 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 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
374 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
375 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
376 CloseHandle( handle2 );
378 SetLastError(0xdeadbeef);
379 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
380 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
381 CloseHandle( handle2 );
383 SetLastError(0xdeadbeef);
384 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
385 ok( !handle2, "OpenEvent succeeded\n");
386 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
388 CloseHandle( handle );
390 /* resource notifications are events too */
392 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
394 trace( "memory resource notifications not supported\n" );
397 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
398 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
399 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
400 ret = pQueryMemoryResourceNotification( handle, &val );
401 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
402 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
404 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
405 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
406 ret = WaitForSingleObject( handle, 10 );
407 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
410 ret = pQueryMemoryResourceNotification( handle, &val );
411 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
412 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
413 ret = CloseHandle( handle );
414 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
416 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
418 ret = pQueryMemoryResourceNotification( handle, &val );
419 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
420 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
421 CloseHandle( handle );
424 static void test_semaphore(void)
426 HANDLE handle, handle2;
428 /* test case sensitivity */
430 SetLastError(0xdeadbeef);
431 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
432 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
433 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
435 SetLastError(0xdeadbeef);
436 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
437 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
438 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
439 CloseHandle( handle2 );
441 SetLastError(0xdeadbeef);
442 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
443 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
444 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
445 CloseHandle( handle2 );
447 SetLastError(0xdeadbeef);
448 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
449 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
450 CloseHandle( handle2 );
452 SetLastError(0xdeadbeef);
453 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
454 ok( !handle2, "OpenSemaphore succeeded\n");
455 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
457 CloseHandle( handle );
460 static void test_waitable_timer(void)
462 HANDLE handle, handle2;
464 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
466 win_skip("{Create,Open}WaitableTimerA() is not available\n");
470 /* test case sensitivity */
472 SetLastError(0xdeadbeef);
473 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
474 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
475 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
477 SetLastError(0xdeadbeef);
478 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
479 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
480 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
481 CloseHandle( handle2 );
483 SetLastError(0xdeadbeef);
484 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
485 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
486 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
487 CloseHandle( handle2 );
489 SetLastError(0xdeadbeef);
490 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
491 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
492 CloseHandle( handle2 );
494 SetLastError(0xdeadbeef);
495 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
496 ok( !handle2, "OpenWaitableTimer succeeded\n");
497 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
498 GetLastError() == ERROR_INVALID_NAME, /* win98 */
499 "wrong error %u\n", GetLastError());
501 CloseHandle( handle );
504 static HANDLE sem = 0;
506 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
508 ReleaseSemaphore(sem, 1, NULL);
511 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
513 static void test_iocp_callback(void)
515 char temp_path[MAX_PATH];
516 char filename[MAX_PATH];
519 static const char prefix[] = "pfx";
521 HMODULE hmod = GetModuleHandleA("kernel32.dll");
523 const char *buffer = "12345678123456781234567812345678";
524 OVERLAPPED overlapped;
526 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
527 if(!p_BindIoCompletionCallback) {
528 win_skip("BindIoCompletionCallback not found in this DLL\n");
532 sem = CreateSemaphore(NULL, 0, 1, NULL);
533 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
535 ret = GetTempPathA(MAX_PATH, temp_path);
536 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
537 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
539 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
540 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
542 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
543 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
544 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
546 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
547 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
548 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
550 ret = CloseHandle(hFile);
551 ok( ret, "CloseHandle: error %d\n", GetLastError());
552 ret = DeleteFileA(filename);
553 ok( ret, "DeleteFileA: error %d\n", GetLastError());
555 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
556 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
557 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
559 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
560 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
562 memset(&overlapped, 0, sizeof(overlapped));
563 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
564 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
566 ret = WaitForSingleObject(sem, 5000);
567 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
570 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
571 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
572 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
573 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
574 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
575 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
577 ret = CloseHandle(hFile);
578 ok( ret, "CloseHandle: error %d\n", GetLastError());
579 ret = DeleteFileA(filename);
580 ok( ret, "DeleteFileA: error %d\n", GetLastError());
582 /* win2k3 requires the Flags parameter to be zero */
583 SetLastError(0xdeadbeef);
584 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
585 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
586 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
587 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
589 ok(GetLastError() == ERROR_INVALID_PARAMETER,
590 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
592 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
593 ret = CloseHandle(hFile);
594 ok( ret, "CloseHandle: error %d\n", GetLastError());
595 ret = DeleteFileA(filename);
596 ok( ret, "DeleteFileA: error %d\n", GetLastError());
598 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
599 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
600 ok(GetLastError() == ERROR_INVALID_HANDLE ||
601 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
602 "Last error is %d\n", GetLastError());
605 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
608 ok(timedOut, "Timer callbacks should always time out\n");
612 struct timer_queue_data1
619 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
621 struct timer_queue_data1 *d = p;
622 ok(timedOut, "Timer callbacks should always time out\n");
623 if (d->t && ++d->num_calls == d->max_calls)
626 SetLastError(0xdeadbeef);
627 /* Note, XP SP2 does *not* do any deadlock checking, so passing
628 INVALID_HANDLE_VALUE here will just hang. */
629 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
630 ok(!ret, "DeleteTimerQueueTimer\n");
631 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
635 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
637 struct timer_queue_data1 *d = p;
638 ok(timedOut, "Timer callbacks should always time out\n");
639 if (d->t && ++d->num_calls == d->max_calls)
641 /* Basically kill the timer since it won't have time to run
643 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
644 ok(ret, "ChangeTimerQueueTimer\n");
648 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
650 struct timer_queue_data1 *d = p;
651 ok(timedOut, "Timer callbacks should always time out\n");
654 /* This tests whether a timer gets flagged for deletion before
655 or after the callback runs. If we start this timer with a
656 period of zero (run once), then ChangeTimerQueueTimer will
657 fail if the timer is already flagged. Hence we really run
658 only once. Otherwise we will run multiple times. */
659 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
660 ok(ret, "ChangeTimerQueueTimer\n");
665 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
667 DWORD_PTR delay = (DWORD_PTR) p;
668 ok(timedOut, "Timer callbacks should always time out\n");
673 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
675 struct timer_queue_data1 *d = p;
676 ok(timedOut, "Timer callbacks should always time out\n");
677 /* This tests an original implementation bug where a deleted timer may get
678 to run, but it is tricky to set up. */
679 if (d->q && d->num_calls++ == 0)
681 /* First run: delete ourselves, then insert and remove a timer
682 that goes in front of us in the sorted timeout list. Once
683 removed, we will still timeout at the faster timer's due time,
684 but this should be a no-op if we are bug-free. There should
685 not be a second run. We can test the value of num_calls later. */
689 /* The delete will pend while we are in this callback. */
690 SetLastError(0xdeadbeef);
691 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
692 ok(!ret, "DeleteTimerQueueTimer\n");
693 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
695 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
696 ok(ret, "CreateTimerQueueTimer\n");
697 ok(t != NULL, "CreateTimerQueueTimer\n");
699 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
700 ok(ret, "DeleteTimerQueueTimer\n");
702 /* Now we stay alive by hanging around in the callback. */
707 static void test_timer_queue(void)
709 HANDLE q, t0, t1, t2, t3, t4, t5;
710 int n0, n1, n2, n3, n4, n5;
711 struct timer_queue_data1 d1, d2, d3, d4;
715 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
716 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
718 win_skip("TimerQueue API not present\n");
722 /* Test asynchronous deletion of the queue. */
723 q = pCreateTimerQueue();
724 ok(q != NULL, "CreateTimerQueue\n");
726 SetLastError(0xdeadbeef);
727 ret = pDeleteTimerQueueEx(q, NULL);
728 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
729 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
732 /* Test synchronous deletion of the queue and running timers. */
733 q = pCreateTimerQueue();
734 ok(q != NULL, "CreateTimerQueue\n");
739 ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0,
741 ok(ret, "CreateTimerQueueTimer\n");
742 ok(t0 != NULL, "CreateTimerQueueTimer\n");
743 ret0 = pDeleteTimerQueueTimer(q, t0, NULL);
744 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
745 broken(ret0), /* Win 2000 & XP & 2003 */
746 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
751 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
753 ok(ret, "CreateTimerQueueTimer\n");
754 ok(t1 != NULL, "CreateTimerQueueTimer\n");
759 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
761 ok(ret, "CreateTimerQueueTimer\n");
762 ok(t2 != NULL, "CreateTimerQueueTimer\n");
767 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
769 ok(ret, "CreateTimerQueueTimer\n");
770 ok(t3 != NULL, "CreateTimerQueueTimer\n");
772 /* Start really late (it won't start). */
775 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
777 ok(ret, "CreateTimerQueueTimer\n");
778 ok(t4 != NULL, "CreateTimerQueueTimer\n");
780 /* Start soon, but delay so long it won't run again. */
783 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
785 ok(ret, "CreateTimerQueueTimer\n");
786 ok(t5 != NULL, "CreateTimerQueueTimer\n");
788 /* Give them a chance to do some work. */
791 /* Test deleting a once-only timer. */
792 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
793 ok(ret, "DeleteTimerQueueTimer\n");
795 /* A periodic timer. */
796 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
797 ok(ret, "DeleteTimerQueueTimer\n");
799 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
800 ok(ret, "DeleteTimerQueueEx\n");
802 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
803 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
804 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
805 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
806 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
808 /* Test synchronous deletion of the timer/queue with event trigger. */
809 e = CreateEvent(NULL, TRUE, FALSE, NULL);
810 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
811 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
812 if (!e || !et1 || !et2)
814 skip("Failed to create timer queue descruction event\n");
818 q = pCreateTimerQueue();
819 ok(q != NULL, "CreateTimerQueue\n");
821 /* Run once and finish quickly (should be done when we delete it). */
823 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
824 ok(ret, "CreateTimerQueueTimer\n");
825 ok(t1 != NULL, "CreateTimerQueueTimer\n");
827 /* Run once and finish slowly (shouldn't be done when we delete it). */
829 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
831 ok(ret, "CreateTimerQueueTimer\n");
832 ok(t2 != NULL, "CreateTimerQueueTimer\n");
834 /* Run once and finish quickly (should be done when we delete it). */
836 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
837 ok(ret, "CreateTimerQueueTimer\n");
838 ok(t3 != NULL, "CreateTimerQueueTimer\n");
840 /* Run once and finish slowly (shouldn't be done when we delete it). */
842 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
844 ok(ret, "CreateTimerQueueTimer\n");
845 ok(t4 != NULL, "CreateTimerQueueTimer\n");
847 /* Give them a chance to start. */
850 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
851 even if the timer is finished. */
852 SetLastError(0xdeadbeef);
853 ret = pDeleteTimerQueueTimer(q, t1, NULL);
854 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
855 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
858 SetLastError(0xdeadbeef);
859 ret = pDeleteTimerQueueTimer(q, t2, NULL);
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",
865 SetLastError(0xdeadbeef);
866 ret = pDeleteTimerQueueTimer(q, t3, et1);
867 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
868 ok(GetLastError() == 0xdeadbeef,
869 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
871 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
872 "Timer destruction event not triggered\n");
874 SetLastError(0xdeadbeef);
875 ret = pDeleteTimerQueueTimer(q, t4, et2);
876 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
877 ok(GetLastError() == ERROR_IO_PENDING,
878 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
880 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
881 "Timer destruction event not triggered\n");
883 SetLastError(0xdeadbeef);
884 ret = pDeleteTimerQueueEx(q, e);
885 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
886 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
888 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
889 "Queue destruction event not triggered\n");
892 /* Test deleting/changing a timer in execution. */
893 q = pCreateTimerQueue();
894 ok(q != NULL, "CreateTimerQueue\n");
896 /* Test changing a once-only timer before it fires (this is allowed,
897 whereas after it fires you cannot). */
899 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
901 ok(ret, "CreateTimerQueueTimer\n");
902 ok(t1 != NULL, "CreateTimerQueueTimer\n");
903 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
904 ok(ret, "ChangeTimerQueueTimer\n");
910 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
913 ok(ret, "CreateTimerQueueTimer\n");
914 ok(t2 != NULL, "CreateTimerQueueTimer\n");
920 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
923 ok(ret, "CreateTimerQueueTimer\n");
924 ok(t3 != NULL, "CreateTimerQueueTimer\n");
929 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
932 ok(ret, "CreateTimerQueueTimer\n");
933 ok(t4 != NULL, "CreateTimerQueueTimer\n");
937 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
938 ok(ret, "DeleteTimerQueueEx\n");
939 ok(n1 == 1, "ChangeTimerQueueTimer\n");
940 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
941 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
942 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
944 /* Test an obscure bug that was in the original implementation. */
945 q = pCreateTimerQueue();
946 ok(q != NULL, "CreateTimerQueue\n");
948 /* All the work is done in the callback. */
952 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
953 100, WT_EXECUTELONGFUNCTION);
955 ok(ret, "CreateTimerQueueTimer\n");
956 ok(t1 != NULL, "CreateTimerQueueTimer\n");
960 SetLastError(0xdeadbeef);
961 ret = pDeleteTimerQueueEx(q, NULL);
962 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
963 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
965 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
967 /* Test functions on the default timer queue. */
970 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
972 ok(ret, "CreateTimerQueueTimer, default queue\n");
973 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
975 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
976 ok(ret, "ChangeTimerQueueTimer, default queue\n");
978 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
979 ok(ret, "DeleteTimerQueueTimer, default queue\n");
981 /* Try mixing default and non-default queues. Apparently this works. */
982 q = pCreateTimerQueue();
983 ok(q != NULL, "CreateTimerQueue\n");
987 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
989 ok(ret, "CreateTimerQueueTimer\n");
990 ok(t1 != NULL, "CreateTimerQueueTimer\n");
994 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
996 ok(ret, "CreateTimerQueueTimer\n");
997 ok(t2 != NULL, "CreateTimerQueueTimer\n");
999 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1000 ok(ret, "ChangeTimerQueueTimer\n");
1002 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
1003 ok(ret, "ChangeTimerQueueTimer\n");
1005 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1006 ok(ret, "DeleteTimerQueueTimer\n");
1008 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1009 ok(ret, "DeleteTimerQueueTimer\n");
1011 /* Try to delete the default queue? In any case: not allowed. */
1012 SetLastError(0xdeadbeef);
1013 ret = pDeleteTimerQueueEx(NULL, NULL);
1014 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1015 ok(GetLastError() == ERROR_INVALID_HANDLE,
1016 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1019 SetLastError(0xdeadbeef);
1020 ret = pDeleteTimerQueueEx(q, NULL);
1021 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1022 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1026 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1028 DWORD tmp = HandleToULong(handle);
1030 return ULongToHandle(tmp);
1033 static void test_WaitForSingleObject(void)
1035 HANDLE signaled, nonsignaled, invalid;
1038 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1039 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1040 invalid = (HANDLE) 0xdeadbee0;
1042 /* invalid handle with different values for lower 2 bits */
1043 SetLastError(0xdeadbeef);
1044 ret = WaitForSingleObject(invalid, 0);
1045 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1046 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1048 SetLastError(0xdeadbeef);
1049 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1050 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1051 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1053 SetLastError(0xdeadbeef);
1054 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1055 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1056 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1058 SetLastError(0xdeadbeef);
1059 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1060 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1061 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1063 /* valid handle with different values for lower 2 bits */
1064 SetLastError(0xdeadbeef);
1065 ret = WaitForSingleObject(nonsignaled, 0);
1066 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1067 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1069 SetLastError(0xdeadbeef);
1070 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1071 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1072 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1074 SetLastError(0xdeadbeef);
1075 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1076 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1077 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1079 SetLastError(0xdeadbeef);
1080 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1081 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1082 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1084 /* valid handle with different values for lower 2 bits */
1085 SetLastError(0xdeadbeef);
1086 ret = WaitForSingleObject(signaled, 0);
1087 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1088 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1090 SetLastError(0xdeadbeef);
1091 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1092 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1093 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1095 SetLastError(0xdeadbeef);
1096 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1097 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1098 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1100 SetLastError(0xdeadbeef);
1101 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1102 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1103 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1105 CloseHandle(signaled);
1106 CloseHandle(nonsignaled);
1109 static void test_WaitForMultipleObjects(void)
1113 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1115 /* create the maximum number of events and make sure
1116 * we can wait on that many */
1117 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1119 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1120 ok( maxevents[i] != 0, "should create enough events\n");
1123 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1124 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1125 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1126 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1127 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1128 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1129 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1131 /* the lowest index is checked first and remaining events are untouched */
1132 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1133 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1136 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1137 if (maxevents[i]) CloseHandle(maxevents[i]);
1140 static BOOL g_initcallback_ret, g_initcallback_called;
1142 BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1144 g_initcallback_called = TRUE;
1145 /* zero bit set means here that initialization is taking place - initialization locked */
1146 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1147 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1148 return g_initcallback_ret;
1151 static void test_initonce(void)
1157 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1159 skip("one-time initialization API not supported\n");
1163 initonce.Ptr = (void*)0xdeadbeef;
1164 pInitOnceInitialize(&initonce);
1165 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1167 /* initialisation completed successfully */
1168 g_initcallback_ret = TRUE;
1170 ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
1171 ok(ret, "got wrong ret value %d\n", ret);
1172 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1173 ok(ctxt == (void*)0x0, "got %p\n", ctxt);
1174 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1176 /* so it's been called already so won't be called again */
1178 g_initcallback_called = FALSE;
1179 ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
1180 ok(ret, "got wrong ret value %d\n", ret);
1181 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1182 ok(ctxt == (void*)0, "got %p\n", ctxt);
1183 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1185 pInitOnceInitialize(&initonce);
1186 g_initcallback_called = FALSE;
1187 /* 2 lower order bits should never be used, you'll get a crash in result */
1188 ctxt = (void*)0xFFFFFFF0;
1189 ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
1190 ok(ret, "got wrong ret value %d\n", ret);
1191 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1192 ok(ctxt == (void*)0xFFFFFFF0, "got %p\n", ctxt);
1193 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1195 /* callback failed */
1196 g_initcallback_ret = FALSE;
1197 g_initcallback_called = FALSE;
1199 pInitOnceInitialize(&initonce);
1200 ret = pInitOnceExecuteOnce(&initonce, &initonce_callback, (void*)0xdeadbeef, &ctxt);
1201 ok(!ret, "got wrong ret value %d\n", ret);
1202 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1203 ok(ctxt == NULL, "got %p\n", ctxt);
1204 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1209 HMODULE hdll = GetModuleHandle("kernel32");
1210 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1211 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1212 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1213 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1214 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1215 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1216 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1217 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1218 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1219 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
1220 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
1222 test_signalandwait();
1227 test_waitable_timer();
1228 test_iocp_callback();
1230 test_WaitForSingleObject();
1231 test_WaitForMultipleObjects();