[KERNEL32_WINETEST]: Sync with Wine 1.5.19.
[reactos.git] / rostests / winetests / kernel32 / sync.c
1 /*
2 * Synchronization tests
3 *
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define _WIN32_WINNT 0x600
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windef.h>
26 #include <winbase.h>
27
28 #include "wine/test.h"
29
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);
44
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);
49
50 static void test_signalandwait(void)
51 {
52 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
53 HMODULE kernel32;
54 DWORD r;
55 HANDLE event[2], semaphore[2], file;
56
57 kernel32 = GetModuleHandle("kernel32");
58 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
59
60 if (!pSignalObjectAndWait)
61 return;
62
63 /* invalid parameters */
64 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
65 if (r == ERROR_INVALID_FUNCTION)
66 {
67 win_skip("SignalObjectAndWait is not implemented\n");
68 return; /* Win98/ME */
69 }
70 ok( r == WAIT_FAILED, "should fail\n");
71
72 event[0] = CreateEvent(NULL, 0, 0, NULL);
73 event[1] = CreateEvent(NULL, 1, 1, NULL);
74
75 ok( event[0] && event[1], "failed to create event flags\n");
76
77 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
78 ok( r == WAIT_FAILED, "should fail\n");
79
80 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
81 ok( r == WAIT_FAILED, "should fail\n");
82
83
84 /* valid parameters */
85 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
86 ok( r == WAIT_OBJECT_0, "should succeed\n");
87
88 /* event[0] is now signalled */
89 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
90 ok( r == WAIT_OBJECT_0, "should succeed\n");
91
92 /* event[0] is not signalled */
93 r = WaitForSingleObject(event[0], 0);
94 ok( r == WAIT_TIMEOUT, "event was signalled\n");
95
96 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
97 ok( r == WAIT_OBJECT_0, "should succeed\n");
98
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");
103
104 CloseHandle(event[0]);
105 CloseHandle(event[1]);
106
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");
111
112 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
113 ok( r == WAIT_OBJECT_0, "should succeed\n");
114
115 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
116 ok( r == WAIT_FAILED, "should fail\n");
117
118 r = ReleaseSemaphore(semaphore[0],1,NULL);
119 ok( r == FALSE, "should fail\n");
120
121 r = ReleaseSemaphore(semaphore[1],1,NULL);
122 ok( r == TRUE, "should succeed\n");
123
124 CloseHandle(semaphore[0]);
125 CloseHandle(semaphore[1]);
126
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);
134 }
135
136 static void test_mutex(void)
137 {
138 DWORD wait_ret;
139 BOOL ret;
140 HANDLE hCreated;
141 HANDLE hOpened;
142 int i;
143 DWORD failed = 0;
144
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());
149
150 SetLastError(0xdeadbeef);
151 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
152 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
153
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());
160
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);
167
168 for(i=0; i < 31; i++)
169 {
170 wait_ret = WaitForSingleObject(hCreated, INFINITE);
171 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
172 }
173
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);
180
181 for (i = 0; i < 32; i++)
182 {
183 SetLastError(0xdeadbeef);
184 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
185 if(hOpened != NULL)
186 {
187 SetLastError(0xdeadbeef);
188 ret = ReleaseMutex(hOpened);
189 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
190 CloseHandle(hOpened);
191 }
192 else
193 {
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;
200 }
201 }
202
203 todo_wine
204 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
205
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());
210
211 /* test case sensitivity */
212
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());
217
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());
222
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);
228
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);
234
235 CloseHandle(hCreated);
236 }
237
238 static void test_slist(void)
239 {
240 struct item
241 {
242 SLIST_ENTRY entry;
243 int value;
244 } item1, item2, item3, *pitem;
245
246 SLIST_HEADER slist_header;
247 PSLIST_ENTRY entry;
248 USHORT size;
249
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;
256
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)
268 {
269 win_skip("some required slist entrypoints were not found, skipping tests\n");
270 return;
271 }
272
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);
277
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);
283
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)
288 {
289 pitem = (struct item*) entry;
290 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
291 }
292 size = pQueryDepthSList(&slist_header);
293 ok(size == 2, "slist with 2 items has size %d\n", size);
294
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)
299 {
300 pitem = (struct item*) entry;
301 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
302 }
303 size = pQueryDepthSList(&slist_header);
304 ok(size == 3, "slist with 3 items has size %d\n", size);
305
306 entry = pInterlockedPopEntrySList(&slist_header);
307 ok(entry != NULL, "entry shouldn't be NULL\n");
308 if (entry != NULL)
309 {
310 pitem = (struct item*) entry;
311 ok(pitem->value == 3, "unexpected entry removed\n");
312 }
313 size = pQueryDepthSList(&slist_header);
314 ok(size == 2, "slist with 2 items has size %d\n", size);
315
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)
320 {
321 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
322 "popping empty slist didn't return NULL\n");
323 }
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");
326 }
327
328 static void test_event(void)
329 {
330 HANDLE handle, handle2;
331 SECURITY_ATTRIBUTES sa;
332 SECURITY_DESCRIPTOR sd;
333 ACL acl;
334 DWORD ret;
335 BOOL val;
336
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);
341
342 sa.nLength = sizeof(sa);
343 sa.lpSecurityDescriptor = &sd;
344 sa.bInheritHandle = FALSE;
345
346 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
347
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);
352
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);
358
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);
365
366 /* test case sensitivity */
367
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());
372
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 );
378
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 );
384
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 );
389
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());
394
395 CloseHandle( handle );
396
397 /* resource notifications are events too */
398
399 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
400 {
401 trace( "memory resource notifications not supported\n" );
402 return;
403 }
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() );
410
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 );
415
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() );
422
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 );
429 }
430
431 static void test_semaphore(void)
432 {
433 HANDLE handle, handle2;
434
435 /* test case sensitivity */
436
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());
441
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 );
447
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 );
453
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 );
458
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());
463
464 CloseHandle( handle );
465 }
466
467 static void test_waitable_timer(void)
468 {
469 HANDLE handle, handle2;
470
471 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
472 {
473 win_skip("{Create,Open}WaitableTimerA() is not available\n");
474 return;
475 }
476
477 /* test case sensitivity */
478
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());
483
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 );
489
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 );
495
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 );
500
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());
507
508 CloseHandle( handle );
509 }
510
511 static HANDLE sem = 0;
512
513 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
514 {
515 ReleaseSemaphore(sem, 1, NULL);
516 }
517
518 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
519
520 static void test_iocp_callback(void)
521 {
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;
532
533 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
534 if(!p_BindIoCompletionCallback) {
535 win_skip("BindIoCompletionCallback not found in this DLL\n");
536 return;
537 }
538
539 sem = CreateSemaphore(NULL, 0, 1, NULL);
540 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
541
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");
545
546 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
547 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
548
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());
552
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());
556
557 ret = CloseHandle(hFile);
558 ok( ret, "CloseHandle: error %d\n", GetLastError());
559 ret = DeleteFileA(filename);
560 ok( ret, "DeleteFileA: error %d\n", GetLastError());
561
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());
565
566 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
567 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
568
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());
572
573 ret = WaitForSingleObject(sem, 5000);
574 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
575 CloseHandle(sem);
576
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());
583
584 ret = CloseHandle(hFile);
585 ok( ret, "CloseHandle: error %d\n", GetLastError());
586 ret = DeleteFileA(filename);
587 ok( ret, "DeleteFileA: error %d\n", GetLastError());
588
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());
604
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());
610 }
611
612 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
613 {
614 int *pn = p;
615 ok(timedOut, "Timer callbacks should always time out\n");
616 ++*pn;
617 }
618
619 struct timer_queue_data1
620 {
621 int num_calls;
622 int max_calls;
623 HANDLE q, t;
624 };
625
626 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
627 {
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)
631 {
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");
639 }
640 }
641
642 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
643 {
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)
647 {
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");
652 }
653 }
654
655 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
656 {
657 struct timer_queue_data1 *d = p;
658 ok(timedOut, "Timer callbacks should always time out\n");
659 if (d->t)
660 {
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;
669 }
670 }
671
672 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
673 {
674 DWORD_PTR delay = (DWORD_PTR) p;
675 ok(timedOut, "Timer callbacks should always time out\n");
676 if (delay)
677 Sleep(delay);
678 }
679
680 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
681 {
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)
687 {
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;
695
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");
701
702 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
703 ok(ret, "CreateTimerQueueTimer\n");
704 ok(t != NULL, "CreateTimerQueueTimer\n");
705
706 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
707 ok(ret, "DeleteTimerQueueTimer\n");
708
709 /* Now we stay alive by hanging around in the callback. */
710 Sleep(500);
711 }
712 }
713
714 static void test_timer_queue(void)
715 {
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;
721
722 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
723 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
724 {
725 win_skip("TimerQueue API not present\n");
726 return;
727 }
728
729 /* Test asynchronous deletion of the queue. */
730 q = pCreateTimerQueue();
731 ok(q != NULL, "CreateTimerQueue\n");
732
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());
738
739 /* Test synchronous deletion of the queue and running timers. */
740 q = pCreateTimerQueue();
741 ok(q != NULL, "CreateTimerQueue\n");
742
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());
754
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");
762
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");
770
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");
778
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");
786
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");
794
795 /* Give them a chance to do some work. */
796 Sleep(500);
797
798 /* Test deleting a once-only timer. */
799 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
800 ok(ret, "DeleteTimerQueueTimer\n");
801
802 /* A periodic timer. */
803 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
804 ok(ret, "DeleteTimerQueueTimer\n");
805
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);
814
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)
820 {
821 skip("Failed to create timer queue descruction event\n");
822 return;
823 }
824
825 q = pCreateTimerQueue();
826 ok(q != NULL, "CreateTimerQueue\n");
827
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");
833
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");
840
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");
846
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");
853
854 /* Give them a chance to start. */
855 Sleep(400);
856
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());
864
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());
871
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");
880
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");
889
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);
898
899 /* Test deleting/changing a timer in execution. */
900 q = pCreateTimerQueue();
901 ok(q != NULL, "CreateTimerQueue\n");
902
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");
912
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");
922
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");
932
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");
941
942 Sleep(500);
943
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");
950
951 /* Test an obscure bug that was in the original implementation. */
952 q = pCreateTimerQueue();
953 ok(q != NULL, "CreateTimerQueue\n");
954
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");
964
965 Sleep(750);
966
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");
973
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");
981
982 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
983 ok(ret, "ChangeTimerQueueTimer, default queue\n");
984
985 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
986 ok(ret, "DeleteTimerQueueTimer, default queue\n");
987
988 /* Try mixing default and non-default queues. Apparently this works. */
989 q = pCreateTimerQueue();
990 ok(q != NULL, "CreateTimerQueue\n");
991
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");
998
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");
1005
1006 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
1007 ok(ret, "ChangeTimerQueueTimer\n");
1008
1009 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
1010 ok(ret, "ChangeTimerQueueTimer\n");
1011
1012 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
1013 ok(ret, "DeleteTimerQueueTimer\n");
1014
1015 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
1016 ok(ret, "DeleteTimerQueueTimer\n");
1017
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());
1025
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());
1031 }
1032
1033 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1034 {
1035 DWORD tmp = HandleToULong(handle);
1036 tmp |= modify;
1037 return ULongToHandle(tmp);
1038 }
1039
1040 static void test_WaitForSingleObject(void)
1041 {
1042 HANDLE signaled, nonsignaled, invalid;
1043 DWORD ret;
1044
1045 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1046 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1047 invalid = (HANDLE) 0xdeadbee0;
1048
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());
1054
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());
1059
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());
1064
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());
1069
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());
1075
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());
1080
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());
1085
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());
1090
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());
1096
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());
1101
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());
1106
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());
1111
1112 CloseHandle(signaled);
1113 CloseHandle(nonsignaled);
1114 }
1115
1116 static void test_WaitForMultipleObjects(void)
1117 {
1118 DWORD r;
1119 int i;
1120 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1121
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++)
1125 {
1126 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1127 ok( maxevents[i] != 0, "should create enough events\n");
1128 }
1129
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++)
1137 {
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);
1141 }
1142
1143 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1144 if (maxevents[i]) CloseHandle(maxevents[i]);
1145 }
1146
1147 static BOOL g_initcallback_ret, g_initcallback_called;
1148 static void *g_initctxt;
1149
1150 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt)
1151 {
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;
1158 }
1159
1160 static void test_initonce(void)
1161 {
1162 INIT_ONCE initonce;
1163 BOOL ret, pending;
1164
1165 if (!pInitOnceInitialize || !pInitOnceExecuteOnce)
1166 {
1167 skip("one-time initialization API not supported\n");
1168 return;
1169 }
1170
1171 /* blocking initialization with callback */
1172 initonce.Ptr = (void*)0xdeadbeef;
1173 pInitOnceInitialize(&initonce);
1174 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr);
1175
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);
1184
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);
1193
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);
1203
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);
1214
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 */
1225
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);
1233
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);
1238
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);
1244 }
1245
1246 static CONDITION_VARIABLE buffernotempty,buffernotfull;
1247 static CRITICAL_SECTION buffercrit;
1248 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE;
1249 static LONG bufferlen,totalproduced,totalconsumed;
1250 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt;
1251
1252 #define BUFFER_SIZE 10
1253
1254 static DWORD WINAPI condvar_producer(LPVOID x) {
1255 while (1) {
1256 Sleep(rand() % 10);
1257
1258 EnterCriticalSection(&buffercrit);
1259 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) {
1260 condvar_producer_sleepcnt++;
1261 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, 2000))
1262 condvar_sleeperr = TRUE;
1263 }
1264 if (condvar_stop) {
1265 LeaveCriticalSection(&buffercrit);
1266 break;
1267 }
1268 bufferlen++;
1269 totalproduced++;
1270 LeaveCriticalSection(&buffercrit);
1271 pWakeConditionVariable(&buffernotempty);
1272 }
1273 return 0;
1274 }
1275
1276 static DWORD WINAPI condvar_consumer(LPVOID x) {
1277 DWORD *cnt = (DWORD*)x;
1278
1279 while (1) {
1280 EnterCriticalSection(&buffercrit);
1281 while ((bufferlen == 0) && !condvar_stop) {
1282 condvar_consumer_sleepcnt++;
1283 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, 2000))
1284 condvar_sleeperr = TRUE;
1285 }
1286 if (condvar_stop && (bufferlen == 0)) {
1287 LeaveCriticalSection(&buffercrit);
1288 break;
1289 }
1290 bufferlen--;
1291 totalconsumed++;
1292 (*cnt)++;
1293 LeaveCriticalSection(&buffercrit);
1294 pWakeConditionVariable(&buffernotfull);
1295 Sleep(rand() % 10);
1296 }
1297 return 0;
1298 }
1299
1300 static void test_condvars(void)
1301 {
1302 HANDLE hp1,hp2,hc1,hc2;
1303 DWORD dummy;
1304 DWORD cnt1,cnt2;
1305
1306 if (!pInitializeConditionVariable) {
1307 /* function is not yet in XP, only in newer Windows */
1308 /* and not yet implemented in Wine for some days/weeks */
1309 todo_wine win_skip("no condition variable support.\n");
1310 return;
1311 }
1312
1313 /* Implement a producer / consumer scheme with non-full / non-empty triggers */
1314 pInitializeConditionVariable(&buffernotfull);
1315 pInitializeConditionVariable(&buffernotempty);
1316 InitializeCriticalSection(&buffercrit);
1317 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = 0;
1318
1319 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1320 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy);
1321 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy);
1322 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy);
1323
1324 /* Limit run to 0.5 seconds. */
1325 Sleep(500);
1326
1327 /* tear down start */
1328 condvar_stop = TRUE;
1329
1330 /* final wake up call */
1331 pWakeAllConditionVariable (&buffernotfull);
1332 pWakeAllConditionVariable (&buffernotempty);
1333
1334 WaitForSingleObject(hp1, 1000);
1335 WaitForSingleObject(hp2, 1000);
1336 WaitForSingleObject(hc1, 1000);
1337 WaitForSingleObject(hc2, 1000);
1338
1339 ok(totalconsumed == totalproduced,
1340 "consumed %d != produced %d\n", totalconsumed, totalproduced);
1341 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n");
1342
1343 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where
1344 * one consumer does not get anything to do is possible. */
1345 trace("produced %d, c1 %d, c2 %d\n", totalproduced, cnt1, cnt2);
1346 /* The sleeps of the producer or consumer should not go above 100* produced count,
1347 * otherwise the implementation does not sleep correctly. But yet again, this is
1348 * not hard defined. */
1349 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt);
1350 }
1351
1352 START_TEST(sync)
1353 {
1354 HMODULE hdll = GetModuleHandle("kernel32");
1355 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1356 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1357 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1358 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1359 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1360 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1361 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1362 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1363 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1364 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize");
1365 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce");
1366 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize");
1367 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete");
1368 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable");
1369 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS");
1370 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable");
1371 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable");
1372
1373 test_signalandwait();
1374 test_mutex();
1375 test_slist();
1376 test_event();
1377 test_semaphore();
1378 test_waitable_timer();
1379 test_iocp_callback();
1380 test_timer_queue();
1381 test_WaitForSingleObject();
1382 test_WaitForMultipleObjects();
1383 test_initonce();
1384 test_condvars();
1385 }