Add AppDefaults app selection to control panel
[wine/gsoc-2012-control.git] / dlls / kernel32 / tests / sync.c
blob5ce8f09b087e7acdef2afb09d618b70cd7b7f213
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);
40 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE);
41 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*);
42 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*);
43 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID);
45 static void test_signalandwait(void)
47 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
48 HMODULE kernel32;
49 DWORD r;
50 HANDLE event[2], semaphore[2], file;
52 kernel32 = GetModuleHandle("kernel32");
53 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
55 if (!pSignalObjectAndWait)
56 return;
58 /* invalid parameters */
59 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
60 if (r == ERROR_INVALID_FUNCTION)
62 win_skip("SignalObjectAndWait is not implemented\n");
63 return; /* Win98/ME */
65 ok( r == WAIT_FAILED, "should fail\n");
67 event[0] = CreateEvent(NULL, 0, 0, NULL);
68 event[1] = CreateEvent(NULL, 1, 1, NULL);
70 ok( event[0] && event[1], "failed to create event flags\n");
72 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
73 ok( r == WAIT_FAILED, "should fail\n");
75 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
76 ok( r == WAIT_FAILED, "should fail\n");
79 /* valid parameters */
80 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
81 ok( r == WAIT_OBJECT_0, "should succeed\n");
83 /* event[0] is now signalled */
84 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
85 ok( r == WAIT_OBJECT_0, "should succeed\n");
87 /* event[0] is not signalled */
88 r = WaitForSingleObject(event[0], 0);
89 ok( r == WAIT_TIMEOUT, "event was signalled\n");
91 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
92 ok( r == WAIT_OBJECT_0, "should succeed\n");
94 /* clear event[1] and check for a timeout */
95 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
96 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
97 ok( r == WAIT_TIMEOUT, "should timeout\n");
99 CloseHandle(event[0]);
100 CloseHandle(event[1]);
102 /* semaphores */
103 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
104 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
105 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
107 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
108 ok( r == WAIT_OBJECT_0, "should succeed\n");
110 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
111 ok( r == WAIT_FAILED, "should fail\n");
113 r = ReleaseSemaphore(semaphore[0],1,NULL);
114 ok( r == FALSE, "should fail\n");
116 r = ReleaseSemaphore(semaphore[1],1,NULL);
117 ok( r == TRUE, "should succeed\n");
119 CloseHandle(semaphore[0]);
120 CloseHandle(semaphore[1]);
122 /* try a registry key */
123 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
124 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
125 r = pSignalObjectAndWait(file, file, 0, FALSE);
126 ok( r == WAIT_FAILED, "should fail\n");
127 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
128 CloseHandle(file);
131 static void test_mutex(void)
133 DWORD wait_ret;
134 BOOL ret;
135 HANDLE hCreated;
136 HANDLE hOpened;
137 int i;
138 DWORD failed = 0;
140 SetLastError(0xdeadbeef);
141 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
142 ok(hOpened == NULL, "OpenMutex succeeded\n");
143 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
145 SetLastError(0xdeadbeef);
146 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
147 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
149 SetLastError(0xdeadbeef);
150 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
151 todo_wine
152 ok(hOpened == NULL, "OpenMutex succeeded\n");
153 todo_wine
154 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
156 SetLastError(0xdeadbeef);
157 hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
158 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
159 wait_ret = WaitForSingleObject(hOpened, INFINITE);
160 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
161 CloseHandle(hOpened);
163 for(i=0; i < 31; i++)
165 wait_ret = WaitForSingleObject(hCreated, INFINITE);
166 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
169 SetLastError(0xdeadbeef);
170 hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
171 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
172 wait_ret = WaitForSingleObject(hOpened, INFINITE);
173 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
174 CloseHandle(hOpened);
176 for (i = 0; i < 32; i++)
178 SetLastError(0xdeadbeef);
179 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
180 if(hOpened != NULL)
182 SetLastError(0xdeadbeef);
183 ret = ReleaseMutex(hOpened);
184 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
185 CloseHandle(hOpened);
187 else
189 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
190 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
191 else
192 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
193 ReleaseMutex(hCreated);
194 failed |=0x1 << i;
198 todo_wine
199 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
201 SetLastError(0xdeadbeef);
202 ret = ReleaseMutex(hCreated);
203 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
204 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
206 /* test case sensitivity */
208 SetLastError(0xdeadbeef);
209 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
210 ok(!hOpened, "OpenMutex succeeded\n");
211 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
213 SetLastError(0xdeadbeef);
214 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
215 ok(!hOpened, "OpenMutex succeeded\n");
216 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
218 SetLastError(0xdeadbeef);
219 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
220 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
221 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
222 CloseHandle(hOpened);
224 SetLastError(0xdeadbeef);
225 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
226 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
227 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
228 CloseHandle(hOpened);
230 CloseHandle(hCreated);
233 static void test_slist(void)
235 struct item
237 SLIST_ENTRY entry;
238 int value;
239 } item1, item2, item3, *pitem;
241 SLIST_HEADER slist_header;
242 PSLIST_ENTRY entry;
243 USHORT size;
245 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
246 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
247 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
248 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
249 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
250 HMODULE kernel32;
252 kernel32 = GetModuleHandle("KERNEL32.DLL");
253 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
254 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
255 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
256 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
257 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
258 if (pInitializeSListHead == NULL ||
259 pQueryDepthSList == NULL ||
260 pInterlockedFlushSList == NULL ||
261 pInterlockedPopEntrySList == NULL ||
262 pInterlockedPushEntrySList == NULL)
264 win_skip("some required slist entrypoints were not found, skipping tests\n");
265 return;
268 memset(&slist_header, 0xFF, sizeof(slist_header));
269 pInitializeSListHead(&slist_header);
270 size = pQueryDepthSList(&slist_header);
271 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
273 item1.value = 1;
274 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
275 "previous entry in empty slist wasn't NULL\n");
276 size = pQueryDepthSList(&slist_header);
277 ok(size == 1, "slist with 1 item has size %d\n", size);
279 item2.value = 2;
280 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
281 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
282 if (entry != NULL)
284 pitem = (struct item*) entry;
285 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
287 size = pQueryDepthSList(&slist_header);
288 ok(size == 2, "slist with 2 items has size %d\n", size);
290 item3.value = 3;
291 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
292 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
293 if (entry != NULL)
295 pitem = (struct item*) entry;
296 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
298 size = pQueryDepthSList(&slist_header);
299 ok(size == 3, "slist with 3 items has size %d\n", size);
301 entry = pInterlockedPopEntrySList(&slist_header);
302 ok(entry != NULL, "entry shouldn't be NULL\n");
303 if (entry != NULL)
305 pitem = (struct item*) entry;
306 ok(pitem->value == 3, "unexpected entry removed\n");
308 size = pQueryDepthSList(&slist_header);
309 ok(size == 2, "slist with 2 items has size %d\n", size);
311 entry = pInterlockedFlushSList(&slist_header);
312 size = pQueryDepthSList(&slist_header);
313 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
314 if (size == 0)
316 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
317 "popping empty slist didn't return NULL\n");
319 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
320 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
323 static void test_event(void)
325 HANDLE handle, handle2;
326 SECURITY_ATTRIBUTES sa;
327 SECURITY_DESCRIPTOR sd;
328 ACL acl;
329 DWORD ret;
330 BOOL val;
332 /* no sd */
333 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
334 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
335 CloseHandle(handle);
337 sa.nLength = sizeof(sa);
338 sa.lpSecurityDescriptor = &sd;
339 sa.bInheritHandle = FALSE;
341 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
343 /* blank sd */
344 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
345 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
346 CloseHandle(handle);
348 /* sd with NULL dacl */
349 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
350 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
351 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
352 CloseHandle(handle);
354 /* sd with empty dacl */
355 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
356 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
357 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
358 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
359 CloseHandle(handle);
361 /* test case sensitivity */
363 SetLastError(0xdeadbeef);
364 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
365 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
366 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
368 SetLastError(0xdeadbeef);
369 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
370 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
371 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
372 CloseHandle( handle2 );
374 SetLastError(0xdeadbeef);
375 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
376 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
377 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
378 CloseHandle( handle2 );
380 SetLastError(0xdeadbeef);
381 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
382 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
383 CloseHandle( handle2 );
385 SetLastError(0xdeadbeef);
386 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
387 ok( !handle2, "OpenEvent succeeded\n");
388 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
390 CloseHandle( handle );
392 /* resource notifications are events too */
394 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
396 trace( "memory resource notifications not supported\n" );
397 return;
399 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
400 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
401 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
402 ret = pQueryMemoryResourceNotification( handle, &val );
403 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
404 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
406 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
407 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
408 ret = WaitForSingleObject( handle, 10 );
409 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
411 val = ~0;
412 ret = pQueryMemoryResourceNotification( handle, &val );
413 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
414 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
415 ret = CloseHandle( handle );
416 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
418 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
419 val = ~0;
420 ret = pQueryMemoryResourceNotification( handle, &val );
421 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
422 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
423 CloseHandle( handle );
426 static void test_semaphore(void)
428 HANDLE handle, handle2;
430 /* test case sensitivity */
432 SetLastError(0xdeadbeef);
433 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
434 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
435 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
437 SetLastError(0xdeadbeef);
438 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
439 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
440 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
441 CloseHandle( handle2 );
443 SetLastError(0xdeadbeef);
444 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
445 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
446 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
447 CloseHandle( handle2 );
449 SetLastError(0xdeadbeef);
450 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
451 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
452 CloseHandle( handle2 );
454 SetLastError(0xdeadbeef);
455 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
456 ok( !handle2, "OpenSemaphore succeeded\n");
457 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
459 CloseHandle( handle );
462 static void test_waitable_timer(void)
464 HANDLE handle, handle2;
466 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
468 win_skip("{Create,Open}WaitableTimerA() is not available\n");
469 return;
472 /* test case sensitivity */
474 SetLastError(0xdeadbeef);
475 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
476 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
477 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
479 SetLastError(0xdeadbeef);
480 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
481 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
482 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
483 CloseHandle( handle2 );
485 SetLastError(0xdeadbeef);
486 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
487 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
488 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
489 CloseHandle( handle2 );
491 SetLastError(0xdeadbeef);
492 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
493 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
494 CloseHandle( handle2 );
496 SetLastError(0xdeadbeef);
497 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
498 ok( !handle2, "OpenWaitableTimer succeeded\n");
499 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
500 GetLastError() == ERROR_INVALID_NAME, /* win98 */
501 "wrong error %u\n", GetLastError());
503 CloseHandle( handle );
506 static HANDLE sem = 0;
508 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
510 ReleaseSemaphore(sem, 1, NULL);
513 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
515 static void test_iocp_callback(void)
517 char temp_path[MAX_PATH];
518 char filename[MAX_PATH];
519 DWORD ret;
520 BOOL retb;
521 static const char prefix[] = "pfx";
522 HANDLE hFile;
523 HMODULE hmod = GetModuleHandleA("kernel32.dll");
524 DWORD bytesWritten;
525 const char *buffer = "12345678123456781234567812345678";
526 OVERLAPPED overlapped;
528 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
529 if(!p_BindIoCompletionCallback) {
530 win_skip("BindIoCompletionCallback not found in this DLL\n");
531 return;
534 sem = CreateSemaphore(NULL, 0, 1, NULL);
535 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
537 ret = GetTempPathA(MAX_PATH, temp_path);
538 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
539 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
541 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
542 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
544 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
545 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
546 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
548 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
549 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
550 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
552 ret = CloseHandle(hFile);
553 ok( ret, "CloseHandle: error %d\n", GetLastError());
554 ret = DeleteFileA(filename);
555 ok( ret, "DeleteFileA: error %d\n", GetLastError());
557 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
558 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
559 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
561 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
562 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
564 memset(&overlapped, 0, sizeof(overlapped));
565 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
566 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
568 ret = WaitForSingleObject(sem, 5000);
569 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
570 CloseHandle(sem);
572 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
573 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
574 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
575 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
576 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
577 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
579 ret = CloseHandle(hFile);
580 ok( ret, "CloseHandle: error %d\n", GetLastError());
581 ret = DeleteFileA(filename);
582 ok( ret, "DeleteFileA: error %d\n", GetLastError());
584 /* win2k3 requires the Flags parameter to be zero */
585 SetLastError(0xdeadbeef);
586 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
587 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
588 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
589 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
590 if (!retb)
591 ok(GetLastError() == ERROR_INVALID_PARAMETER,
592 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
593 else
594 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
595 ret = CloseHandle(hFile);
596 ok( ret, "CloseHandle: error %d\n", GetLastError());
597 ret = DeleteFileA(filename);
598 ok( ret, "DeleteFileA: error %d\n", GetLastError());
600 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
601 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
602 ok(GetLastError() == ERROR_INVALID_HANDLE ||
603 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
604 "Last error is %d\n", GetLastError());
607 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
609 int *pn = p;
610 ok(timedOut, "Timer callbacks should always time out\n");
611 ++*pn;
614 struct timer_queue_data1
616 int num_calls;
617 int max_calls;
618 HANDLE q, t;
621 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
623 struct timer_queue_data1 *d = p;
624 ok(timedOut, "Timer callbacks should always time out\n");
625 if (d->t && ++d->num_calls == d->max_calls)
627 BOOL ret;
628 SetLastError(0xdeadbeef);
629 /* Note, XP SP2 does *not* do any deadlock checking, so passing
630 INVALID_HANDLE_VALUE here will just hang. */
631 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
632 ok(!ret, "DeleteTimerQueueTimer\n");
633 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
637 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
639 struct timer_queue_data1 *d = p;
640 ok(timedOut, "Timer callbacks should always time out\n");
641 if (d->t && ++d->num_calls == d->max_calls)
643 /* Basically kill the timer since it won't have time to run
644 again. */
645 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
646 ok(ret, "ChangeTimerQueueTimer\n");
650 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
652 struct timer_queue_data1 *d = p;
653 ok(timedOut, "Timer callbacks should always time out\n");
654 if (d->t)
656 /* This tests whether a timer gets flagged for deletion before
657 or after the callback runs. If we start this timer with a
658 period of zero (run once), then ChangeTimerQueueTimer will
659 fail if the timer is already flagged. Hence we really run
660 only once. Otherwise we will run multiple times. */
661 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
662 ok(ret, "ChangeTimerQueueTimer\n");
663 ++d->num_calls;
667 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
669 DWORD_PTR delay = (DWORD_PTR) p;
670 ok(timedOut, "Timer callbacks should always time out\n");
671 if (delay)
672 Sleep(delay);
675 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
677 struct timer_queue_data1 *d = p;
678 ok(timedOut, "Timer callbacks should always time out\n");
679 /* This tests an original implementation bug where a deleted timer may get
680 to run, but it is tricky to set up. */
681 if (d->q && d->num_calls++ == 0)
683 /* First run: delete ourselves, then insert and remove a timer
684 that goes in front of us in the sorted timeout list. Once
685 removed, we will still timeout at the faster timer's due time,
686 but this should be a no-op if we are bug-free. There should
687 not be a second run. We can test the value of num_calls later. */
688 BOOL ret;
689 HANDLE t;
691 /* The delete will pend while we are in this callback. */
692 SetLastError(0xdeadbeef);
693 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
694 ok(!ret, "DeleteTimerQueueTimer\n");
695 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
697 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
698 ok(ret, "CreateTimerQueueTimer\n");
699 ok(t != NULL, "CreateTimerQueueTimer\n");
701 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
702 ok(ret, "DeleteTimerQueueTimer\n");
704 /* Now we stay alive by hanging around in the callback. */
705 Sleep(500);
709 static void test_timer_queue(void)
711 HANDLE q, t0, t1, t2, t3, t4, t5;
712 int n0, n1, n2, n3, n4, n5;
713 struct timer_queue_data1 d1, d2, d3, d4;
714 HANDLE e, et1, et2;
715 BOOL ret, ret0;
717 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
718 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
720 win_skip("TimerQueue API not present\n");
721 return;
724 /* Test asynchronous deletion of the queue. */
725 q = pCreateTimerQueue();
726 ok(q != NULL, "CreateTimerQueue\n");
728 SetLastError(0xdeadbeef);
729 ret = pDeleteTimerQueueEx(q, NULL);
730 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
731 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
732 GetLastError());
734 /* Test synchronous deletion of the queue and running timers. */
735 q = pCreateTimerQueue();
736 ok(q != NULL, "CreateTimerQueue\n");
738 /* Not called. */
739 t0 = NULL;
740 n0 = 0;
741 ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0,
742 300, 0);
743 ok(ret, "CreateTimerQueueTimer\n");
744 ok(t0 != NULL, "CreateTimerQueueTimer\n");
745 ret0 = pDeleteTimerQueueTimer(q, t0, NULL);
746 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
747 broken(ret0), /* Win 2000 & XP & 2003 */
748 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
750 /* Called once. */
751 t1 = NULL;
752 n1 = 0;
753 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
754 0, 0);
755 ok(ret, "CreateTimerQueueTimer\n");
756 ok(t1 != NULL, "CreateTimerQueueTimer\n");
758 /* A slow one. */
759 t2 = NULL;
760 n2 = 0;
761 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
762 100, 0);
763 ok(ret, "CreateTimerQueueTimer\n");
764 ok(t2 != NULL, "CreateTimerQueueTimer\n");
766 /* A fast one. */
767 t3 = NULL;
768 n3 = 0;
769 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
770 10, 0);
771 ok(ret, "CreateTimerQueueTimer\n");
772 ok(t3 != NULL, "CreateTimerQueueTimer\n");
774 /* Start really late (it won't start). */
775 t4 = NULL;
776 n4 = 0;
777 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
778 10, 0);
779 ok(ret, "CreateTimerQueueTimer\n");
780 ok(t4 != NULL, "CreateTimerQueueTimer\n");
782 /* Start soon, but delay so long it won't run again. */
783 t5 = NULL;
784 n5 = 0;
785 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
786 10000, 0);
787 ok(ret, "CreateTimerQueueTimer\n");
788 ok(t5 != NULL, "CreateTimerQueueTimer\n");
790 /* Give them a chance to do some work. */
791 Sleep(500);
793 /* Test deleting a once-only timer. */
794 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
795 ok(ret, "DeleteTimerQueueTimer\n");
797 /* A periodic timer. */
798 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
799 ok(ret, "DeleteTimerQueueTimer\n");
801 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
802 ok(ret, "DeleteTimerQueueEx\n");
803 todo_wine
804 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
805 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
806 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
807 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
808 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
810 /* Test synchronous deletion of the timer/queue with event trigger. */
811 e = CreateEvent(NULL, TRUE, FALSE, NULL);
812 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
813 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
814 if (!e || !et1 || !et2)
816 skip("Failed to create timer queue descruction event\n");
817 return;
820 q = pCreateTimerQueue();
821 ok(q != NULL, "CreateTimerQueue\n");
823 /* Run once and finish quickly (should be done when we delete it). */
824 t1 = NULL;
825 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
826 ok(ret, "CreateTimerQueueTimer\n");
827 ok(t1 != NULL, "CreateTimerQueueTimer\n");
829 /* Run once and finish slowly (shouldn't be done when we delete it). */
830 t2 = NULL;
831 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
832 0, 0);
833 ok(ret, "CreateTimerQueueTimer\n");
834 ok(t2 != NULL, "CreateTimerQueueTimer\n");
836 /* Run once and finish quickly (should be done when we delete it). */
837 t3 = NULL;
838 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
839 ok(ret, "CreateTimerQueueTimer\n");
840 ok(t3 != NULL, "CreateTimerQueueTimer\n");
842 /* Run once and finish slowly (shouldn't be done when we delete it). */
843 t4 = NULL;
844 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
845 0, 0);
846 ok(ret, "CreateTimerQueueTimer\n");
847 ok(t4 != NULL, "CreateTimerQueueTimer\n");
849 /* Give them a chance to start. */
850 Sleep(400);
852 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
853 even if the timer is finished. */
854 SetLastError(0xdeadbeef);
855 ret = pDeleteTimerQueueTimer(q, t1, NULL);
856 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
857 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
858 GetLastError());
860 SetLastError(0xdeadbeef);
861 ret = pDeleteTimerQueueTimer(q, t2, NULL);
862 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
863 ok(GetLastError() == ERROR_IO_PENDING,
864 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
865 GetLastError());
867 SetLastError(0xdeadbeef);
868 ret = pDeleteTimerQueueTimer(q, t3, et1);
869 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
870 ok(GetLastError() == 0xdeadbeef,
871 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
872 GetLastError());
873 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
874 "Timer destruction event not triggered\n");
876 SetLastError(0xdeadbeef);
877 ret = pDeleteTimerQueueTimer(q, t4, et2);
878 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
879 ok(GetLastError() == ERROR_IO_PENDING,
880 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
881 GetLastError());
882 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
883 "Timer destruction event not triggered\n");
885 SetLastError(0xdeadbeef);
886 ret = pDeleteTimerQueueEx(q, e);
887 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
888 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
889 GetLastError());
890 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
891 "Queue destruction event not triggered\n");
892 CloseHandle(e);
894 /* Test deleting/changing a timer in execution. */
895 q = pCreateTimerQueue();
896 ok(q != NULL, "CreateTimerQueue\n");
898 /* Test changing a once-only timer before it fires (this is allowed,
899 whereas after it fires you cannot). */
900 n1 = 0;
901 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
902 0, 0);
903 ok(ret, "CreateTimerQueueTimer\n");
904 ok(t1 != NULL, "CreateTimerQueueTimer\n");
905 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
906 ok(ret, "ChangeTimerQueueTimer\n");
908 d2.t = t2 = NULL;
909 d2.num_calls = 0;
910 d2.max_calls = 3;
911 d2.q = q;
912 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
913 10, 0);
914 d2.t = t2;
915 ok(ret, "CreateTimerQueueTimer\n");
916 ok(t2 != NULL, "CreateTimerQueueTimer\n");
918 d3.t = t3 = NULL;
919 d3.num_calls = 0;
920 d3.max_calls = 4;
921 d3.q = q;
922 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
923 10, 0);
924 d3.t = t3;
925 ok(ret, "CreateTimerQueueTimer\n");
926 ok(t3 != NULL, "CreateTimerQueueTimer\n");
928 d4.t = t4 = NULL;
929 d4.num_calls = 0;
930 d4.q = q;
931 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
932 0, 0);
933 d4.t = t4;
934 ok(ret, "CreateTimerQueueTimer\n");
935 ok(t4 != NULL, "CreateTimerQueueTimer\n");
937 Sleep(500);
939 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
940 ok(ret, "DeleteTimerQueueEx\n");
941 ok(n1 == 1, "ChangeTimerQueueTimer\n");
942 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
943 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
944 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
946 /* Test an obscure bug that was in the original implementation. */
947 q = pCreateTimerQueue();
948 ok(q != NULL, "CreateTimerQueue\n");
950 /* All the work is done in the callback. */
951 d1.t = t1 = NULL;
952 d1.num_calls = 0;
953 d1.q = q;
954 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
955 100, WT_EXECUTELONGFUNCTION);
956 d1.t = t1;
957 ok(ret, "CreateTimerQueueTimer\n");
958 ok(t1 != NULL, "CreateTimerQueueTimer\n");
960 Sleep(750);
962 SetLastError(0xdeadbeef);
963 ret = pDeleteTimerQueueEx(q, NULL);
964 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
965 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
966 GetLastError());
967 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
969 /* Test functions on the default timer queue. */
970 t1 = NULL;
971 n1 = 0;
972 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
973 1000, 0);
974 ok(ret, "CreateTimerQueueTimer, default queue\n");
975 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
977 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
978 ok(ret, "ChangeTimerQueueTimer, default queue\n");
980 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
981 ok(ret, "DeleteTimerQueueTimer, default queue\n");
983 /* Try mixing default and non-default queues. Apparently this works. */
984 q = pCreateTimerQueue();
985 ok(q != NULL, "CreateTimerQueue\n");
987 t1 = NULL;
988 n1 = 0;
989 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
990 1000, 0);
991 ok(ret, "CreateTimerQueueTimer\n");
992 ok(t1 != NULL, "CreateTimerQueueTimer\n");
994 t2 = NULL;
995 n2 = 0;
996 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
997 1000, 0);
998 ok(ret, "CreateTimerQueueTimer\n");
999 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1001 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1002 ok(ret, "ChangeTimerQueueTimer\n");
1004 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
1005 ok(ret, "ChangeTimerQueueTimer\n");
1007 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1008 ok(ret, "DeleteTimerQueueTimer\n");
1010 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1011 ok(ret, "DeleteTimerQueueTimer\n");
1013 /* Try to delete the default queue? In any case: not allowed. */
1014 SetLastError(0xdeadbeef);
1015 ret = pDeleteTimerQueueEx(NULL, NULL);
1016 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1017 ok(GetLastError() == ERROR_INVALID_HANDLE,
1018 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1019 GetLastError());
1021 SetLastError(0xdeadbeef);
1022 ret = pDeleteTimerQueueEx(q, NULL);
1023 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1024 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1025 GetLastError());
1028 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1030 DWORD tmp = HandleToULong(handle);
1031 tmp |= modify;
1032 return ULongToHandle(tmp);
1035 static void test_WaitForSingleObject(void)
1037 HANDLE signaled, nonsignaled, invalid;
1038 DWORD ret;
1040 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1041 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1042 invalid = (HANDLE) 0xdeadbee0;
1044 /* invalid handle with different values for lower 2 bits */
1045 SetLastError(0xdeadbeef);
1046 ret = WaitForSingleObject(invalid, 0);
1047 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1048 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1050 SetLastError(0xdeadbeef);
1051 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1052 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1053 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1055 SetLastError(0xdeadbeef);
1056 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1057 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1058 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1060 SetLastError(0xdeadbeef);
1061 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1062 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1063 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1065 /* valid handle with different values for lower 2 bits */
1066 SetLastError(0xdeadbeef);
1067 ret = WaitForSingleObject(nonsignaled, 0);
1068 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1069 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1071 SetLastError(0xdeadbeef);
1072 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1073 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1074 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1076 SetLastError(0xdeadbeef);
1077 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1078 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1079 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1081 SetLastError(0xdeadbeef);
1082 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1083 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1084 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1086 /* valid handle with different values for lower 2 bits */
1087 SetLastError(0xdeadbeef);
1088 ret = WaitForSingleObject(signaled, 0);
1089 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1090 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1092 SetLastError(0xdeadbeef);
1093 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1094 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1095 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1097 SetLastError(0xdeadbeef);
1098 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1099 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1100 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1102 SetLastError(0xdeadbeef);
1103 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1104 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1105 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1107 CloseHandle(signaled);
1108 CloseHandle(nonsignaled);
1111 static void test_WaitForMultipleObjects(void)
1113 DWORD r;
1114 int i;
1115 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1117 /* create the maximum number of events and make sure
1118 * we can wait on that many */
1119 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1121 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1122 ok( maxevents[i] != 0, "should create enough events\n");
1125 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1126 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1127 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1128 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1129 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1130 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1131 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1133 /* the lowest index is checked first and remaining events are untouched */
1134 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1135 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1138 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1139 if (maxevents[i]) CloseHandle(maxevents[i]);
1142 static BOOL g_initcallback_ret, g_initcallback_called;
1143 static void *g_initctxt;
1145 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1147 g_initcallback_called = TRUE;
1148 /* zero bit set means here that initialization is taking place - initialization locked */
1149 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1150 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1151 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1152 return g_initcallback_ret;
1155 static void test_initonce(void)
1157 INIT_ONCE initonce;
1158 BOOL ret, pending;
1160 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1162 skip("one-time initialization API not supported\n");
1163 return;
1166 /* blocking initialization with callback */
1167 initonce.Ptr = (void*)0xdeadbeef;
1168 pInitOnceInitialize(&initonce);
1169 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1171 /* initialisation completed successfully */
1172 g_initcallback_ret = TRUE;
1173 g_initctxt = NULL;
1174 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1175 ok(ret, "got wrong ret value %d\n", ret);
1176 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1177 ok(g_initctxt == (void*)0x0, "got %p\n", g_initctxt);
1178 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1180 /* so it's been called already so won't be called again */
1181 g_initctxt = NULL;
1182 g_initcallback_called = FALSE;
1183 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1184 ok(ret, "got wrong ret value %d\n", ret);
1185 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1186 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1187 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1189 pInitOnceInitialize(&initonce);
1190 g_initcallback_called = FALSE;
1191 /* 2 lower order bits should never be used, you'll get a crash in result */
1192 g_initctxt = (void*)0xFFFFFFF0;
1193 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1194 ok(ret, "got wrong ret value %d\n", ret);
1195 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1196 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1197 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1199 /* callback failed */
1200 g_initcallback_ret = FALSE;
1201 g_initcallback_called = FALSE;
1202 g_initctxt = NULL;
1203 pInitOnceInitialize(&initonce);
1204 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1205 ok(!ret, "got wrong ret value %d\n", ret);
1206 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1207 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1208 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1210 /* blocking initialzation without a callback */
1211 pInitOnceInitialize(&initonce);
1212 g_initctxt = NULL;
1213 pending = FALSE;
1214 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1215 ok(ret, "got wrong ret value %d\n", ret);
1216 ok(pending, "got %d\n", pending);
1217 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1218 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1219 /* another attempt to begin initialization with block a single thread */
1221 g_initctxt = NULL;
1222 pending = 0xf;
1223 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1224 ok(!ret, "got wrong ret value %d\n", ret);
1225 ok(pending == 0xf, "got %d\n", pending);
1226 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1227 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1229 g_initctxt = (void*)0xdeadbee0;
1230 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1231 ok(!ret, "got wrong ret value %d\n", ret);
1232 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1234 /* once failed already */
1235 g_initctxt = (void*)0xdeadbee0;
1236 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1237 ok(ret, "got wrong ret value %d\n", ret);
1238 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1241 START_TEST(sync)
1243 HMODULE hdll = GetModuleHandle("kernel32");
1244 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1245 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1246 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1247 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1248 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1249 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1250 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1251 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1252 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1253 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
1254 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
1255 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
1256 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
1258 test_signalandwait();
1259 test_mutex();
1260 test_slist();
1261 test_event();
1262 test_semaphore();
1263 test_waitable_timer();
1264 test_iocp_callback();
1265 test_timer_queue();
1266 test_WaitForSingleObject();
1267 test_WaitForMultipleObjects();
1268 test_initonce();