[KERNEL32_WINETEST]
[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 0x502
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
41 static void test_signalandwait(void)
42 {
43 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
44 HMODULE kernel32;
45 DWORD r;
46 HANDLE event[2], semaphore[2], file;
47
48 kernel32 = GetModuleHandle("kernel32");
49 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
50
51 if (!pSignalObjectAndWait)
52 return;
53
54 /* invalid parameters */
55 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
56 if (r == ERROR_INVALID_FUNCTION)
57 {
58 win_skip("SignalObjectAndWait is not implemented\n");
59 return; /* Win98/ME */
60 }
61 ok( r == WAIT_FAILED, "should fail\n");
62
63 event[0] = CreateEvent(NULL, 0, 0, NULL);
64 event[1] = CreateEvent(NULL, 1, 1, NULL);
65
66 ok( event[0] && event[1], "failed to create event flags\n");
67
68 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
69 ok( r == WAIT_FAILED, "should fail\n");
70
71 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
72 ok( r == WAIT_FAILED, "should fail\n");
73
74
75 /* valid parameters */
76 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
77 ok( r == WAIT_OBJECT_0, "should succeed\n");
78
79 /* event[0] is now signalled */
80 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
81 ok( r == WAIT_OBJECT_0, "should succeed\n");
82
83 /* event[0] is not signalled */
84 r = WaitForSingleObject(event[0], 0);
85 ok( r == WAIT_TIMEOUT, "event was signalled\n");
86
87 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
88 ok( r == WAIT_OBJECT_0, "should succeed\n");
89
90 /* clear event[1] and check for a timeout */
91 ok(ResetEvent(event[1]), "failed to clear event[1]\n");
92 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
93 ok( r == WAIT_TIMEOUT, "should timeout\n");
94
95 CloseHandle(event[0]);
96 CloseHandle(event[1]);
97
98 /* semaphores */
99 semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
100 semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
101 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
102
103 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
104 ok( r == WAIT_OBJECT_0, "should succeed\n");
105
106 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
107 ok( r == WAIT_FAILED, "should fail\n");
108
109 r = ReleaseSemaphore(semaphore[0],1,NULL);
110 ok( r == FALSE, "should fail\n");
111
112 r = ReleaseSemaphore(semaphore[1],1,NULL);
113 ok( r == TRUE, "should succeed\n");
114
115 CloseHandle(semaphore[0]);
116 CloseHandle(semaphore[1]);
117
118 /* try a registry key */
119 file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
120 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
121 r = pSignalObjectAndWait(file, file, 0, FALSE);
122 ok( r == WAIT_FAILED, "should fail\n");
123 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
124 CloseHandle(file);
125 }
126
127 static void test_mutex(void)
128 {
129 DWORD wait_ret;
130 BOOL ret;
131 HANDLE hCreated;
132 HANDLE hOpened;
133 int i;
134 DWORD failed = 0;
135
136 SetLastError(0xdeadbeef);
137 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
138 ok(hOpened == NULL, "OpenMutex succeeded\n");
139 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
140
141 SetLastError(0xdeadbeef);
142 hCreated = CreateMutex(NULL, FALSE, "WineTestMutex");
143 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError());
144
145 SetLastError(0xdeadbeef);
146 hOpened = OpenMutex(0, FALSE, "WineTestMutex");
147 todo_wine
148 ok(hOpened == NULL, "OpenMutex succeeded\n");
149 todo_wine
150 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError());
151
152 SetLastError(0xdeadbeef);
153 hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex");
154 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
155 wait_ret = WaitForSingleObject(hOpened, INFINITE);
156 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError());
157 CloseHandle(hOpened);
158
159 for(i=0; i < 31; i++)
160 {
161 wait_ret = WaitForSingleObject(hCreated, INFINITE);
162 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret);
163 }
164
165 SetLastError(0xdeadbeef);
166 hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex");
167 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError());
168 wait_ret = WaitForSingleObject(hOpened, INFINITE);
169 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n");
170 CloseHandle(hOpened);
171
172 for (i = 0; i < 32; i++)
173 {
174 SetLastError(0xdeadbeef);
175 hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex");
176 if(hOpened != NULL)
177 {
178 SetLastError(0xdeadbeef);
179 ret = ReleaseMutex(hOpened);
180 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i);
181 CloseHandle(hOpened);
182 }
183 else
184 {
185 if ((1 << i) == ACCESS_SYSTEM_SECURITY)
186 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i);
187 else
188 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i);
189 ReleaseMutex(hCreated);
190 failed |=0x1 << i;
191 }
192 }
193
194 todo_wine
195 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed);
196
197 SetLastError(0xdeadbeef);
198 ret = ReleaseMutex(hCreated);
199 ok(!ret && (GetLastError() == ERROR_NOT_OWNER),
200 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
201
202 /* test case sensitivity */
203
204 SetLastError(0xdeadbeef);
205 hOpened = OpenMutex(READ_CONTROL, FALSE, "WINETESTMUTEX");
206 ok(!hOpened, "OpenMutex succeeded\n");
207 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
208
209 SetLastError(0xdeadbeef);
210 hOpened = OpenMutex(READ_CONTROL, FALSE, "winetestmutex");
211 ok(!hOpened, "OpenMutex succeeded\n");
212 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
213
214 SetLastError(0xdeadbeef);
215 hOpened = CreateMutex(NULL, FALSE, "WineTestMutex");
216 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
217 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
218 CloseHandle(hOpened);
219
220 SetLastError(0xdeadbeef);
221 hOpened = CreateMutex(NULL, FALSE, "WINETESTMUTEX");
222 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError());
223 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
224 CloseHandle(hOpened);
225
226 CloseHandle(hCreated);
227 }
228
229 static void test_slist(void)
230 {
231 struct item
232 {
233 SLIST_ENTRY entry;
234 int value;
235 } item1, item2, item3, *pitem;
236
237 SLIST_HEADER slist_header;
238 PSLIST_ENTRY entry;
239 USHORT size;
240
241 VOID (WINAPI *pInitializeSListHead)(PSLIST_HEADER);
242 USHORT (WINAPI *pQueryDepthSList)(PSLIST_HEADER);
243 PSLIST_ENTRY (WINAPI *pInterlockedFlushSList)(PSLIST_HEADER);
244 PSLIST_ENTRY (WINAPI *pInterlockedPopEntrySList)(PSLIST_HEADER);
245 PSLIST_ENTRY (WINAPI *pInterlockedPushEntrySList)(PSLIST_HEADER,PSLIST_ENTRY);
246 HMODULE kernel32;
247
248 kernel32 = GetModuleHandle("KERNEL32.DLL");
249 pInitializeSListHead = (void*) GetProcAddress(kernel32, "InitializeSListHead");
250 pQueryDepthSList = (void*) GetProcAddress(kernel32, "QueryDepthSList");
251 pInterlockedFlushSList = (void*) GetProcAddress(kernel32, "InterlockedFlushSList");
252 pInterlockedPopEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPopEntrySList");
253 pInterlockedPushEntrySList = (void*) GetProcAddress(kernel32, "InterlockedPushEntrySList");
254 if (pInitializeSListHead == NULL ||
255 pQueryDepthSList == NULL ||
256 pInterlockedFlushSList == NULL ||
257 pInterlockedPopEntrySList == NULL ||
258 pInterlockedPushEntrySList == NULL)
259 {
260 win_skip("some required slist entrypoints were not found, skipping tests\n");
261 return;
262 }
263
264 memset(&slist_header, 0xFF, sizeof(slist_header));
265 pInitializeSListHead(&slist_header);
266 size = pQueryDepthSList(&slist_header);
267 ok(size == 0, "initially created slist has size %d, expected 0\n", size);
268
269 item1.value = 1;
270 ok(pInterlockedPushEntrySList(&slist_header, &item1.entry) == NULL,
271 "previous entry in empty slist wasn't NULL\n");
272 size = pQueryDepthSList(&slist_header);
273 ok(size == 1, "slist with 1 item has size %d\n", size);
274
275 item2.value = 2;
276 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
277 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
278 if (entry != NULL)
279 {
280 pitem = (struct item*) entry;
281 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
282 }
283 size = pQueryDepthSList(&slist_header);
284 ok(size == 2, "slist with 2 items has size %d\n", size);
285
286 item3.value = 3;
287 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
288 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
289 if (entry != NULL)
290 {
291 pitem = (struct item*) entry;
292 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
293 }
294 size = pQueryDepthSList(&slist_header);
295 ok(size == 3, "slist with 3 items has size %d\n", size);
296
297 entry = pInterlockedPopEntrySList(&slist_header);
298 ok(entry != NULL, "entry shouldn't be NULL\n");
299 if (entry != NULL)
300 {
301 pitem = (struct item*) entry;
302 ok(pitem->value == 3, "unexpected entry removed\n");
303 }
304 size = pQueryDepthSList(&slist_header);
305 ok(size == 2, "slist with 2 items has size %d\n", size);
306
307 entry = pInterlockedFlushSList(&slist_header);
308 size = pQueryDepthSList(&slist_header);
309 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
310 if (size == 0)
311 {
312 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
313 "popping empty slist didn't return NULL\n");
314 }
315 ok(((struct item*)entry)->value == 2, "item 2 not in front of list\n");
316 ok(((struct item*)entry->Next)->value == 1, "item 1 not at the back of list\n");
317 }
318
319 static void test_event(void)
320 {
321 HANDLE handle, handle2;
322 SECURITY_ATTRIBUTES sa;
323 SECURITY_DESCRIPTOR sd;
324 ACL acl;
325 DWORD ret;
326 BOOL val;
327
328 /* no sd */
329 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
330 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
331 CloseHandle(handle);
332
333 sa.nLength = sizeof(sa);
334 sa.lpSecurityDescriptor = &sd;
335 sa.bInheritHandle = FALSE;
336
337 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
338
339 /* blank sd */
340 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
341 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
342 CloseHandle(handle);
343
344 /* sd with NULL dacl */
345 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
346 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
347 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
348 CloseHandle(handle);
349
350 /* sd with empty dacl */
351 InitializeAcl(&acl, sizeof(acl), ACL_REVISION);
352 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE);
353 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
354 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
355 CloseHandle(handle);
356
357 /* test case sensitivity */
358
359 SetLastError(0xdeadbeef);
360 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
361 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError());
362 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
363
364 SetLastError(0xdeadbeef);
365 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
366 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
367 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
368 CloseHandle( handle2 );
369
370 SetLastError(0xdeadbeef);
371 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT");
372 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError());
373 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
374 CloseHandle( handle2 );
375
376 SetLastError(0xdeadbeef);
377 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event");
378 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError());
379 CloseHandle( handle2 );
380
381 SetLastError(0xdeadbeef);
382 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT");
383 ok( !handle2, "OpenEvent succeeded\n");
384 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
385
386 CloseHandle( handle );
387
388 /* resource notifications are events too */
389
390 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification)
391 {
392 trace( "memory resource notifications not supported\n" );
393 return;
394 }
395 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 );
396 ok( !handle, "CreateMemoryResourceNotification succeeded\n" );
397 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
398 ret = pQueryMemoryResourceNotification( handle, &val );
399 ok( !ret, "QueryMemoryResourceNotification succeeded\n" );
400 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
401
402 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification );
403 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() );
404 ret = WaitForSingleObject( handle, 10 );
405 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret );
406
407 val = ~0;
408 ret = pQueryMemoryResourceNotification( handle, &val );
409 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
410 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
411 ret = CloseHandle( handle );
412 ok( ret, "CloseHandle failed err %u\n", GetLastError() );
413
414 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
415 val = ~0;
416 ret = pQueryMemoryResourceNotification( handle, &val );
417 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() );
418 ok( val == FALSE || val == TRUE, "wrong value %u\n", val );
419 CloseHandle( handle );
420 }
421
422 static void test_semaphore(void)
423 {
424 HANDLE handle, handle2;
425
426 /* test case sensitivity */
427
428 SetLastError(0xdeadbeef);
429 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
430 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError());
431 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
432
433 SetLastError(0xdeadbeef);
434 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore");
435 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
436 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
437 CloseHandle( handle2 );
438
439 SetLastError(0xdeadbeef);
440 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE");
441 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError());
442 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
443 CloseHandle( handle2 );
444
445 SetLastError(0xdeadbeef);
446 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore");
447 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError());
448 CloseHandle( handle2 );
449
450 SetLastError(0xdeadbeef);
451 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE");
452 ok( !handle2, "OpenSemaphore succeeded\n");
453 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError());
454
455 CloseHandle( handle );
456 }
457
458 static void test_waitable_timer(void)
459 {
460 HANDLE handle, handle2;
461
462 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
463 {
464 win_skip("{Create,Open}WaitableTimerA() is not available\n");
465 return;
466 }
467
468 /* test case sensitivity */
469
470 SetLastError(0xdeadbeef);
471 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
472 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError());
473 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
474
475 SetLastError(0xdeadbeef);
476 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer");
477 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
478 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError());
479 CloseHandle( handle2 );
480
481 SetLastError(0xdeadbeef);
482 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER");
483 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError());
484 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
485 CloseHandle( handle2 );
486
487 SetLastError(0xdeadbeef);
488 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer");
489 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError());
490 CloseHandle( handle2 );
491
492 SetLastError(0xdeadbeef);
493 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER");
494 ok( !handle2, "OpenWaitableTimer succeeded\n");
495 ok( GetLastError() == ERROR_FILE_NOT_FOUND ||
496 GetLastError() == ERROR_INVALID_NAME, /* win98 */
497 "wrong error %u\n", GetLastError());
498
499 CloseHandle( handle );
500 }
501
502 static HANDLE sem = 0;
503
504 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
505 {
506 ReleaseSemaphore(sem, 1, NULL);
507 }
508
509 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
510
511 static void test_iocp_callback(void)
512 {
513 char temp_path[MAX_PATH];
514 char filename[MAX_PATH];
515 DWORD ret;
516 BOOL retb;
517 static const char prefix[] = "pfx";
518 HANDLE hFile;
519 HMODULE hmod = GetModuleHandleA("kernel32.dll");
520 DWORD bytesWritten;
521 const char *buffer = "12345678123456781234567812345678";
522 OVERLAPPED overlapped;
523
524 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
525 if(!p_BindIoCompletionCallback) {
526 win_skip("BindIoCompletionCallback not found in this DLL\n");
527 return;
528 }
529
530 sem = CreateSemaphore(NULL, 0, 1, NULL);
531 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
532
533 ret = GetTempPathA(MAX_PATH, temp_path);
534 ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
535 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
536
537 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
538 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
539
540 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
541 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
542 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
543
544 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
545 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
546 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
547
548 ret = CloseHandle(hFile);
549 ok( ret, "CloseHandle: error %d\n", GetLastError());
550 ret = DeleteFileA(filename);
551 ok( ret, "DeleteFileA: error %d\n", GetLastError());
552
553 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
554 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
555 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
556
557 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
558 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
559
560 memset(&overlapped, 0, sizeof(overlapped));
561 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
562 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
563
564 ret = WaitForSingleObject(sem, 5000);
565 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
566 CloseHandle(sem);
567
568 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
569 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
570 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
571 retb = p_BindIoCompletionCallback(hFile, NULL, 0);
572 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
573 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError());
574
575 ret = CloseHandle(hFile);
576 ok( ret, "CloseHandle: error %d\n", GetLastError());
577 ret = DeleteFileA(filename);
578 ok( ret, "DeleteFileA: error %d\n", GetLastError());
579
580 /* win2k3 requires the Flags parameter to be zero */
581 SetLastError(0xdeadbeef);
582 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
583 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0);
584 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError());
585 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345);
586 if (!retb)
587 ok(GetLastError() == ERROR_INVALID_PARAMETER,
588 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
589 else
590 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n");
591 ret = CloseHandle(hFile);
592 ok( ret, "CloseHandle: error %d\n", GetLastError());
593 ret = DeleteFileA(filename);
594 ok( ret, "DeleteFileA: error %d\n", GetLastError());
595
596 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0);
597 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n");
598 ok(GetLastError() == ERROR_INVALID_HANDLE ||
599 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */
600 "Last error is %d\n", GetLastError());
601 }
602
603 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
604 {
605 int *pn = p;
606 ok(timedOut, "Timer callbacks should always time out\n");
607 ++*pn;
608 }
609
610 struct timer_queue_data1
611 {
612 int num_calls;
613 int max_calls;
614 HANDLE q, t;
615 };
616
617 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
618 {
619 struct timer_queue_data1 *d = p;
620 ok(timedOut, "Timer callbacks should always time out\n");
621 if (d->t && ++d->num_calls == d->max_calls)
622 {
623 BOOL ret;
624 SetLastError(0xdeadbeef);
625 /* Note, XP SP2 does *not* do any deadlock checking, so passing
626 INVALID_HANDLE_VALUE here will just hang. */
627 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
628 ok(!ret, "DeleteTimerQueueTimer\n");
629 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
630 }
631 }
632
633 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
634 {
635 struct timer_queue_data1 *d = p;
636 ok(timedOut, "Timer callbacks should always time out\n");
637 if (d->t && ++d->num_calls == d->max_calls)
638 {
639 /* Basically kill the timer since it won't have time to run
640 again. */
641 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
642 ok(ret, "ChangeTimerQueueTimer\n");
643 }
644 }
645
646 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
647 {
648 struct timer_queue_data1 *d = p;
649 ok(timedOut, "Timer callbacks should always time out\n");
650 if (d->t)
651 {
652 /* This tests whether a timer gets flagged for deletion before
653 or after the callback runs. If we start this timer with a
654 period of zero (run once), then ChangeTimerQueueTimer will
655 fail if the timer is already flagged. Hence we really run
656 only once. Otherwise we will run multiple times. */
657 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50);
658 ok(ret, "ChangeTimerQueueTimer\n");
659 ++d->num_calls;
660 }
661 }
662
663 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
664 {
665 DWORD_PTR delay = (DWORD_PTR) p;
666 ok(timedOut, "Timer callbacks should always time out\n");
667 if (delay)
668 Sleep(delay);
669 }
670
671 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
672 {
673 struct timer_queue_data1 *d = p;
674 ok(timedOut, "Timer callbacks should always time out\n");
675 /* This tests an original implementation bug where a deleted timer may get
676 to run, but it is tricky to set up. */
677 if (d->q && d->num_calls++ == 0)
678 {
679 /* First run: delete ourselves, then insert and remove a timer
680 that goes in front of us in the sorted timeout list. Once
681 removed, we will still timeout at the faster timer's due time,
682 but this should be a no-op if we are bug-free. There should
683 not be a second run. We can test the value of num_calls later. */
684 BOOL ret;
685 HANDLE t;
686
687 /* The delete will pend while we are in this callback. */
688 SetLastError(0xdeadbeef);
689 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
690 ok(!ret, "DeleteTimerQueueTimer\n");
691 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
692
693 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
694 ok(ret, "CreateTimerQueueTimer\n");
695 ok(t != NULL, "CreateTimerQueueTimer\n");
696
697 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
698 ok(ret, "DeleteTimerQueueTimer\n");
699
700 /* Now we stay alive by hanging around in the callback. */
701 Sleep(500);
702 }
703 }
704
705 static void test_timer_queue(void)
706 {
707 HANDLE q, t1, t2, t3, t4, t5;
708 int n1, n2, n3, n4, n5;
709 struct timer_queue_data1 d1, d2, d3, d4;
710 HANDLE e, et1, et2;
711 BOOL ret;
712
713 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
714 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
715 {
716 win_skip("TimerQueue API not present\n");
717 return;
718 }
719
720 /* Test asynchronous deletion of the queue. */
721 q = pCreateTimerQueue();
722 ok(q != NULL, "CreateTimerQueue\n");
723
724 SetLastError(0xdeadbeef);
725 ret = pDeleteTimerQueueEx(q, NULL);
726 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
727 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
728 GetLastError());
729
730 /* Test synchronous deletion of the queue and running timers. */
731 q = pCreateTimerQueue();
732 ok(q != NULL, "CreateTimerQueue\n");
733
734 /* Called once. */
735 t1 = NULL;
736 n1 = 0;
737 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
738 0, 0);
739 ok(ret, "CreateTimerQueueTimer\n");
740 ok(t1 != NULL, "CreateTimerQueueTimer\n");
741
742 /* A slow one. */
743 t2 = NULL;
744 n2 = 0;
745 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
746 100, 0);
747 ok(ret, "CreateTimerQueueTimer\n");
748 ok(t2 != NULL, "CreateTimerQueueTimer\n");
749
750 /* A fast one. */
751 t3 = NULL;
752 n3 = 0;
753 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
754 10, 0);
755 ok(ret, "CreateTimerQueueTimer\n");
756 ok(t3 != NULL, "CreateTimerQueueTimer\n");
757
758 /* Start really late (it won't start). */
759 t4 = NULL;
760 n4 = 0;
761 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
762 10, 0);
763 ok(ret, "CreateTimerQueueTimer\n");
764 ok(t4 != NULL, "CreateTimerQueueTimer\n");
765
766 /* Start soon, but delay so long it won't run again. */
767 t5 = NULL;
768 n5 = 0;
769 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
770 10000, 0);
771 ok(ret, "CreateTimerQueueTimer\n");
772 ok(t5 != NULL, "CreateTimerQueueTimer\n");
773
774 /* Give them a chance to do some work. */
775 Sleep(500);
776
777 /* Test deleting a once-only timer. */
778 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
779 ok(ret, "DeleteTimerQueueTimer\n");
780
781 /* A periodic timer. */
782 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
783 ok(ret, "DeleteTimerQueueTimer\n");
784
785 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
786 ok(ret, "DeleteTimerQueueEx\n");
787 ok(n1 == 1, "Timer callback 1\n");
788 ok(n2 < n3, "Timer callback 2 should be much slower than 3\n");
789 ok(n4 == 0, "Timer callback 4\n");
790 ok(n5 == 1, "Timer callback 5\n");
791
792 /* Test synchronous deletion of the timer/queue with event trigger. */
793 e = CreateEvent(NULL, TRUE, FALSE, NULL);
794 et1 = CreateEvent(NULL, TRUE, FALSE, NULL);
795 et2 = CreateEvent(NULL, TRUE, FALSE, NULL);
796 if (!e || !et1 || !et2)
797 {
798 skip("Failed to create timer queue descruction event\n");
799 return;
800 }
801
802 q = pCreateTimerQueue();
803 ok(q != NULL, "CreateTimerQueue\n");
804
805 /* Run once and finish quickly (should be done when we delete it). */
806 t1 = NULL;
807 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
808 ok(ret, "CreateTimerQueueTimer\n");
809 ok(t1 != NULL, "CreateTimerQueueTimer\n");
810
811 /* Run once and finish slowly (shouldn't be done when we delete it). */
812 t2 = NULL;
813 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
814 0, 0);
815 ok(ret, "CreateTimerQueueTimer\n");
816 ok(t2 != NULL, "CreateTimerQueueTimer\n");
817
818 /* Run once and finish quickly (should be done when we delete it). */
819 t3 = NULL;
820 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
821 ok(ret, "CreateTimerQueueTimer\n");
822 ok(t3 != NULL, "CreateTimerQueueTimer\n");
823
824 /* Run once and finish slowly (shouldn't be done when we delete it). */
825 t4 = NULL;
826 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
827 0, 0);
828 ok(ret, "CreateTimerQueueTimer\n");
829 ok(t4 != NULL, "CreateTimerQueueTimer\n");
830
831 /* Give them a chance to start. */
832 Sleep(400);
833
834 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
835 even if the timer is finished. */
836 SetLastError(0xdeadbeef);
837 ret = pDeleteTimerQueueTimer(q, t1, NULL);
838 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
839 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
840 GetLastError());
841
842 SetLastError(0xdeadbeef);
843 ret = pDeleteTimerQueueTimer(q, t2, NULL);
844 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
845 ok(GetLastError() == ERROR_IO_PENDING,
846 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
847 GetLastError());
848
849 SetLastError(0xdeadbeef);
850 ret = pDeleteTimerQueueTimer(q, t3, et1);
851 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n");
852 ok(GetLastError() == 0xdeadbeef,
853 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
854 GetLastError());
855 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
856 "Timer destruction event not triggered\n");
857
858 SetLastError(0xdeadbeef);
859 ret = pDeleteTimerQueueTimer(q, t4, et2);
860 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n");
861 ok(GetLastError() == ERROR_IO_PENDING,
862 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
863 GetLastError());
864 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
865 "Timer destruction event not triggered\n");
866
867 SetLastError(0xdeadbeef);
868 ret = pDeleteTimerQueueEx(q, e);
869 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
870 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
871 GetLastError());
872 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
873 "Queue destruction event not triggered\n");
874 CloseHandle(e);
875
876 /* Test deleting/changing a timer in execution. */
877 q = pCreateTimerQueue();
878 ok(q != NULL, "CreateTimerQueue\n");
879
880 /* Test changing a once-only timer before it fires (this is allowed,
881 whereas after it fires you cannot). */
882 n1 = 0;
883 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
884 0, 0);
885 ok(ret, "CreateTimerQueueTimer\n");
886 ok(t1 != NULL, "CreateTimerQueueTimer\n");
887 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
888 ok(ret, "ChangeTimerQueueTimer\n");
889
890 d2.t = t2 = NULL;
891 d2.num_calls = 0;
892 d2.max_calls = 3;
893 d2.q = q;
894 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
895 10, 0);
896 d2.t = t2;
897 ok(ret, "CreateTimerQueueTimer\n");
898 ok(t2 != NULL, "CreateTimerQueueTimer\n");
899
900 d3.t = t3 = NULL;
901 d3.num_calls = 0;
902 d3.max_calls = 4;
903 d3.q = q;
904 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
905 10, 0);
906 d3.t = t3;
907 ok(ret, "CreateTimerQueueTimer\n");
908 ok(t3 != NULL, "CreateTimerQueueTimer\n");
909
910 d4.t = t4 = NULL;
911 d4.num_calls = 0;
912 d4.q = q;
913 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
914 0, 0);
915 d4.t = t4;
916 ok(ret, "CreateTimerQueueTimer\n");
917 ok(t4 != NULL, "CreateTimerQueueTimer\n");
918
919 Sleep(500);
920
921 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
922 ok(ret, "DeleteTimerQueueEx\n");
923 ok(n1 == 1, "ChangeTimerQueueTimer\n");
924 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
925 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
926 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
927
928 /* Test an obscure bug that was in the original implementation. */
929 q = pCreateTimerQueue();
930 ok(q != NULL, "CreateTimerQueue\n");
931
932 /* All the work is done in the callback. */
933 d1.t = t1 = NULL;
934 d1.num_calls = 0;
935 d1.q = q;
936 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
937 100, WT_EXECUTELONGFUNCTION);
938 d1.t = t1;
939 ok(ret, "CreateTimerQueueTimer\n");
940 ok(t1 != NULL, "CreateTimerQueueTimer\n");
941
942 Sleep(750);
943
944 SetLastError(0xdeadbeef);
945 ret = pDeleteTimerQueueEx(q, NULL);
946 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
947 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
948 GetLastError());
949 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
950
951 /* Test functions on the default timer queue. */
952 t1 = NULL;
953 n1 = 0;
954 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
955 1000, 0);
956 ok(ret, "CreateTimerQueueTimer, default queue\n");
957 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
958
959 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
960 ok(ret, "ChangeTimerQueueTimer, default queue\n");
961
962 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
963 ok(ret, "DeleteTimerQueueTimer, default queue\n");
964
965 /* Try mixing default and non-default queues. Apparently this works. */
966 q = pCreateTimerQueue();
967 ok(q != NULL, "CreateTimerQueue\n");
968
969 t1 = NULL;
970 n1 = 0;
971 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
972 1000, 0);
973 ok(ret, "CreateTimerQueueTimer\n");
974 ok(t1 != NULL, "CreateTimerQueueTimer\n");
975
976 t2 = NULL;
977 n2 = 0;
978 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
979 1000, 0);
980 ok(ret, "CreateTimerQueueTimer\n");
981 ok(t2 != NULL, "CreateTimerQueueTimer\n");
982
983 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
984 ok(ret, "ChangeTimerQueueTimer\n");
985
986 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
987 ok(ret, "ChangeTimerQueueTimer\n");
988
989 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
990 ok(ret, "DeleteTimerQueueTimer\n");
991
992 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
993 ok(ret, "DeleteTimerQueueTimer\n");
994
995 /* Try to delete the default queue? In any case: not allowed. */
996 SetLastError(0xdeadbeef);
997 ret = pDeleteTimerQueueEx(NULL, NULL);
998 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n");
999 ok(GetLastError() == ERROR_INVALID_HANDLE,
1000 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
1001 GetLastError());
1002
1003 SetLastError(0xdeadbeef);
1004 ret = pDeleteTimerQueueEx(q, NULL);
1005 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING,
1006 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
1007 GetLastError());
1008 }
1009
1010 static HANDLE modify_handle(HANDLE handle, DWORD modify)
1011 {
1012 DWORD tmp = HandleToULong(handle);
1013 tmp |= modify;
1014 return ULongToHandle(tmp);
1015 }
1016
1017 static void test_WaitForSingleObject(void)
1018 {
1019 HANDLE signaled, nonsignaled, invalid;
1020 DWORD ret;
1021
1022 signaled = CreateEventW(NULL, TRUE, TRUE, NULL);
1023 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL);
1024 invalid = (HANDLE) 0xdeadbee0;
1025
1026 /* invalid handle with different values for lower 2 bits */
1027 SetLastError(0xdeadbeef);
1028 ret = WaitForSingleObject(invalid, 0);
1029 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1030 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1031
1032 SetLastError(0xdeadbeef);
1033 ret = WaitForSingleObject(modify_handle(invalid, 1), 0);
1034 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1035 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1036
1037 SetLastError(0xdeadbeef);
1038 ret = WaitForSingleObject(modify_handle(invalid, 2), 0);
1039 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1040 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1041
1042 SetLastError(0xdeadbeef);
1043 ret = WaitForSingleObject(modify_handle(invalid, 3), 0);
1044 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret);
1045 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
1046
1047 /* valid handle with different values for lower 2 bits */
1048 SetLastError(0xdeadbeef);
1049 ret = WaitForSingleObject(nonsignaled, 0);
1050 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1051 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1052
1053 SetLastError(0xdeadbeef);
1054 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0);
1055 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1056 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1057
1058 SetLastError(0xdeadbeef);
1059 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0);
1060 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1061 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1062
1063 SetLastError(0xdeadbeef);
1064 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0);
1065 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret);
1066 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1067
1068 /* valid handle with different values for lower 2 bits */
1069 SetLastError(0xdeadbeef);
1070 ret = WaitForSingleObject(signaled, 0);
1071 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1072 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1073
1074 SetLastError(0xdeadbeef);
1075 ret = WaitForSingleObject(modify_handle(signaled, 1), 0);
1076 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1077 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1078
1079 SetLastError(0xdeadbeef);
1080 ret = WaitForSingleObject(modify_handle(signaled, 2), 0);
1081 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1082 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1083
1084 SetLastError(0xdeadbeef);
1085 ret = WaitForSingleObject(modify_handle(signaled, 3), 0);
1086 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret);
1087 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
1088
1089 CloseHandle(signaled);
1090 CloseHandle(nonsignaled);
1091 }
1092
1093 static void test_WaitForMultipleObjects(void)
1094 {
1095 DWORD r;
1096 int i;
1097 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS];
1098
1099 /* create the maximum number of events and make sure
1100 * we can wait on that many */
1101 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1102 {
1103 maxevents[i] = CreateEvent(NULL, i==0, TRUE, NULL);
1104 ok( maxevents[i] != 0, "should create enough events\n");
1105 }
1106
1107 /* a manual-reset event remains signaled, an auto-reset event is cleared */
1108 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1109 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r);
1110 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1111 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r);
1112 ok(ResetEvent(maxevents[0]), "ResetEvent\n");
1113 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++)
1114 {
1115 /* the lowest index is checked first and remaining events are untouched */
1116 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
1117 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r);
1118 }
1119
1120 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
1121 if (maxevents[i]) CloseHandle(maxevents[i]);
1122 }
1123
1124 START_TEST(sync)
1125 {
1126 HMODULE hdll = GetModuleHandle("kernel32");
1127 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer");
1128 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue");
1129 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer");
1130 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA");
1131 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx");
1132 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer");
1133 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA");
1134 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification");
1135 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification");
1136
1137 test_signalandwait();
1138 test_mutex();
1139 test_slist();
1140 test_event();
1141 test_semaphore();
1142 test_waitable_timer();
1143 test_iocp_callback();
1144 test_timer_queue();
1145 test_WaitForSingleObject();
1146 test_WaitForMultipleObjects();
1147 }