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