Release 1.6-rc2.
[wine/testsucceed.git] / dlls / kernel32 / tests / sync.c
blob3924dc047a77e09562b72082ced11d2c9529eaaf
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 (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE);
46 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD);
47 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE);
48 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE);
50 static void test_signalandwait(void)
52 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
53 HMODULE kernel32;
54 DWORD r;
55 HANDLE event[2], semaphore[2], file;
57 kernel32 = GetModuleHandle("kernel32");
58 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
60 if (!pSignalObjectAndWait)
61 return;
63 /* invalid parameters */
64 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
65 if (r == ERROR_INVALID_FUNCTION)
67 win_skip("SignalObjectAndWait is not implemented\n");
68 return; /* Win98/ME */
70 ok( r == WAIT_FAILED, "should fail\n");
72 event[0] = CreateEvent(NULL, 0, 0, NULL);
73 event[1] = CreateEvent(NULL, 1, 1, NULL);
75 ok( event[0] && event[1], "failed to create event flags\n");
77 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
78 ok( r == WAIT_FAILED, "should fail\n");
80 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
81 ok( r == WAIT_FAILED, "should fail\n");
84 /* valid parameters */
85 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
86 ok( r == WAIT_OBJECT_0, "should succeed\n");
88 /* event[0] is now signalled */
89 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
90 ok( r == WAIT_OBJECT_0, "should succeed\n");
92 /* event[0] is not signalled */
93 r = WaitForSingleObject(event[0], 0);
94 ok( r == WAIT_TIMEOUT, "event was signalled\n");
96 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
97 ok( r == WAIT_OBJECT_0, "should succeed\n");
99 /* clear event[1] and check for a timeout */
100 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
101 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
102 ok( r == WAIT_TIMEOUT, "should timeout\n");
104 CloseHandle(event[0]);
105 CloseHandle(event[1]);
107 /* semaphores */
108 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
109 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
110 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
112 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
113 ok( r == WAIT_OBJECT_0, "should succeed\n");
115 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
116 ok( r == WAIT_FAILED, "should fail\n");
118 r = ReleaseSemaphore(semaphore[0],1,NULL);
119 ok( r == FALSE, "should fail\n");
121 r = ReleaseSemaphore(semaphore[1],1,NULL);
122 ok( r == TRUE, "should succeed\n");
124 CloseHandle(semaphore[0]);
125 CloseHandle(semaphore[1]);
127 /* try a registry key */
128 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
129 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
130 r = pSignalObjectAndWait(file, file, 0, FALSE);
131 ok( r == WAIT_FAILED, "should fail\n");
132 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
133 CloseHandle(file);
136 static void test_mutex(void)
138 DWORD wait_ret;
139 BOOL ret;
140 HANDLE hCreated;
141 HANDLE hOpened;
142 int i;
143 DWORD failed = 0;
145 SetLastError(0xdeadbeef);
146 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
147 ok(hOpened == NULL, "OpenMutex succeeded\n");
148 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
150 SetLastError(0xdeadbeef);
151 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
152 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
154 SetLastError(0xdeadbeef);
155 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
156 todo_wine
157 ok(hOpened == NULL, "OpenMutex succeeded\n");
158 todo_wine
159 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
161 SetLastError(0xdeadbeef);
162 hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
163 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
164 wait_ret = WaitForSingleObject(hOpened, INFINITE);
165 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
166 CloseHandle(hOpened);
168 for(i=0; i < 31; i++)
170 wait_ret = WaitForSingleObject(hCreated, INFINITE);
171 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
174 SetLastError(0xdeadbeef);
175 hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
176 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
177 wait_ret = WaitForSingleObject(hOpened, INFINITE);
178 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
179 CloseHandle(hOpened);
181 for (i = 0; i < 32; i++)
183 SetLastError(0xdeadbeef);
184 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
185 if(hOpened != NULL)
187 SetLastError(0xdeadbeef);
188 ret = ReleaseMutex(hOpened);
189 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
190 CloseHandle(hOpened);
192 else
194 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
195 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
196 else
197 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
198 ReleaseMutex(hCreated);
199 failed |=0x1 << i;
203 todo_wine
204 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
206 SetLastError(0xdeadbeef);
207 ret = ReleaseMutex(hCreated);
208 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
209 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
211 /* test case sensitivity */
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 = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
220 ok(!hOpened, "OpenMutex succeeded\n");
221 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
223 SetLastError(0xdeadbeef);
224 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
225 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
226 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
227 CloseHandle(hOpened);
229 SetLastError(0xdeadbeef);
230 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
231 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
232 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
233 CloseHandle(hOpened);
235 CloseHandle(hCreated);
238 static void test_slist(void)
240 struct item
242 SLIST_ENTRY entry;
243 int value;
244 } item1, item2, item3, *pitem;
246 SLIST_HEADER slist_header;
247 PSLIST_ENTRY entry;
248 USHORT size;
250 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
251 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
252 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
253 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
254 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
255 HMODULE kernel32;
257 kernel32 = GetModuleHandle("KERNEL32.DLL");
258 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
259 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
260 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
261 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
262 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
263 if (pInitializeSListHead == NULL ||
264 pQueryDepthSList == NULL ||
265 pInterlockedFlushSList == NULL ||
266 pInterlockedPopEntrySList == NULL ||
267 pInterlockedPushEntrySList == NULL)
269 win_skip("some required slist entrypoints were not found, skipping tests\n");
270 return;
273 memset(&slist_header, 0xFF, sizeof(slist_header));
274 pInitializeSListHead(&slist_header);
275 size = pQueryDepthSList(&slist_header);
276 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
278 item1.value = 1;
279 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
280 "previous entry in empty slist wasn't NULL\n");
281 size = pQueryDepthSList(&slist_header);
282 ok(size == 1, "slist with 1 item has size %d\n", size);
284 item2.value = 2;
285 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
286 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
287 if (entry != NULL)
289 pitem = (struct item*) entry;
290 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
292 size = pQueryDepthSList(&slist_header);
293 ok(size == 2, "slist with 2 items has size %d\n", size);
295 item3.value = 3;
296 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
297 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
298 if (entry != NULL)
300 pitem = (struct item*) entry;
301 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
303 size = pQueryDepthSList(&slist_header);
304 ok(size == 3, "slist with 3 items has size %d\n", size);
306 entry = pInterlockedPopEntrySList(&slist_header);
307 ok(entry != NULL, "entry shouldn't be NULL\n");
308 if (entry != NULL)
310 pitem = (struct item*) entry;
311 ok(pitem->value == 3, "unexpected entry removed\n");
313 size = pQueryDepthSList(&slist_header);
314 ok(size == 2, "slist with 2 items has size %d\n", size);
316 entry = pInterlockedFlushSList(&slist_header);
317 size = pQueryDepthSList(&slist_header);
318 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
319 if (size == 0)
321 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
322 "popping empty slist didn't return NULL\n");
324 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
325 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
328 static void test_event(void)
330 HANDLE handle, handle2;
331 SECURITY_ATTRIBUTES sa;
332 SECURITY_DESCRIPTOR sd;
333 ACL acl;
334 DWORD ret;
335 BOOL val;
337 /* no sd */
338 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
339 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
340 CloseHandle(handle);
342 sa.nLength = sizeof(sa);
343 sa.lpSecurityDescriptor = &sd;
344 sa.bInheritHandle = FALSE;
346 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
348 /* blank sd */
349 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
350 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
351 CloseHandle(handle);
353 /* sd with NULL dacl */
354 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
355 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
356 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
357 CloseHandle(handle);
359 /* sd with empty dacl */
360 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
361 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
362 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
363 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
364 CloseHandle(handle);
366 /* test case sensitivity */
368 SetLastError(0xdeadbeef);
369 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
370 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
371 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
373 SetLastError(0xdeadbeef);
374 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
375 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
376 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
377 CloseHandle( handle2 );
379 SetLastError(0xdeadbeef);
380 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
381 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
382 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
383 CloseHandle( handle2 );
385 SetLastError(0xdeadbeef);
386 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
387 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
388 CloseHandle( handle2 );
390 SetLastError(0xdeadbeef);
391 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
392 ok( !handle2, "OpenEvent succeeded\n");
393 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
395 CloseHandle( handle );
397 /* resource notifications are events too */
399 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
401 trace( "memory resource notifications not supported\n" );
402 return;
404 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
405 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
406 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
407 ret = pQueryMemoryResourceNotification( handle, &val );
408 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
409 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
411 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
412 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
413 ret = WaitForSingleObject( handle, 10 );
414 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
416 val = ~0;
417 ret = pQueryMemoryResourceNotification( handle, &val );
418 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
419 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
420 ret = CloseHandle( handle );
421 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
423 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
424 val = ~0;
425 ret = pQueryMemoryResourceNotification( handle, &val );
426 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
427 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
428 CloseHandle( handle );
431 static void test_semaphore(void)
433 HANDLE handle, handle2;
435 /* test case sensitivity */
437 SetLastError(0xdeadbeef);
438 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
439 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
440 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
442 SetLastError(0xdeadbeef);
443 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
444 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
445 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
446 CloseHandle( handle2 );
448 SetLastError(0xdeadbeef);
449 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
450 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
451 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
452 CloseHandle( handle2 );
454 SetLastError(0xdeadbeef);
455 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
456 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
457 CloseHandle( handle2 );
459 SetLastError(0xdeadbeef);
460 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
461 ok( !handle2, "OpenSemaphore succeeded\n");
462 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
464 CloseHandle( handle );
467 static void test_waitable_timer(void)
469 HANDLE handle, handle2;
471 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
473 win_skip("{Create,Open}WaitableTimerA() is not available\n");
474 return;
477 /* test case sensitivity */
479 SetLastError(0xdeadbeef);
480 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
481 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
482 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
484 SetLastError(0xdeadbeef);
485 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
486 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
487 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
488 CloseHandle( handle2 );
490 SetLastError(0xdeadbeef);
491 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
492 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
493 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
494 CloseHandle( handle2 );
496 SetLastError(0xdeadbeef);
497 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
498 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
499 CloseHandle( handle2 );
501 SetLastError(0xdeadbeef);
502 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
503 ok( !handle2, "OpenWaitableTimer succeeded\n");
504 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
505 GetLastError() == ERROR_INVALID_NAME, /* win98 */
506 "wrong error %u\n", GetLastError());
508 CloseHandle( handle );
511 static HANDLE sem = 0;
513 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
515 ReleaseSemaphore(sem, 1, NULL);
518 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
520 static void test_iocp_callback(void)
522 char temp_path[MAX_PATH];
523 char filename[MAX_PATH];
524 DWORD ret;
525 BOOL retb;
526 static const char prefix[] = "pfx";
527 HANDLE hFile;
528 HMODULE hmod = GetModuleHandleA("kernel32.dll");
529 DWORD bytesWritten;
530 const char *buffer = "12345678123456781234567812345678";
531 OVERLAPPED overlapped;
533 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
534 if(!p_BindIoCompletionCallback) {
535 win_skip("BindIoCompletionCallback not found in this DLL\n");
536 return;
539 sem = CreateSemaphore(NULL, 0, 1, NULL);
540 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
542 ret = GetTempPathA(MAX_PATH, temp_path);
543 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
544 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
546 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
547 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
549 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
550 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
551 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
553 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
554 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
555 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
557 ret = CloseHandle(hFile);
558 ok( ret, "CloseHandle: error %d\n", GetLastError());
559 ret = DeleteFileA(filename);
560 ok( ret, "DeleteFileA: error %d\n", GetLastError());
562 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
563 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
564 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
566 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
567 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
569 memset(&overlapped, 0, sizeof(overlapped));
570 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
571 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
573 ret = WaitForSingleObject(sem, 5000);
574 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
575 CloseHandle(sem);
577 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
578 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
579 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
580 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
581 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
582 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
584 ret = CloseHandle(hFile);
585 ok( ret, "CloseHandle: error %d\n", GetLastError());
586 ret = DeleteFileA(filename);
587 ok( ret, "DeleteFileA: error %d\n", GetLastError());
589 /* win2k3 requires the Flags parameter to be zero */
590 SetLastError(0xdeadbeef);
591 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
592 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
593 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
594 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
595 if (!retb)
596 ok(GetLastError() == ERROR_INVALID_PARAMETER,
597 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
598 else
599 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
600 ret = CloseHandle(hFile);
601 ok( ret, "CloseHandle: error %d\n", GetLastError());
602 ret = DeleteFileA(filename);
603 ok( ret, "DeleteFileA: error %d\n", GetLastError());
605 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
606 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
607 ok(GetLastError() == ERROR_INVALID_HANDLE ||
608 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
609 "Last error is %d\n", GetLastError());
612 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
614 int *pn = p;
615 ok(timedOut, "Timer callbacks should always time out\n");
616 ++*pn;
619 struct timer_queue_data1
621 int num_calls;
622 int max_calls;
623 HANDLE q, t;
626 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
628 struct timer_queue_data1 *d = p;
629 ok(timedOut, "Timer callbacks should always time out\n");
630 if (d->t && ++d->num_calls == d->max_calls)
632 BOOL ret;
633 SetLastError(0xdeadbeef);
634 /* Note, XP SP2 does *not* do any deadlock checking, so passing
635 INVALID_HANDLE_VALUE here will just hang. */
636 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
637 ok(!ret, "DeleteTimerQueueTimer\n");
638 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
642 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
644 struct timer_queue_data1 *d = p;
645 ok(timedOut, "Timer callbacks should always time out\n");
646 if (d->t && ++d->num_calls == d->max_calls)
648 /* Basically kill the timer since it won't have time to run
649 again. */
650 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
651 ok(ret, "ChangeTimerQueueTimer\n");
655 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
657 struct timer_queue_data1 *d = p;
658 ok(timedOut, "Timer callbacks should always time out\n");
659 if (d->t)
661 /* This tests whether a timer gets flagged for deletion before
662 or after the callback runs. If we start this timer with a
663 period of zero (run once), then ChangeTimerQueueTimer will
664 fail if the timer is already flagged. Hence we really run
665 only once. Otherwise we will run multiple times. */
666 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
667 ok(ret, "ChangeTimerQueueTimer\n");
668 ++d->num_calls;
672 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
674 DWORD_PTR delay = (DWORD_PTR) p;
675 ok(timedOut, "Timer callbacks should always time out\n");
676 if (delay)
677 Sleep(delay);
680 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
682 struct timer_queue_data1 *d = p;
683 ok(timedOut, "Timer callbacks should always time out\n");
684 /* This tests an original implementation bug where a deleted timer may get
685 to run, but it is tricky to set up. */
686 if (d->q && d->num_calls++ == 0)
688 /* First run: delete ourselves, then insert and remove a timer
689 that goes in front of us in the sorted timeout list. Once
690 removed, we will still timeout at the faster timer's due time,
691 but this should be a no-op if we are bug-free. There should
692 not be a second run. We can test the value of num_calls later. */
693 BOOL ret;
694 HANDLE t;
696 /* The delete will pend while we are in this callback. */
697 SetLastError(0xdeadbeef);
698 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
699 ok(!ret, "DeleteTimerQueueTimer\n");
700 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
702 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
703 ok(ret, "CreateTimerQueueTimer\n");
704 ok(t != NULL, "CreateTimerQueueTimer\n");
706 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
707 ok(ret, "DeleteTimerQueueTimer\n");
709 /* Now we stay alive by hanging around in the callback. */
710 Sleep(500);
714 static void test_timer_queue(void)
716 HANDLE q, t0, t1, t2, t3, t4, t5;
717 int n0, n1, n2, n3, n4, n5;
718 struct timer_queue_data1 d1, d2, d3, d4;
719 HANDLE e, et1, et2;
720 BOOL ret, ret0;
722 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
723 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
725 win_skip("TimerQueue API not present\n");
726 return;
729 /* Test asynchronous deletion of the queue. */
730 q = pCreateTimerQueue();
731 ok(q != NULL, "CreateTimerQueue\n");
733 SetLastError(0xdeadbeef);
734 ret = pDeleteTimerQueueEx(q, NULL);
735 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
736 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
737 GetLastError());
739 /* Test synchronous deletion of the queue and running timers. */
740 q = pCreateTimerQueue();
741 ok(q != NULL, "CreateTimerQueue\n");
743 /* Not called. */
744 t0 = NULL;
745 n0 = 0;
746 ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0,
747 300, 0);
748 ok(ret, "CreateTimerQueueTimer\n");
749 ok(t0 != NULL, "CreateTimerQueueTimer\n");
750 ret0 = pDeleteTimerQueueTimer(q, t0, NULL);
751 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) ||
752 broken(ret0), /* Win 2000 & XP & 2003 */
753 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError());
755 /* Called once. */
756 t1 = NULL;
757 n1 = 0;
758 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
759 0, 0);
760 ok(ret, "CreateTimerQueueTimer\n");
761 ok(t1 != NULL, "CreateTimerQueueTimer\n");
763 /* A slow one. */
764 t2 = NULL;
765 n2 = 0;
766 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
767 100, 0);
768 ok(ret, "CreateTimerQueueTimer\n");
769 ok(t2 != NULL, "CreateTimerQueueTimer\n");
771 /* A fast one. */
772 t3 = NULL;
773 n3 = 0;
774 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
775 10, 0);
776 ok(ret, "CreateTimerQueueTimer\n");
777 ok(t3 != NULL, "CreateTimerQueueTimer\n");
779 /* Start really late (it won't start). */
780 t4 = NULL;
781 n4 = 0;
782 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
783 10, 0);
784 ok(ret, "CreateTimerQueueTimer\n");
785 ok(t4 != NULL, "CreateTimerQueueTimer\n");
787 /* Start soon, but delay so long it won't run again. */
788 t5 = NULL;
789 n5 = 0;
790 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
791 10000, 0);
792 ok(ret, "CreateTimerQueueTimer\n");
793 ok(t5 != NULL, "CreateTimerQueueTimer\n");
795 /* Give them a chance to do some work. */
796 Sleep(500);
798 /* Test deleting a once-only timer. */
799 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
800 ok(ret, "DeleteTimerQueueTimer\n");
802 /* A periodic timer. */
803 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
804 ok(ret, "DeleteTimerQueueTimer\n");
806 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
807 ok(ret, "DeleteTimerQueueEx\n");
808 todo_wine
809 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0);
810 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1);
811 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3);
812 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4);
813 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5);
815 /* Test synchronous deletion of the timer/queue with event trigger. */
816 e = CreateEvent(NULL, TRUE, FALSE, NULL);
817 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
818 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
819 if (!e || !et1 || !et2)
821 skip("Failed to create timer queue descruction event\n");
822 return;
825 q = pCreateTimerQueue();
826 ok(q != NULL, "CreateTimerQueue\n");
828 /* Run once and finish quickly (should be done when we delete it). */
829 t1 = NULL;
830 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
831 ok(ret, "CreateTimerQueueTimer\n");
832 ok(t1 != NULL, "CreateTimerQueueTimer\n");
834 /* Run once and finish slowly (shouldn't be done when we delete it). */
835 t2 = NULL;
836 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
837 0, 0);
838 ok(ret, "CreateTimerQueueTimer\n");
839 ok(t2 != NULL, "CreateTimerQueueTimer\n");
841 /* Run once and finish quickly (should be done when we delete it). */
842 t3 = NULL;
843 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
844 ok(ret, "CreateTimerQueueTimer\n");
845 ok(t3 != NULL, "CreateTimerQueueTimer\n");
847 /* Run once and finish slowly (shouldn't be done when we delete it). */
848 t4 = NULL;
849 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
850 0, 0);
851 ok(ret, "CreateTimerQueueTimer\n");
852 ok(t4 != NULL, "CreateTimerQueueTimer\n");
854 /* Give them a chance to start. */
855 Sleep(400);
857 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
858 even if the timer is finished. */
859 SetLastError(0xdeadbeef);
860 ret = pDeleteTimerQueueTimer(q, t1, NULL);
861 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
862 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
863 GetLastError());
865 SetLastError(0xdeadbeef);
866 ret = pDeleteTimerQueueTimer(q, t2, NULL);
867 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
868 ok(GetLastError() == ERROR_IO_PENDING,
869 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
870 GetLastError());
872 SetLastError(0xdeadbeef);
873 ret = pDeleteTimerQueueTimer(q, t3, et1);
874 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
875 ok(GetLastError() == 0xdeadbeef,
876 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
877 GetLastError());
878 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
879 "Timer destruction event not triggered\n");
881 SetLastError(0xdeadbeef);
882 ret = pDeleteTimerQueueTimer(q, t4, et2);
883 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
884 ok(GetLastError() == ERROR_IO_PENDING,
885 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
886 GetLastError());
887 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
888 "Timer destruction event not triggered\n");
890 SetLastError(0xdeadbeef);
891 ret = pDeleteTimerQueueEx(q, e);
892 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
893 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
894 GetLastError());
895 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
896 "Queue destruction event not triggered\n");
897 CloseHandle(e);
899 /* Test deleting/changing a timer in execution. */
900 q = pCreateTimerQueue();
901 ok(q != NULL, "CreateTimerQueue\n");
903 /* Test changing a once-only timer before it fires (this is allowed,
904 whereas after it fires you cannot). */
905 n1 = 0;
906 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
907 0, 0);
908 ok(ret, "CreateTimerQueueTimer\n");
909 ok(t1 != NULL, "CreateTimerQueueTimer\n");
910 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
911 ok(ret, "ChangeTimerQueueTimer\n");
913 d2.t = t2 = NULL;
914 d2.num_calls = 0;
915 d2.max_calls = 3;
916 d2.q = q;
917 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
918 10, 0);
919 d2.t = t2;
920 ok(ret, "CreateTimerQueueTimer\n");
921 ok(t2 != NULL, "CreateTimerQueueTimer\n");
923 d3.t = t3 = NULL;
924 d3.num_calls = 0;
925 d3.max_calls = 4;
926 d3.q = q;
927 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
928 10, 0);
929 d3.t = t3;
930 ok(ret, "CreateTimerQueueTimer\n");
931 ok(t3 != NULL, "CreateTimerQueueTimer\n");
933 d4.t = t4 = NULL;
934 d4.num_calls = 0;
935 d4.q = q;
936 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
937 0, 0);
938 d4.t = t4;
939 ok(ret, "CreateTimerQueueTimer\n");
940 ok(t4 != NULL, "CreateTimerQueueTimer\n");
942 Sleep(500);
944 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
945 ok(ret, "DeleteTimerQueueEx\n");
946 ok(n1 == 1, "ChangeTimerQueueTimer\n");
947 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
948 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
949 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
951 /* Test an obscure bug that was in the original implementation. */
952 q = pCreateTimerQueue();
953 ok(q != NULL, "CreateTimerQueue\n");
955 /* All the work is done in the callback. */
956 d1.t = t1 = NULL;
957 d1.num_calls = 0;
958 d1.q = q;
959 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
960 100, WT_EXECUTELONGFUNCTION);
961 d1.t = t1;
962 ok(ret, "CreateTimerQueueTimer\n");
963 ok(t1 != NULL, "CreateTimerQueueTimer\n");
965 Sleep(750);
967 SetLastError(0xdeadbeef);
968 ret = pDeleteTimerQueueEx(q, NULL);
969 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
970 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
971 GetLastError());
972 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
974 /* Test functions on the default timer queue. */
975 t1 = NULL;
976 n1 = 0;
977 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
978 1000, 0);
979 ok(ret, "CreateTimerQueueTimer, default queue\n");
980 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
982 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
983 ok(ret, "ChangeTimerQueueTimer, default queue\n");
985 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
986 ok(ret, "DeleteTimerQueueTimer, default queue\n");
988 /* Try mixing default and non-default queues. Apparently this works. */
989 q = pCreateTimerQueue();
990 ok(q != NULL, "CreateTimerQueue\n");
992 t1 = NULL;
993 n1 = 0;
994 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
995 1000, 0);
996 ok(ret, "CreateTimerQueueTimer\n");
997 ok(t1 != NULL, "CreateTimerQueueTimer\n");
999 t2 = NULL;
1000 n2 = 0;
1001 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
1002 1000, 0);
1003 ok(ret, "CreateTimerQueueTimer\n");
1004 ok(t2 != NULL, "CreateTimerQueueTimer\n");
1006 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1007 ok(ret, "ChangeTimerQueueTimer\n");
1009 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
1010 ok(ret, "ChangeTimerQueueTimer\n");
1012 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1013 ok(ret, "DeleteTimerQueueTimer\n");
1015 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1016 ok(ret, "DeleteTimerQueueTimer\n");
1018 /* Try to delete the default queue? In any case: not allowed. */
1019 SetLastError(0xdeadbeef);
1020 ret = pDeleteTimerQueueEx(NULL, NULL);
1021 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
1022 ok(GetLastError() == ERROR_INVALID_HANDLE,
1023 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1024 GetLastError());
1026 SetLastError(0xdeadbeef);
1027 ret = pDeleteTimerQueueEx(q, NULL);
1028 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1029 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1030 GetLastError());
1033 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1035 DWORD tmp = HandleToULong(handle);
1036 tmp |= modify;
1037 return ULongToHandle(tmp);
1040 static void test_WaitForSingleObject(void)
1042 HANDLE signaled, nonsignaled, invalid;
1043 DWORD ret;
1045 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1046 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1047 invalid = (HANDLE) 0xdeadbee0;
1049 /* invalid handle with different values for lower 2 bits */
1050 SetLastError(0xdeadbeef);
1051 ret = WaitForSingleObject(invalid, 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, 1), 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, 2), 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 SetLastError(0xdeadbeef);
1066 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1067 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1068 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1070 /* valid handle with different values for lower 2 bits */
1071 SetLastError(0xdeadbeef);
1072 ret = WaitForSingleObject(nonsignaled, 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, 1), 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, 2), 0);
1083 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1084 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1086 SetLastError(0xdeadbeef);
1087 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1088 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1089 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1091 /* valid handle with different values for lower 2 bits */
1092 SetLastError(0xdeadbeef);
1093 ret = WaitForSingleObject(signaled, 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, 1), 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, 2), 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 SetLastError(0xdeadbeef);
1108 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1109 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1110 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1112 CloseHandle(signaled);
1113 CloseHandle(nonsignaled);
1116 static void test_WaitForMultipleObjects(void)
1118 DWORD r;
1119 int i;
1120 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1122 /* create the maximum number of events and make sure
1123 * we can wait on that many */
1124 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1126 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1127 ok( maxevents[i] != 0, "should create enough events\n");
1130 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1131 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1132 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1133 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1134 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1135 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1136 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1138 /* the lowest index is checked first and remaining events are untouched */
1139 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1140 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1143 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1144 if (maxevents[i]) CloseHandle(maxevents[i]);
1147 static BOOL g_initcallback_ret, g_initcallback_called;
1148 static void *g_initctxt;
1150 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1152 g_initcallback_called = TRUE;
1153 /* zero bit set means here that initialization is taking place - initialization locked */
1154 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt);
1155 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr);
1156 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n");
1157 return g_initcallback_ret;
1160 static void test_initonce(void)
1162 INIT_ONCE initonce;
1163 BOOL ret, pending;
1165 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1167 skip("one-time initialization API not supported\n");
1168 return;
1171 /* blocking initialization with callback */
1172 initonce.Ptr = (void*)0xdeadbeef;
1173 pInitOnceInitialize(&initonce);
1174 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1176 /* initialisation completed successfully */
1177 g_initcallback_ret = TRUE;
1178 g_initctxt = NULL;
1179 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1180 ok(ret, "got wrong ret value %d\n", ret);
1181 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1182 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1183 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1185 /* so it's been called already so won't be called again */
1186 g_initctxt = NULL;
1187 g_initcallback_called = FALSE;
1188 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1189 ok(ret, "got wrong ret value %d\n", ret);
1190 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr);
1191 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1192 ok(!g_initcallback_called, "got %d\n", g_initcallback_called);
1194 pInitOnceInitialize(&initonce);
1195 g_initcallback_called = FALSE;
1196 /* 2 lower order bits should never be used, you'll get a crash in result */
1197 g_initctxt = (void*)0xFFFFFFF0;
1198 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1199 ok(ret, "got wrong ret value %d\n", ret);
1200 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr);
1201 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt);
1202 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1204 /* callback failed */
1205 g_initcallback_ret = FALSE;
1206 g_initcallback_called = FALSE;
1207 g_initctxt = NULL;
1208 pInitOnceInitialize(&initonce);
1209 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt);
1210 ok(!ret, "got wrong ret value %d\n", ret);
1211 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1212 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1213 ok(g_initcallback_called, "got %d\n", g_initcallback_called);
1215 /* blocking initialzation without a callback */
1216 pInitOnceInitialize(&initonce);
1217 g_initctxt = NULL;
1218 pending = FALSE;
1219 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt);
1220 ok(ret, "got wrong ret value %d\n", ret);
1221 ok(pending, "got %d\n", pending);
1222 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1223 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1224 /* another attempt to begin initialization with block a single thread */
1226 g_initctxt = NULL;
1227 pending = 0xf;
1228 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt);
1229 ok(!ret, "got wrong ret value %d\n", ret);
1230 ok(pending == 0xf, "got %d\n", pending);
1231 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1232 ok(g_initctxt == NULL, "got %p\n", g_initctxt);
1234 g_initctxt = (void*)0xdeadbee0;
1235 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt);
1236 ok(!ret, "got wrong ret value %d\n", ret);
1237 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr);
1239 /* once failed already */
1240 g_initctxt = (void*)0xdeadbee0;
1241 ret = pInitOnceComplete(&initonce, 0, g_initctxt);
1242 ok(ret, "got wrong ret value %d\n", ret);
1243 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr);
1246 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT;
1247 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT;
1248 static CRITICAL_SECTION buffercrit;
1249 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1250 static LONG bufferlen,totalproduced,totalconsumed;
1251 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1253 #define BUFFER_SIZE 5
1255 static DWORD WINAPI condvar_producer(LPVOID x) {
1256 DWORD sleepinterval = 5;
1258 while (1) {
1259 Sleep(sleepinterval);
1260 if (sleepinterval > 1)
1261 sleepinterval -= 1;
1263 EnterCriticalSection(&buffercrit);
1264 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1265 condvar_producer_sleepcnt++;
1266 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) {
1267 if (GetLastError() != ERROR_TIMEOUT)
1268 condvar_sleeperr = TRUE;
1271 if (condvar_stop) {
1272 LeaveCriticalSection(&buffercrit);
1273 break;
1275 bufferlen++;
1276 totalproduced++;
1277 LeaveCriticalSection(&buffercrit);
1278 pWakeConditionVariable(&buffernotempty);
1280 return 0;
1283 static DWORD WINAPI condvar_consumer(LPVOID x) {
1284 DWORD *cnt = (DWORD*)x;
1285 DWORD sleepinterval = 1;
1287 while (1) {
1288 EnterCriticalSection(&buffercrit);
1289 while ((bufferlen == 0) && !condvar_stop) {
1290 condvar_consumer_sleepcnt++;
1291 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) {
1292 if (GetLastError() != ERROR_TIMEOUT)
1293 condvar_sleeperr = TRUE;
1296 if (condvar_stop && (bufferlen == 0)) {
1297 LeaveCriticalSection(&buffercrit);
1298 break;
1300 bufferlen--;
1301 totalconsumed++;
1302 (*cnt)++;
1303 LeaveCriticalSection(&buffercrit);
1304 pWakeConditionVariable(&buffernotfull);
1305 Sleep(sleepinterval);
1306 if (sleepinterval < 5) sleepinterval += 1;
1308 return 0;
1311 static void test_condvars_consumer_producer(void)
1313 HANDLE hp1,hp2,hp3,hc1,hc2,hc3;
1314 DWORD dummy;
1315 DWORD cnt1,cnt2,cnt3;
1317 if (!pInitializeConditionVariable) {
1318 /* function is not yet in XP, only in newer Windows */
1319 /* and not yet implemented in Wine for some days/weeks */
1320 todo_wine win_skip("no condition variable support.\n");
1321 return;
1324 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1326 /* If we have static initialized condition variables, InitializeConditionVariable
1327 * is not strictly necessary.
1328 * pInitializeConditionVariable(&buffernotfull);
1330 pInitializeConditionVariable(&buffernotempty);
1331 InitializeCriticalSection(&buffercrit);
1333 /* Larger Test: consumer/producer example */
1335 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0;
1337 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1338 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1339 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1340 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1341 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1342 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy);
1344 /* Limit run to 0.5 seconds. */
1345 Sleep(500);
1347 /* tear down start */
1348 condvar_stop = TRUE;
1350 /* final wake up call */
1351 pWakeAllConditionVariable (&buffernotfull);
1352 pWakeAllConditionVariable (&buffernotempty);
1354 /* (mostly an implementation detail)
1355 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr);
1358 WaitForSingleObject(hp1, 1000);
1359 WaitForSingleObject(hp2, 1000);
1360 WaitForSingleObject(hp3, 1000);
1361 WaitForSingleObject(hc1, 1000);
1362 WaitForSingleObject(hc2, 1000);
1363 WaitForSingleObject(hc3, 1000);
1365 ok(totalconsumed == totalproduced,
1366 "consumed %d != produced %d\n", totalconsumed, totalproduced);
1367 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1369 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1370 * one consumer does not get anything to do is possible. */
1371 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced, cnt1, cnt2, cnt3);
1372 /* The sleeps of the producer or consumer should not go above 100* produced count,
1373 * otherwise the implementation does not sleep correctly. But yet again, this is
1374 * not hard defined. */
1375 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1378 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */
1379 static DWORD condvar_seq = 0;
1380 static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT;
1381 static CRITICAL_SECTION condvar_crit;
1383 /* Sequence of wake/sleep to check boundary conditions:
1384 * 0: init
1385 * 1: producer emits a WakeConditionVaribale without consumer waiting.
1386 * 2: consumer sleeps without a wake expecting timeout
1387 * 3: producer emits a WakeAllConditionVaribale without consumer waiting.
1388 * 4: consumer sleeps without a wake expecting timeout
1389 * 5: a wake is handed to a SleepConditionVariableCS
1390 * 6: a wakeall is handed to a SleepConditionVariableCS
1391 * 7: sleep after above should timeout
1392 * 8: wake with crit section locked into the sleep timeout
1393 * 9: end
1395 static DWORD WINAPI condvar_base_producer(LPVOID x) {
1396 while (condvar_seq < 1) Sleep(1);
1398 pWakeConditionVariable (&condvar_base);
1399 condvar_seq = 2;
1401 while (condvar_seq < 3) Sleep(1);
1402 pWakeAllConditionVariable (&condvar_base);
1403 condvar_seq = 4;
1405 while (condvar_seq < 5) Sleep(1);
1406 EnterCriticalSection (&condvar_crit);
1407 pWakeConditionVariable (&condvar_base);
1408 LeaveCriticalSection (&condvar_crit);
1409 while (condvar_seq < 6) Sleep(1);
1410 EnterCriticalSection (&condvar_crit);
1411 pWakeAllConditionVariable (&condvar_base);
1412 LeaveCriticalSection (&condvar_crit);
1414 while (condvar_seq < 8) Sleep(1);
1415 EnterCriticalSection (&condvar_crit);
1416 pWakeConditionVariable (&condvar_base);
1417 Sleep(50);
1418 LeaveCriticalSection (&condvar_crit);
1420 return 0;
1423 static DWORD WINAPI condvar_base_consumer(LPVOID x) {
1424 BOOL ret;
1426 while (condvar_seq < 2) Sleep(1);
1428 /* wake was emitted, but we were not sleeping */
1429 EnterCriticalSection (&condvar_crit);
1430 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1431 LeaveCriticalSection (&condvar_crit);
1432 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1433 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1435 condvar_seq = 3;
1436 while (condvar_seq < 4) Sleep(1);
1438 /* wake all was emitted, but we were not sleeping */
1439 EnterCriticalSection (&condvar_crit);
1440 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1441 LeaveCriticalSection (&condvar_crit);
1442 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1443 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1445 EnterCriticalSection (&condvar_crit);
1446 condvar_seq = 5;
1447 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1448 LeaveCriticalSection (&condvar_crit);
1449 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n");
1451 EnterCriticalSection (&condvar_crit);
1452 condvar_seq = 6;
1453 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200);
1454 LeaveCriticalSection (&condvar_crit);
1455 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n");
1456 condvar_seq = 7;
1458 EnterCriticalSection (&condvar_crit);
1459 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1460 LeaveCriticalSection (&condvar_crit);
1461 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n");
1462 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError());
1464 EnterCriticalSection (&condvar_crit);
1465 condvar_seq = 8;
1466 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20);
1467 LeaveCriticalSection (&condvar_crit);
1468 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n");
1469 condvar_seq = 9;
1471 return 0;
1474 static void test_condvars_base(void) {
1475 HANDLE hp, hc;
1476 DWORD dummy;
1477 BOOL ret;
1480 if (!pInitializeConditionVariable) {
1481 /* function is not yet in XP, only in newer Windows */
1482 /* and not yet implemented in Wine for some days/weeks */
1483 todo_wine win_skip("no condition variable support.\n");
1484 return;
1487 InitializeCriticalSection (&condvar_crit);
1489 EnterCriticalSection (&condvar_crit);
1490 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10);
1491 LeaveCriticalSection (&condvar_crit);
1493 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n");
1494 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError());
1497 hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy);
1498 hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy);
1500 condvar_seq = 1; /* go */
1502 while (condvar_seq < 9)
1503 Sleep (5);
1504 WaitForSingleObject(hp, 100);
1505 WaitForSingleObject(hc, 100);
1509 START_TEST(sync)
1511 HMODULE hdll = GetModuleHandle("kernel32");
1512 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1513 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1514 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1515 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1516 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1517 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1518 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1519 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1520 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1521 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
1522 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
1523 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
1524 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
1525 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
1526 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
1527 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
1528 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
1530 test_signalandwait();
1531 test_mutex();
1532 test_slist();
1533 test_event();
1534 test_semaphore();
1535 test_waitable_timer();
1536 test_iocp_callback();
1537 test_timer_queue();
1538 test_WaitForSingleObject();
1539 test_WaitForMultipleObjects();
1540 test_initonce();
1541 test_condvars_base();
1542 test_condvars_consumer_producer();