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
25 #define _WIN32_WINNT 0x500
28 #include "wine/test.h"
30 static HANDLE (WINAPI
*pCreateTimerQueue
)(void);
31 static BOOL (WINAPI
*pCreateTimerQueueTimer
)(PHANDLE
, HANDLE
, WAITORTIMERCALLBACK
,
32 PVOID
, DWORD
, DWORD
, ULONG
);
33 static HANDLE (WINAPI
*pCreateWaitableTimerA
)(SECURITY_ATTRIBUTES
*,BOOL
,LPCSTR
);
34 static BOOL (WINAPI
*pDeleteTimerQueueEx
)(HANDLE
, HANDLE
);
35 static HANDLE (WINAPI
*pOpenWaitableTimerA
)(DWORD
,BOOL
,LPCSTR
);
37 static void test_signalandwait(void)
39 DWORD (WINAPI
*pSignalObjectAndWait
)(HANDLE
, HANDLE
, DWORD
, BOOL
);
43 HANDLE event
[2], maxevents
[MAXIMUM_WAIT_OBJECTS
], semaphore
[2], file
;
45 kernel32
= GetModuleHandle("kernel32");
46 pSignalObjectAndWait
= (void*) GetProcAddress(kernel32
, "SignalObjectAndWait");
48 if (!pSignalObjectAndWait
)
51 /* invalid parameters */
52 r
= pSignalObjectAndWait(NULL
, NULL
, 0, 0);
53 if (r
== ERROR_INVALID_FUNCTION
)
55 trace("SignalObjectAndWait not implemented, skipping tests\n");
56 return; /* Win98/ME */
58 ok( r
== WAIT_FAILED
, "should fail\n");
60 event
[0] = CreateEvent(NULL
, 0, 0, NULL
);
61 event
[1] = CreateEvent(NULL
, 1, 1, NULL
);
63 ok( event
[0] && event
[1], "failed to create event flags\n");
65 r
= pSignalObjectAndWait(event
[0], NULL
, 0, FALSE
);
66 ok( r
== WAIT_FAILED
, "should fail\n");
68 r
= pSignalObjectAndWait(NULL
, event
[0], 0, FALSE
);
69 ok( r
== WAIT_FAILED
, "should fail\n");
72 /* valid parameters */
73 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
74 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
76 /* event[0] is now signalled */
77 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
78 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
80 /* event[0] is not signalled */
81 r
= WaitForSingleObject(event
[0], 0);
82 ok( r
== WAIT_TIMEOUT
, "event was signalled\n");
84 r
= pSignalObjectAndWait(event
[0], event
[0], 0, FALSE
);
85 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
87 /* clear event[1] and check for a timeout */
88 ok(ResetEvent(event
[1]), "failed to clear event[1]\n");
89 r
= pSignalObjectAndWait(event
[0], event
[1], 0, FALSE
);
90 ok( r
== WAIT_TIMEOUT
, "should timeout\n");
92 CloseHandle(event
[0]);
93 CloseHandle(event
[1]);
95 /* create the maximum number of events and make sure
96 * we can wait on that many */
97 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
99 maxevents
[i
] = CreateEvent(NULL
, 1, 1, NULL
);
100 ok( maxevents
[i
] != 0, "should create enough events\n");
102 r
= WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS
, maxevents
, 0, 0);
103 ok( r
!= WAIT_FAILED
&& r
!= WAIT_TIMEOUT
, "should succeed\n");
105 for (i
=0; i
<MAXIMUM_WAIT_OBJECTS
; i
++)
106 if (maxevents
[i
]) CloseHandle(maxevents
[i
]);
109 semaphore
[0] = CreateSemaphore( NULL
, 0, 1, NULL
);
110 semaphore
[1] = CreateSemaphore( NULL
, 1, 1, NULL
);
111 ok( semaphore
[0] && semaphore
[1], "failed to create semaphore\n");
113 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
114 ok( r
== WAIT_OBJECT_0
, "should succeed\n");
116 r
= pSignalObjectAndWait(semaphore
[0], semaphore
[1], 0, FALSE
);
117 ok( r
== WAIT_FAILED
, "should fail\n");
119 r
= ReleaseSemaphore(semaphore
[0],1,NULL
);
120 ok( r
== FALSE
, "should fail\n");
122 r
= ReleaseSemaphore(semaphore
[1],1,NULL
);
123 ok( r
== TRUE
, "should succeed\n");
125 CloseHandle(semaphore
[0]);
126 CloseHandle(semaphore
[1]);
128 /* try a registry key */
129 file
= CreateFile("x", GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
130 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
131 r
= pSignalObjectAndWait(file
, file
, 0, FALSE
);
132 ok( r
== WAIT_FAILED
, "should fail\n");
133 ok( ERROR_INVALID_HANDLE
== GetLastError(), "should return invalid handle error\n");
137 static void test_mutex(void)
144 hCreated
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
145 ok(hCreated
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
146 wait_ret
= WaitForSingleObject(hCreated
, INFINITE
);
147 ok(wait_ret
== WAIT_OBJECT_0
, "WaitForSingleObject failed with error 0x%08x\n", wait_ret
);
149 /* yes, opening with just READ_CONTROL access allows us to successfully
150 * call ReleaseMutex */
151 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WineTestMutex");
152 ok(hOpened
!= NULL
, "OpenMutex failed with error %d\n", GetLastError());
153 ret
= ReleaseMutex(hOpened
);
154 todo_wine
ok(ret
, "ReleaseMutex failed with error %d\n", GetLastError());
155 ret
= ReleaseMutex(hCreated
);
156 todo_wine
ok(!ret
&& (GetLastError() == ERROR_NOT_OWNER
),
157 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError());
159 /* test case sensitivity */
161 SetLastError(0xdeadbeef);
162 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "WINETESTMUTEX");
163 ok(!hOpened
, "OpenMutex succeeded\n");
164 ok(GetLastError() == ERROR_FILE_NOT_FOUND
||
165 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
166 "wrong error %u\n", GetLastError());
168 SetLastError(0xdeadbeef);
169 hOpened
= OpenMutex(READ_CONTROL
, FALSE
, "winetestmutex");
170 ok(!hOpened
, "OpenMutex succeeded\n");
171 ok(GetLastError() == ERROR_FILE_NOT_FOUND
||
172 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
173 "wrong error %u\n", GetLastError());
175 SetLastError(0xdeadbeef);
176 hOpened
= CreateMutex(NULL
, FALSE
, "WineTestMutex");
177 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
178 ok(GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
179 CloseHandle(hOpened
);
181 SetLastError(0xdeadbeef);
182 hOpened
= CreateMutex(NULL
, FALSE
, "WINETESTMUTEX");
183 ok(hOpened
!= NULL
, "CreateMutex failed with error %d\n", GetLastError());
184 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
185 CloseHandle(hOpened
);
187 CloseHandle(hCreated
);
190 static void test_slist(void)
196 } item1
, item2
, item3
, *pitem
;
198 SLIST_HEADER slist_header
, test_header
;
202 VOID (WINAPI
*pInitializeSListHead
)(PSLIST_HEADER
);
203 USHORT (WINAPI
*pQueryDepthSList
)(PSLIST_HEADER
);
204 PSLIST_ENTRY (WINAPI
*pInterlockedFlushSList
)(PSLIST_HEADER
);
205 PSLIST_ENTRY (WINAPI
*pInterlockedPopEntrySList
)(PSLIST_HEADER
);
206 PSLIST_ENTRY (WINAPI
*pInterlockedPushEntrySList
)(PSLIST_HEADER
,PSLIST_ENTRY
);
209 kernel32
= GetModuleHandle("KERNEL32.DLL");
210 pInitializeSListHead
= (void*) GetProcAddress(kernel32
, "InitializeSListHead");
211 pQueryDepthSList
= (void*) GetProcAddress(kernel32
, "QueryDepthSList");
212 pInterlockedFlushSList
= (void*) GetProcAddress(kernel32
, "InterlockedFlushSList");
213 pInterlockedPopEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPopEntrySList");
214 pInterlockedPushEntrySList
= (void*) GetProcAddress(kernel32
, "InterlockedPushEntrySList");
215 if (pInitializeSListHead
== NULL
||
216 pQueryDepthSList
== NULL
||
217 pInterlockedFlushSList
== NULL
||
218 pInterlockedPopEntrySList
== NULL
||
219 pInterlockedPushEntrySList
== NULL
)
221 skip("some required slist entrypoints were not found, skipping tests\n");
225 memset(&test_header
, 0, sizeof(test_header
));
226 memset(&slist_header
, 0xFF, sizeof(slist_header
));
227 pInitializeSListHead(&slist_header
);
228 ok(memcmp(&test_header
, &slist_header
, sizeof(SLIST_HEADER
)) == 0,
229 "InitializeSListHead didn't zero-fill list header\n");
230 size
= pQueryDepthSList(&slist_header
);
231 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
234 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
235 "previous entry in empty slist wasn't NULL\n");
236 size
= pQueryDepthSList(&slist_header
);
237 ok(size
== 1, "slist with 1 item has size %d\n", size
);
240 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
241 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
244 pitem
= (struct item
*) entry
;
245 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
247 size
= pQueryDepthSList(&slist_header
);
248 ok(size
== 2, "slist with 2 items has size %d\n", size
);
251 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
252 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
255 pitem
= (struct item
*) entry
;
256 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
258 size
= pQueryDepthSList(&slist_header
);
259 ok(size
== 3, "slist with 3 items has size %d\n", size
);
261 entry
= pInterlockedPopEntrySList(&slist_header
);
262 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
265 pitem
= (struct item
*) entry
;
266 ok(pitem
->value
== 3, "unexpected entry removed\n");
268 size
= pQueryDepthSList(&slist_header
);
269 ok(size
== 2, "slist with 2 items has size %d\n", size
);
271 entry
= pInterlockedFlushSList(&slist_header
);
272 size
= pQueryDepthSList(&slist_header
);
273 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
276 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
277 "popping empty slist didn't return NULL\n");
279 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
280 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
283 static void test_event(void)
285 HANDLE handle
, handle2
;
286 SECURITY_ATTRIBUTES sa
;
287 SECURITY_DESCRIPTOR sd
;
291 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
292 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
295 sa
.nLength
= sizeof(sa
);
296 sa
.lpSecurityDescriptor
= &sd
;
297 sa
.bInheritHandle
= FALSE
;
299 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
302 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
303 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
306 /* sd with NULL dacl */
307 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
308 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
309 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
312 /* sd with empty dacl */
313 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
314 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
315 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
316 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
319 /* test case sensitivity */
321 SetLastError(0xdeadbeef);
322 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
323 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
324 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
326 SetLastError(0xdeadbeef);
327 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
328 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
329 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
330 CloseHandle( handle2
);
332 SetLastError(0xdeadbeef);
333 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
334 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
335 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
336 CloseHandle( handle2
);
338 SetLastError(0xdeadbeef);
339 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
340 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
341 CloseHandle( handle2
);
343 SetLastError(0xdeadbeef);
344 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
345 ok( !handle2
, "OpenEvent succeeded\n");
346 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
347 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
348 "wrong error %u\n", GetLastError());
350 CloseHandle( handle
);
353 static void test_semaphore(void)
355 HANDLE handle
, handle2
;
357 /* test case sensitivity */
359 SetLastError(0xdeadbeef);
360 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
361 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
362 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
364 SetLastError(0xdeadbeef);
365 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
366 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
367 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
368 CloseHandle( handle2
);
370 SetLastError(0xdeadbeef);
371 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
372 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
373 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
374 CloseHandle( handle2
);
376 SetLastError(0xdeadbeef);
377 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
378 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
379 CloseHandle( handle2
);
381 SetLastError(0xdeadbeef);
382 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
383 ok( !handle2
, "OpenSemaphore succeeded\n");
384 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
385 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
386 "wrong error %u\n", GetLastError());
388 CloseHandle( handle
);
391 static void test_waitable_timer(void)
393 HANDLE handle
, handle2
;
395 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
397 skip("{Create,Open}WaitableTimerA() is not available\n");
401 /* test case sensitivity */
403 SetLastError(0xdeadbeef);
404 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
405 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
406 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
408 SetLastError(0xdeadbeef);
409 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
410 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
411 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
412 CloseHandle( handle2
);
414 SetLastError(0xdeadbeef);
415 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
416 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
417 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
418 CloseHandle( handle2
);
420 SetLastError(0xdeadbeef);
421 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
422 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
423 CloseHandle( handle2
);
425 SetLastError(0xdeadbeef);
426 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
427 ok( !handle2
, "OpenWaitableTimer succeeded\n");
428 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
430 CloseHandle( handle
);
433 static HANDLE sem
= 0;
435 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
437 ReleaseSemaphore(sem
, 1, NULL
);
440 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
442 static void test_iocp_callback(void)
444 char temp_path
[MAX_PATH
];
445 char filename
[MAX_PATH
];
448 static const char prefix
[] = "pfx";
450 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
452 const char *buffer
= "12345678123456781234567812345678";
453 OVERLAPPED overlapped
;
455 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
456 if(!p_BindIoCompletionCallback
) {
457 skip("BindIoCompletionCallback not found in this DLL\n");
461 sem
= CreateSemaphore(NULL
, 0, 1, NULL
);
462 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
464 ret
= GetTempPathA(MAX_PATH
, temp_path
);
465 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
466 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
468 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
469 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
471 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
472 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
473 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
475 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
476 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
477 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
479 ret
= CloseHandle(hFile
);
480 ok( ret
, "CloseHandle: error %d\n", GetLastError());
481 ret
= DeleteFileA(filename
);
482 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
484 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
485 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
486 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
488 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
489 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
491 memset(&overlapped
, 0, sizeof(overlapped
));
492 retb
= WriteFile(hFile
, (const void *) buffer
, 4, &bytesWritten
, &overlapped
);
493 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
495 ret
= WaitForSingleObject(sem
, 5000);
496 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
499 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
500 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
501 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
502 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
503 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
504 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
506 ret
= CloseHandle(hFile
);
507 ok( ret
, "CloseHandle: error %d\n", GetLastError());
508 ret
= DeleteFileA(filename
);
509 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
511 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
512 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
513 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
514 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
515 ok(retb
== TRUE
, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
516 ret
= CloseHandle(hFile
);
517 ok( ret
, "CloseHandle: error %d\n", GetLastError());
518 ret
= DeleteFileA(filename
);
519 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
521 /* win2k3 requires the Flags parameter to be zero */
522 SetLastError(0xdeadbeef);
523 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
524 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
525 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
526 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
528 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
529 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
531 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
532 ret
= CloseHandle(hFile
);
533 ok( ret
, "CloseHandle: error %d\n", GetLastError());
534 ret
= DeleteFileA(filename
);
535 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
537 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
538 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
539 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Last error is %d\n", GetLastError());
542 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
545 ok(timedOut
, "Timer callbacks should always time out\n");
549 static void test_timer_queue(void)
551 HANDLE q
, t1
, t2
, t3
, t4
, t5
;
552 int n1
, n2
, n3
, n4
, n5
;
556 if (!pCreateTimerQueue
|| !pCreateTimerQueueTimer
|| !pDeleteTimerQueueEx
) {
557 skip("TimerQueue API not present\n");
561 /* Test asynchronous deletion of the queue. */
562 q
= pCreateTimerQueue();
564 ok(q
!= NULL
, "CreateTimerQueue\n");
566 SetLastError(0xdeadbeef);
567 ret
= pDeleteTimerQueueEx(q
, NULL
);
568 ok(!ret
, "DeleteTimerQueueEx\n");
570 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueEx\n");
572 /* Test synchronous deletion of the queue and running timers. */
573 q
= pCreateTimerQueue();
575 ok(q
!= NULL
, "CreateTimerQueue\n");
580 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
582 ok(ret
, "CreateTimerQueueTimer\n");
587 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
589 ok(ret
, "CreateTimerQueueTimer\n");
594 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
596 ok(ret
, "CreateTimerQueueTimer\n");
598 /* Start really late (it won't start). */
601 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
603 ok(ret
, "CreateTimerQueueTimer\n");
605 /* Start soon, but delay so long it won't run again. */
608 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
610 ok(ret
, "CreateTimerQueueTimer\n");
612 /* Give them a chance to do some work. */
615 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
618 ok(ret
, "DeleteTimerQueueEx\n");
619 ok(n1
== 1, "Timer callback 1\n");
620 ok(n2
< n3
, "Timer callback 2 should be much slower than 3\n");
622 ok(n4
== 0, "Timer callback 4\n");
624 ok(n5
== 1, "Timer callback 5\n");
626 /* Test synchronous deletion of the queue with event trigger. */
627 e
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
630 skip("Failed to create timer queue descruction event\n");
634 q
= pCreateTimerQueue();
636 ok(q
!= NULL
, "CreateTimerQueue\n");
638 SetLastError(0xdeadbeef);
639 ret
= pDeleteTimerQueueEx(q
, e
);
640 ok(!ret
, "DeleteTimerQueueEx\n");
643 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueEx\n");
644 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
645 "Timer destruction event not triggered\n");
652 HMODULE hdll
= GetModuleHandle("kernel32");
653 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
654 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
655 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
656 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
657 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
659 test_signalandwait();
664 test_waitable_timer();
665 test_iocp_callback();