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
);
39 static void test_signalandwait(void)
41 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
45 HANDLE event
[2], maxevents
[MAXIMUM_WAIT_OBJECTS
], semaphore
[2], file
;
47 kernel32
= GetModuleHandle("kernel32");
48 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
50 if (!pSignalObjectAndWait
)
53 /* invalid parameters */
54 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
55 if (r
== ERROR_INVALID_FUNCTION
)
57 skip("SignalObjectAndWait is not implemented\n");
58 return; /* Win98/ME */
60 ok( r
== WAIT_FAILED
, "should fail\n");
62 event
[0] = CreateEvent(NULL
, 0, 0, NULL
);
63 event
[1] = CreateEvent(NULL
, 1, 1, NULL
);
65 ok( event
[0] && event
[1], "failed to create event flags\n");
67 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
68 ok( r
== WAIT_FAILED
, "should fail\n");
70 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
71 ok( r
== WAIT_FAILED
, "should fail\n");
74 /* valid parameters */
75 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
76 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
78 /* event[0] is now signalled */
79 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
80 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
82 /* event[0] is not signalled */
83 r
= WaitForSingleObject(event
[0], 0);
84 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
86 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
87 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
89 /* clear event[1] and check for a timeout */
90 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
91 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
92 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
94 CloseHandle(event
[0]);
95 CloseHandle(event
[1]);
97 /* create the maximum number of events and make sure
98 * we can wait on that many */
99 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
101 maxevents
[i
] = CreateEvent(NULL
, 1, 1, NULL
);
102 ok( maxevents
[i
] != 0, "should create enough events\n");
104 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
105 ok( r
!= WAIT_FAILED
&& r
!= WAIT_TIMEOUT
, "should succeed\n");
107 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
108 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
111 semaphore
[0] = CreateSemaphore( NULL
, 0, 1, NULL
);
112 semaphore
[1] = CreateSemaphore( NULL
, 1, 1, NULL
);
113 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
115 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
116 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
118 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
119 ok( r
== WAIT_FAILED
, "should fail\n");
121 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
122 ok( r
== FALSE
, "should fail\n");
124 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
125 ok( r
== TRUE
, "should succeed\n");
127 CloseHandle(semaphore
[0]);
128 CloseHandle(semaphore
[1]);
130 /* try a registry key */
131 file
= CreateFile("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
132 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
133 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
134 ok( r
== WAIT_FAILED
, "should fail\n");
135 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
139 static void test_mutex(void)
146 hCreated
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
147 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
148 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
149 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
151 /* yes, opening with just READ_CONTROL access allows us to successfully
152 * call ReleaseMutex */
153 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WineTestMutex");
154 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
155 ret
= ReleaseMutex(hOpened
);
156 todo_wine
ok(ret
, "ReleaseMutex failed with error %d\n", GetLastError());
157 ret
= ReleaseMutex(hCreated
);
158 todo_wine
ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
159 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
161 /* test case sensitivity */
163 SetLastError(0xdeadbeef);
164 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
165 ok(!hOpened
, "OpenMutex succeeded\n");
166 ok(GetLastError() == ERROR_FILE_NOT_FOUND
||
167 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
168 "wrong error %u\n", GetLastError());
170 SetLastError(0xdeadbeef);
171 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "winetestmutex");
172 ok(!hOpened
, "OpenMutex succeeded\n");
173 ok(GetLastError() == ERROR_FILE_NOT_FOUND
||
174 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
175 "wrong error %u\n", GetLastError());
177 SetLastError(0xdeadbeef);
178 hOpened
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
179 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
180 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
181 CloseHandle(hOpened
);
183 SetLastError(0xdeadbeef);
184 hOpened
= CreateMutex(NULL
, FALSE
, "WINETESTMUTEX");
185 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
186 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
187 CloseHandle(hOpened
);
189 CloseHandle(hCreated
);
192 static void test_slist(void)
198 } item1
, item2
, item3
, *pitem
;
200 SLIST_HEADER slist_header
;
204 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
205 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
206 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
207 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
208 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
211 kernel32
= GetModuleHandle("KERNEL32.DLL");
212 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
213 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
214 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
215 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
216 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
217 if (pInitializeSListHead
== NULL
||
218 pQueryDepthSList
== NULL
||
219 pInterlockedFlushSList
== NULL
||
220 pInterlockedPopEntrySList
== NULL
||
221 pInterlockedPushEntrySList
== NULL
)
223 skip("some required slist entrypoints were not found, skipping tests\n");
227 memset(&slist_header
, 0xFF, sizeof(slist_header
));
228 pInitializeSListHead(&slist_header
);
229 size
= pQueryDepthSList(&slist_header
);
230 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
233 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
234 "previous entry in empty slist wasn't NULL\n");
235 size
= pQueryDepthSList(&slist_header
);
236 ok(size
== 1, "slist with 1 item has size %d\n", size
);
239 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
240 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
243 pitem
= (struct item
*) entry
;
244 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
246 size
= pQueryDepthSList(&slist_header
);
247 ok(size
== 2, "slist with 2 items has size %d\n", size
);
250 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
251 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
254 pitem
= (struct item
*) entry
;
255 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
257 size
= pQueryDepthSList(&slist_header
);
258 ok(size
== 3, "slist with 3 items has size %d\n", size
);
260 entry
= pInterlockedPopEntrySList(&slist_header
);
261 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
264 pitem
= (struct item
*) entry
;
265 ok(pitem
->value
== 3, "unexpected entry removed\n");
267 size
= pQueryDepthSList(&slist_header
);
268 ok(size
== 2, "slist with 2 items has size %d\n", size
);
270 entry
= pInterlockedFlushSList(&slist_header
);
271 size
= pQueryDepthSList(&slist_header
);
272 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
275 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
276 "popping empty slist didn't return NULL\n");
278 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
279 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
282 static void test_event(void)
284 HANDLE handle
, handle2
;
285 SECURITY_ATTRIBUTES sa
;
286 SECURITY_DESCRIPTOR sd
;
290 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
291 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
294 sa
.nLength
= sizeof(sa
);
295 sa
.lpSecurityDescriptor
= &sd
;
296 sa
.bInheritHandle
= FALSE
;
298 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
301 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
302 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
305 /* sd with NULL dacl */
306 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
307 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
308 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
311 /* sd with empty dacl */
312 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
313 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
314 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
315 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
318 /* test case sensitivity */
320 SetLastError(0xdeadbeef);
321 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
322 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
323 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
325 SetLastError(0xdeadbeef);
326 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
327 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
328 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
329 CloseHandle( handle2
);
331 SetLastError(0xdeadbeef);
332 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
333 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
334 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
335 CloseHandle( handle2
);
337 SetLastError(0xdeadbeef);
338 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
339 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
340 CloseHandle( handle2
);
342 SetLastError(0xdeadbeef);
343 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
344 ok( !handle2
, "OpenEvent succeeded\n");
345 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
346 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
347 "wrong error %u\n", GetLastError());
349 CloseHandle( handle
);
352 static void test_semaphore(void)
354 HANDLE handle
, handle2
;
356 /* test case sensitivity */
358 SetLastError(0xdeadbeef);
359 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
360 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
361 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
363 SetLastError(0xdeadbeef);
364 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
365 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
366 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
367 CloseHandle( handle2
);
369 SetLastError(0xdeadbeef);
370 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
371 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
372 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
373 CloseHandle( handle2
);
375 SetLastError(0xdeadbeef);
376 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
377 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
378 CloseHandle( handle2
);
380 SetLastError(0xdeadbeef);
381 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
382 ok( !handle2
, "OpenSemaphore succeeded\n");
383 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
384 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
385 "wrong error %u\n", GetLastError());
387 CloseHandle( handle
);
390 static void test_waitable_timer(void)
392 HANDLE handle
, handle2
;
394 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
396 skip("{Create,Open}WaitableTimerA() is not available\n");
400 /* test case sensitivity */
402 SetLastError(0xdeadbeef);
403 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
404 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
405 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
407 SetLastError(0xdeadbeef);
408 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
409 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
410 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
411 CloseHandle( handle2
);
413 SetLastError(0xdeadbeef);
414 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
415 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
416 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
417 CloseHandle( handle2
);
419 SetLastError(0xdeadbeef);
420 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
421 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
422 CloseHandle( handle2
);
424 SetLastError(0xdeadbeef);
425 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
426 ok( !handle2
, "OpenWaitableTimer succeeded\n");
427 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
428 GetLastError() == ERROR_INVALID_NAME
, /* win98 */
429 "wrong error %u\n", GetLastError());
431 CloseHandle( handle
);
434 static HANDLE sem
= 0;
436 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
438 ReleaseSemaphore(sem
, 1, NULL
);
441 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
443 static void test_iocp_callback(void)
445 char temp_path
[MAX_PATH
];
446 char filename
[MAX_PATH
];
449 static const char prefix
[] = "pfx";
451 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
453 const char *buffer
= "12345678123456781234567812345678";
454 OVERLAPPED overlapped
;
456 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
457 if(!p_BindIoCompletionCallback
) {
458 skip("BindIoCompletionCallback not found in this DLL\n");
462 sem
= CreateSemaphore(NULL
, 0, 1, NULL
);
463 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
465 ret
= GetTempPathA(MAX_PATH
, temp_path
);
466 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
467 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
469 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
470 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
472 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
473 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
474 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
476 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
477 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
478 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
480 ret
= CloseHandle(hFile
);
481 ok( ret
, "CloseHandle: error %d\n", GetLastError());
482 ret
= DeleteFileA(filename
);
483 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
485 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
486 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
487 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
489 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
490 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
492 memset(&overlapped
, 0, sizeof(overlapped
));
493 retb
= WriteFile(hFile
, (const void *) buffer
, 4, &bytesWritten
, &overlapped
);
494 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
496 ret
= WaitForSingleObject(sem
, 5000);
497 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
500 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
501 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
502 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
503 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
504 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
505 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
507 ret
= CloseHandle(hFile
);
508 ok( ret
, "CloseHandle: error %d\n", GetLastError());
509 ret
= DeleteFileA(filename
);
510 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
512 /* win2k3 requires the Flags parameter to be zero */
513 SetLastError(0xdeadbeef);
514 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
515 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
516 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
517 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
519 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
520 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
522 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
523 ret
= CloseHandle(hFile
);
524 ok( ret
, "CloseHandle: error %d\n", GetLastError());
525 ret
= DeleteFileA(filename
);
526 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
528 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
529 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
530 ok(GetLastError() == ERROR_INVALID_HANDLE
||
531 GetLastError() == ERROR_INVALID_PARAMETER
, /* vista */
532 "Last error is %d\n", GetLastError());
535 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
538 ok(timedOut
, "Timer callbacks should always time out\n");
542 struct timer_queue_data1
549 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
551 struct timer_queue_data1
*d
= p
;
552 ok(timedOut
, "Timer callbacks should always time out\n");
553 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
556 SetLastError(0xdeadbeef);
557 /* Note, XP SP2 does *not* do any deadlock checking, so passing
558 INVALID_HANDLE_VALUE here will just hang. */
559 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
560 ok(!ret
, "DeleteTimerQueueTimer\n");
561 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
565 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
567 struct timer_queue_data1
*d
= p
;
568 ok(timedOut
, "Timer callbacks should always time out\n");
569 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
571 /* Basically kill the timer since it won't have time to run
573 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
574 ok(ret
, "ChangeTimerQueueTimer\n");
578 static void CALLBACK
timer_queue_cb4(PVOID p
, BOOLEAN timedOut
)
580 struct timer_queue_data1
*d
= p
;
581 ok(timedOut
, "Timer callbacks should always time out\n");
584 /* This tests whether a timer gets flagged for deletion before
585 or after the callback runs. If we start this timer with a
586 period of zero (run once), then ChangeTimerQueueTimer will
587 fail if the timer is already flagged. Hence we really run
588 only once. Otherwise we will run multiple times. */
589 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 50, 50);
590 ok(ret
, "ChangeTimerQueueTimer\n");
595 static void CALLBACK
timer_queue_cb5(PVOID p
, BOOLEAN timedOut
)
597 DWORD_PTR delay
= (DWORD_PTR
) p
;
598 ok(timedOut
, "Timer callbacks should always time out\n");
603 static void CALLBACK
timer_queue_cb6(PVOID p
, BOOLEAN timedOut
)
605 struct timer_queue_data1
*d
= p
;
606 ok(timedOut
, "Timer callbacks should always time out\n");
607 /* This tests an original implementation bug where a deleted timer may get
608 to run, but it is tricky to set up. */
609 if (d
->q
&& d
->num_calls
++ == 0)
611 /* First run: delete ourselves, then insert and remove a timer
612 that goes in front of us in the sorted timeout list. Once
613 removed, we will still timeout at the faster timer's due time,
614 but this should be a no-op if we are bug-free. There should
615 not be a second run. We can test the value of num_calls later. */
619 /* The delete will pend while we are in this callback. */
620 SetLastError(0xdeadbeef);
621 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
622 ok(!ret
, "DeleteTimerQueueTimer\n");
623 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
625 ret
= pCreateTimerQueueTimer(&t
, d
->q
, timer_queue_cb1
, NULL
, 100, 0, 0);
626 ok(ret
, "CreateTimerQueueTimer\n");
627 ok(t
!= NULL
, "CreateTimerQueueTimer\n");
629 ret
= pDeleteTimerQueueTimer(d
->q
, t
, INVALID_HANDLE_VALUE
);
630 ok(ret
, "DeleteTimerQueueTimer\n");
632 /* Now we stay alive by hanging around in the callback. */
637 static void test_timer_queue(void)
639 HANDLE q
, t1
, t2
, t3
, t4
, t5
;
640 int n1
, n2
, n3
, n4
, n5
;
641 struct timer_queue_data1 d1
, d2
, d3
, d4
;
645 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
646 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
648 skip("TimerQueue API not present\n");
652 /* Test asynchronous deletion of the queue. */
653 q
= pCreateTimerQueue();
654 ok(q
!= NULL
, "CreateTimerQueue\n");
656 SetLastError(0xdeadbeef);
657 ret
= pDeleteTimerQueueEx(q
, NULL
);
658 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
659 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
662 /* Test synchronous deletion of the queue and running timers. */
663 q
= pCreateTimerQueue();
664 ok(q
!= NULL
, "CreateTimerQueue\n");
669 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
671 ok(ret
, "CreateTimerQueueTimer\n");
672 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
677 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
679 ok(ret
, "CreateTimerQueueTimer\n");
680 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
685 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
687 ok(ret
, "CreateTimerQueueTimer\n");
688 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
690 /* Start really late (it won't start). */
693 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
695 ok(ret
, "CreateTimerQueueTimer\n");
696 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
698 /* Start soon, but delay so long it won't run again. */
701 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
703 ok(ret
, "CreateTimerQueueTimer\n");
704 ok(t5
!= NULL
, "CreateTimerQueueTimer\n");
706 /* Give them a chance to do some work. */
709 /* Test deleting a once-only timer. */
710 ret
= pDeleteTimerQueueTimer(q
, t1
, INVALID_HANDLE_VALUE
);
711 ok(ret
, "DeleteTimerQueueTimer\n");
713 /* A periodic timer. */
714 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
715 ok(ret
, "DeleteTimerQueueTimer\n");
717 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
718 ok(ret
, "DeleteTimerQueueEx\n");
719 ok(n1
== 1, "Timer callback 1\n");
720 ok(n2
< n3
, "Timer callback 2 should be much slower than 3\n");
721 ok(n4
== 0, "Timer callback 4\n");
722 ok(n5
== 1, "Timer callback 5\n");
724 /* Test synchronous deletion of the timer/queue with event trigger. */
725 e
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
726 et1
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
727 et2
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
728 if (!e
|| !et1
|| !et2
)
730 skip("Failed to create timer queue descruction event\n");
734 q
= pCreateTimerQueue();
735 ok(q
!= NULL
, "CreateTimerQueue\n");
737 /* Run once and finish quickly (should be done when we delete it). */
739 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
740 ok(ret
, "CreateTimerQueueTimer\n");
741 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
743 /* Run once and finish slowly (shouldn't be done when we delete it). */
745 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
747 ok(ret
, "CreateTimerQueueTimer\n");
748 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
750 /* Run once and finish quickly (should be done when we delete it). */
752 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb5
, NULL
, 0, 0, 0);
753 ok(ret
, "CreateTimerQueueTimer\n");
754 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
756 /* Run once and finish slowly (shouldn't be done when we delete it). */
758 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb5
, (PVOID
) 1000, 0,
760 ok(ret
, "CreateTimerQueueTimer\n");
761 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
763 /* Give them a chance to start. */
766 /* DeleteTimerQueueTimer always returns PENDING with a NULL event,
767 even if the timer is finished. */
768 SetLastError(0xdeadbeef);
769 ret
= pDeleteTimerQueueTimer(q
, t1
, NULL
);
770 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
771 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
774 SetLastError(0xdeadbeef);
775 ret
= pDeleteTimerQueueTimer(q
, t2
, NULL
);
776 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
777 ok(GetLastError() == ERROR_IO_PENDING
,
778 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
781 SetLastError(0xdeadbeef);
782 ret
= pDeleteTimerQueueTimer(q
, t3
, et1
);
783 ok(ret
, "DeleteTimerQueueTimer call was expected to fail\n");
784 ok(GetLastError() == 0xdeadbeef,
785 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n",
787 ok(WaitForSingleObject(et1
, 250) == WAIT_OBJECT_0
,
788 "Timer destruction event not triggered\n");
790 SetLastError(0xdeadbeef);
791 ret
= pDeleteTimerQueueTimer(q
, t4
, et2
);
792 ok(!ret
, "DeleteTimerQueueTimer call was expected to fail\n");
793 ok(GetLastError() == ERROR_IO_PENDING
,
794 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n",
796 ok(WaitForSingleObject(et2
, 1000) == WAIT_OBJECT_0
,
797 "Timer destruction event not triggered\n");
799 SetLastError(0xdeadbeef);
800 ret
= pDeleteTimerQueueEx(q
, e
);
801 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
802 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
804 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
805 "Queue destruction event not triggered\n");
808 /* Test deleting/changing a timer in execution. */
809 q
= pCreateTimerQueue();
810 ok(q
!= NULL
, "CreateTimerQueue\n");
812 /* Test changing a once-only timer before it fires (this is allowed,
813 whereas after it fires you cannot). */
815 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 10000,
817 ok(ret
, "CreateTimerQueueTimer\n");
818 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
819 ret
= pChangeTimerQueueTimer(q
, t1
, 0, 0);
820 ok(ret
, "ChangeTimerQueueTimer\n");
826 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
829 ok(ret
, "CreateTimerQueueTimer\n");
830 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
836 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
839 ok(ret
, "CreateTimerQueueTimer\n");
840 ok(t3
!= NULL
, "CreateTimerQueueTimer\n");
845 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb4
, &d4
, 10,
848 ok(ret
, "CreateTimerQueueTimer\n");
849 ok(t4
!= NULL
, "CreateTimerQueueTimer\n");
853 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
854 ok(ret
, "DeleteTimerQueueEx\n");
855 ok(n1
== 1, "ChangeTimerQueueTimer\n");
856 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
857 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
858 ok(d4
.num_calls
== 1, "Timer flagged for deletion incorrectly\n");
860 /* Test an obscure bug that was in the original implementation. */
861 q
= pCreateTimerQueue();
862 ok(q
!= NULL
, "CreateTimerQueue\n");
864 /* All the work is done in the callback. */
868 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb6
, &d1
, 100,
869 100, WT_EXECUTELONGFUNCTION
);
871 ok(ret
, "CreateTimerQueueTimer\n");
872 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
876 SetLastError(0xdeadbeef);
877 ret
= pDeleteTimerQueueEx(q
, NULL
);
878 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
879 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
881 ok(d1
.num_calls
== 1, "DeleteTimerQueueTimer\n");
883 /* Test functions on the default timer queue. */
886 ret
= pCreateTimerQueueTimer(&t1
, NULL
, timer_queue_cb1
, &n1
, 1000,
888 ok(ret
, "CreateTimerQueueTimer, default queue\n");
889 ok(t1
!= NULL
, "CreateTimerQueueTimer, default queue\n");
891 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
892 ok(ret
, "ChangeTimerQueueTimer, default queue\n");
894 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
895 ok(ret
, "DeleteTimerQueueTimer, default queue\n");
897 /* Try mixing default and non-default queues. Apparently this works. */
898 q
= pCreateTimerQueue();
899 ok(q
!= NULL
, "CreateTimerQueue\n");
903 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 1000,
905 ok(ret
, "CreateTimerQueueTimer\n");
906 ok(t1
!= NULL
, "CreateTimerQueueTimer\n");
910 ret
= pCreateTimerQueueTimer(&t2
, NULL
, timer_queue_cb1
, &n2
, 1000,
912 ok(ret
, "CreateTimerQueueTimer\n");
913 ok(t2
!= NULL
, "CreateTimerQueueTimer\n");
915 ret
= pChangeTimerQueueTimer(NULL
, t1
, 2000, 2000);
916 ok(ret
, "ChangeTimerQueueTimer\n");
918 ret
= pChangeTimerQueueTimer(q
, t2
, 2000, 2000);
919 ok(ret
, "ChangeTimerQueueTimer\n");
921 ret
= pDeleteTimerQueueTimer(NULL
, t1
, INVALID_HANDLE_VALUE
);
922 ok(ret
, "DeleteTimerQueueTimer\n");
924 ret
= pDeleteTimerQueueTimer(q
, t2
, INVALID_HANDLE_VALUE
);
925 ok(ret
, "DeleteTimerQueueTimer\n");
927 /* Try to delete the default queue? In any case: not allowed. */
928 SetLastError(0xdeadbeef);
929 ret
= pDeleteTimerQueueEx(NULL
, NULL
);
930 ok(!ret
, "DeleteTimerQueueEx call was expected to fail\n");
931 ok(GetLastError() == ERROR_INVALID_HANDLE
,
932 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n",
935 SetLastError(0xdeadbeef);
936 ret
= pDeleteTimerQueueEx(q
, NULL
);
937 ok(ret
/* vista */ || GetLastError() == ERROR_IO_PENDING
,
938 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n",
944 HMODULE hdll
= GetModuleHandle("kernel32");
945 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
946 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
947 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
948 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
949 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
950 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
951 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
953 test_signalandwait();
958 test_waitable_timer();
959 test_iocp_callback();