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 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 trace("SignalObjectAndWait not implemented, skipping tests\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
, test_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(&test_header
, 0, sizeof(test_header
));
228 memset(&slist_header
, 0xFF, sizeof(slist_header
));
229 pInitializeSListHead(&slist_header
);
230 ok(memcmp(&test_header
, &slist_header
, sizeof(SLIST_HEADER
)) == 0,
231 "InitializeSListHead didn't zero-fill list header\n");
232 size
= pQueryDepthSList(&slist_header
);
233 ok(size
== 0, "initially created slist has size %d, expected 0\n", size
);
236 ok(pInterlockedPushEntrySList(&slist_header
, &item1
.entry
) == NULL
,
237 "previous entry in empty slist wasn't NULL\n");
238 size
= pQueryDepthSList(&slist_header
);
239 ok(size
== 1, "slist with 1 item has size %d\n", size
);
242 entry
= pInterlockedPushEntrySList(&slist_header
, &item2
.entry
);
243 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
246 pitem
= (struct item
*) entry
;
247 ok(pitem
->value
== 1, "previous entry in slist wasn't the one added\n");
249 size
= pQueryDepthSList(&slist_header
);
250 ok(size
== 2, "slist with 2 items has size %d\n", size
);
253 entry
= pInterlockedPushEntrySList(&slist_header
, &item3
.entry
);
254 ok(entry
!= NULL
, "previous entry in non-empty slist was NULL\n");
257 pitem
= (struct item
*) entry
;
258 ok(pitem
->value
== 2, "previous entry in slist wasn't the one added\n");
260 size
= pQueryDepthSList(&slist_header
);
261 ok(size
== 3, "slist with 3 items has size %d\n", size
);
263 entry
= pInterlockedPopEntrySList(&slist_header
);
264 ok(entry
!= NULL
, "entry shouldn't be NULL\n");
267 pitem
= (struct item
*) entry
;
268 ok(pitem
->value
== 3, "unexpected entry removed\n");
270 size
= pQueryDepthSList(&slist_header
);
271 ok(size
== 2, "slist with 2 items has size %d\n", size
);
273 entry
= pInterlockedFlushSList(&slist_header
);
274 size
= pQueryDepthSList(&slist_header
);
275 ok(size
== 0, "flushed slist should be empty, size is %d\n", size
);
278 ok(pInterlockedPopEntrySList(&slist_header
) == NULL
,
279 "popping empty slist didn't return NULL\n");
281 ok(((struct item
*)entry
)->value
== 2, "item 2 not in front of list\n");
282 ok(((struct item
*)entry
->Next
)->value
== 1, "item 1 not at the back of list\n");
285 static void test_event(void)
287 HANDLE handle
, handle2
;
288 SECURITY_ATTRIBUTES sa
;
289 SECURITY_DESCRIPTOR sd
;
293 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
294 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
297 sa
.nLength
= sizeof(sa
);
298 sa
.lpSecurityDescriptor
= &sd
;
299 sa
.bInheritHandle
= FALSE
;
301 InitializeSecurityDescriptor(&sd
, SECURITY_DESCRIPTOR_REVISION
);
304 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
305 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
308 /* sd with NULL dacl */
309 SetSecurityDescriptorDacl(&sd
, TRUE
, NULL
, FALSE
);
310 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
311 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
314 /* sd with empty dacl */
315 InitializeAcl(&acl
, sizeof(acl
), ACL_REVISION
);
316 SetSecurityDescriptorDacl(&sd
, TRUE
, &acl
, FALSE
);
317 handle
= CreateEventA(&sa
, FALSE
, FALSE
, __FILE__
": Test Event");
318 ok(handle
!= NULL
, "CreateEventW with blank sd failed with error %d\n", GetLastError());
321 /* test case sensitivity */
323 SetLastError(0xdeadbeef);
324 handle
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
325 ok( handle
!= NULL
, "CreateEvent failed with error %u\n", GetLastError());
326 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
328 SetLastError(0xdeadbeef);
329 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": Test Event");
330 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
331 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
332 CloseHandle( handle2
);
334 SetLastError(0xdeadbeef);
335 handle2
= CreateEventA(NULL
, FALSE
, FALSE
, __FILE__
": TEST EVENT");
336 ok( handle2
!= NULL
, "CreateEvent failed with error %d\n", GetLastError());
337 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
338 CloseHandle( handle2
);
340 SetLastError(0xdeadbeef);
341 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": Test Event");
342 ok( handle2
!= NULL
, "OpenEvent failed with error %d\n", GetLastError());
343 CloseHandle( handle2
);
345 SetLastError(0xdeadbeef);
346 handle2
= OpenEventA( EVENT_ALL_ACCESS
, FALSE
, __FILE__
": TEST EVENT");
347 ok( !handle2
, "OpenEvent succeeded\n");
348 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
349 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
350 "wrong error %u\n", GetLastError());
352 CloseHandle( handle
);
355 static void test_semaphore(void)
357 HANDLE handle
, handle2
;
359 /* test case sensitivity */
361 SetLastError(0xdeadbeef);
362 handle
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
363 ok(handle
!= NULL
, "CreateSemaphore failed with error %u\n", GetLastError());
364 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
366 SetLastError(0xdeadbeef);
367 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": Test Semaphore");
368 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
369 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
370 CloseHandle( handle2
);
372 SetLastError(0xdeadbeef);
373 handle2
= CreateSemaphoreA(NULL
, 0, 1, __FILE__
": TEST SEMAPHORE");
374 ok( handle2
!= NULL
, "CreateSemaphore failed with error %d\n", GetLastError());
375 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
376 CloseHandle( handle2
);
378 SetLastError(0xdeadbeef);
379 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": Test Semaphore");
380 ok( handle2
!= NULL
, "OpenSemaphore failed with error %d\n", GetLastError());
381 CloseHandle( handle2
);
383 SetLastError(0xdeadbeef);
384 handle2
= OpenSemaphoreA( SEMAPHORE_ALL_ACCESS
, FALSE
, __FILE__
": TEST SEMAPHORE");
385 ok( !handle2
, "OpenSemaphore succeeded\n");
386 ok( GetLastError() == ERROR_FILE_NOT_FOUND
||
387 GetLastError() == ERROR_INVALID_NAME
, /* win9x */
388 "wrong error %u\n", GetLastError());
390 CloseHandle( handle
);
393 static void test_waitable_timer(void)
395 HANDLE handle
, handle2
;
397 if (!pCreateWaitableTimerA
|| !pOpenWaitableTimerA
)
399 skip("{Create,Open}WaitableTimerA() is not available\n");
403 /* test case sensitivity */
405 SetLastError(0xdeadbeef);
406 handle
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
407 ok(handle
!= NULL
, "CreateWaitableTimer failed with error %u\n", GetLastError());
408 ok(GetLastError() == 0, "wrong error %u\n", GetLastError());
410 SetLastError(0xdeadbeef);
411 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": Test WaitableTimer");
412 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
413 ok( GetLastError() == ERROR_ALREADY_EXISTS
, "wrong error %u\n", GetLastError());
414 CloseHandle( handle2
);
416 SetLastError(0xdeadbeef);
417 handle2
= pCreateWaitableTimerA(NULL
, FALSE
, __FILE__
": TEST WAITABLETIMER");
418 ok( handle2
!= NULL
, "CreateWaitableTimer failed with error %d\n", GetLastError());
419 ok( GetLastError() == 0, "wrong error %u\n", GetLastError());
420 CloseHandle( handle2
);
422 SetLastError(0xdeadbeef);
423 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": Test WaitableTimer");
424 ok( handle2
!= NULL
, "OpenWaitableTimer failed with error %d\n", GetLastError());
425 CloseHandle( handle2
);
427 SetLastError(0xdeadbeef);
428 handle2
= pOpenWaitableTimerA( TIMER_ALL_ACCESS
, FALSE
, __FILE__
": TEST WAITABLETIMER");
429 ok( !handle2
, "OpenWaitableTimer succeeded\n");
430 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError());
432 CloseHandle( handle
);
435 static HANDLE sem
= 0;
437 static void CALLBACK
iocp_callback(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
439 ReleaseSemaphore(sem
, 1, NULL
);
442 static BOOL (WINAPI
*p_BindIoCompletionCallback
)( HANDLE FileHandle
, LPOVERLAPPED_COMPLETION_ROUTINE Function
, ULONG Flags
) = NULL
;
444 static void test_iocp_callback(void)
446 char temp_path
[MAX_PATH
];
447 char filename
[MAX_PATH
];
450 static const char prefix
[] = "pfx";
452 HMODULE hmod
= GetModuleHandleA("kernel32.dll");
454 const char *buffer
= "12345678123456781234567812345678";
455 OVERLAPPED overlapped
;
457 p_BindIoCompletionCallback
= (void*)GetProcAddress(hmod
, "BindIoCompletionCallback");
458 if(!p_BindIoCompletionCallback
) {
459 skip("BindIoCompletionCallback not found in this DLL\n");
463 sem
= CreateSemaphore(NULL
, 0, 1, NULL
);
464 ok(sem
!= INVALID_HANDLE_VALUE
, "Creating a semaphore failed\n");
466 ret
= GetTempPathA(MAX_PATH
, temp_path
);
467 ok(ret
!= 0, "GetTempPathA error %d\n", GetLastError());
468 ok(ret
< MAX_PATH
, "temp path should fit into MAX_PATH\n");
470 ret
= GetTempFileNameA(temp_path
, prefix
, 0, filename
);
471 ok(ret
!= 0, "GetTempFileNameA error %d\n", GetLastError());
473 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
474 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
, 0);
475 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
477 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
478 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n");
479 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
481 ret
= CloseHandle(hFile
);
482 ok( ret
, "CloseHandle: error %d\n", GetLastError());
483 ret
= DeleteFileA(filename
);
484 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
486 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
487 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
488 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
490 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
491 ok(retb
== TRUE
, "BindIoCompletionCallback failed\n");
493 memset(&overlapped
, 0, sizeof(overlapped
));
494 retb
= WriteFile(hFile
, (const void *) buffer
, 4, &bytesWritten
, &overlapped
);
495 ok(retb
== TRUE
|| GetLastError() == ERROR_IO_PENDING
, "WriteFile failed, lastError = %d\n", GetLastError());
497 ret
= WaitForSingleObject(sem
, 5000);
498 ok(ret
== WAIT_OBJECT_0
, "Wait for the IO completion callback failed\n");
501 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 0);
502 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n");
503 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
504 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
505 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded when setting the callback to NULL\n");
506 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Last error is %d\n", GetLastError());
508 ret
= CloseHandle(hFile
);
509 ok( ret
, "CloseHandle: error %d\n", GetLastError());
510 ret
= DeleteFileA(filename
);
511 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
513 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
514 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
515 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
516 retb
= p_BindIoCompletionCallback(hFile
, NULL
, 0);
517 ok(retb
== TRUE
, "BindIoCompletionCallback failed with a NULL callback(first time set)\n");
518 ret
= CloseHandle(hFile
);
519 ok( ret
, "CloseHandle: error %d\n", GetLastError());
520 ret
= DeleteFileA(filename
);
521 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
523 /* win2k3 requires the Flags parameter to be zero */
524 SetLastError(0xdeadbeef);
525 hFile
= CreateFileA(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
526 CREATE_ALWAYS
, FILE_FLAG_RANDOM_ACCESS
| FILE_FLAG_OVERLAPPED
, 0);
527 ok(hFile
!= INVALID_HANDLE_VALUE
, "CreateFileA: error %d\n", GetLastError());
528 retb
= p_BindIoCompletionCallback(hFile
, iocp_callback
, 12345);
530 ok(GetLastError() == ERROR_INVALID_PARAMETER
,
531 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
533 ok(retb
== TRUE
, "BindIoCompletionCallback failed with Flags != 0\n");
534 ret
= CloseHandle(hFile
);
535 ok( ret
, "CloseHandle: error %d\n", GetLastError());
536 ret
= DeleteFileA(filename
);
537 ok( ret
, "DeleteFileA: error %d\n", GetLastError());
539 retb
= p_BindIoCompletionCallback(NULL
, iocp_callback
, 0);
540 ok(retb
== FALSE
, "BindIoCompletionCallback succeeded on a NULL file\n");
541 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Last error is %d\n", GetLastError());
544 static void CALLBACK
timer_queue_cb1(PVOID p
, BOOLEAN timedOut
)
547 ok(timedOut
, "Timer callbacks should always time out\n");
551 struct timer_queue_data1
558 static void CALLBACK
timer_queue_cb2(PVOID p
, BOOLEAN timedOut
)
560 struct timer_queue_data1
*d
= p
;
561 ok(timedOut
, "Timer callbacks should always time out\n");
562 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
565 SetLastError(0xdeadbeef);
566 /* Note, XP SP2 does *not* do any deadlock checking, so passing
567 INVALID_HANDLE_VALUE here will just hang. */
568 ret
= pDeleteTimerQueueTimer(d
->q
, d
->t
, NULL
);
571 ok(!ret
, "DeleteTimerQueueTimer\n");
572 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueTimer\n");
577 static void CALLBACK
timer_queue_cb3(PVOID p
, BOOLEAN timedOut
)
579 struct timer_queue_data1
*d
= p
;
580 ok(timedOut
, "Timer callbacks should always time out\n");
581 if (d
->t
&& ++d
->num_calls
== d
->max_calls
)
583 /* Basically kill the timer since it won't have time to run
585 BOOL ret
= pChangeTimerQueueTimer(d
->q
, d
->t
, 10000, 0);
587 ok(ret
, "ChangeTimerQueueTimer\n");
591 static void test_timer_queue(void)
593 HANDLE q
, t1
, t2
, t3
, t4
, t5
;
594 int n1
, n2
, n3
, n4
, n5
;
595 struct timer_queue_data1 d2
, d3
;
599 if (!pChangeTimerQueueTimer
|| !pCreateTimerQueue
|| !pCreateTimerQueueTimer
600 || !pDeleteTimerQueueEx
|| !pDeleteTimerQueueTimer
)
602 skip("TimerQueue API not present\n");
606 /* Test asynchronous deletion of the queue. */
607 q
= pCreateTimerQueue();
609 ok(q
!= NULL
, "CreateTimerQueue\n");
611 SetLastError(0xdeadbeef);
612 ret
= pDeleteTimerQueueEx(q
, NULL
);
613 ok(!ret
, "DeleteTimerQueueEx\n");
615 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueEx\n");
617 /* Test synchronous deletion of the queue and running timers. */
618 q
= pCreateTimerQueue();
620 ok(q
!= NULL
, "CreateTimerQueue\n");
625 ret
= pCreateTimerQueueTimer(&t1
, q
, timer_queue_cb1
, &n1
, 0,
627 ok(ret
, "CreateTimerQueueTimer\n");
632 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb1
, &n2
, 0,
634 ok(ret
, "CreateTimerQueueTimer\n");
639 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb1
, &n3
, 0,
641 ok(ret
, "CreateTimerQueueTimer\n");
643 /* Start really late (it won't start). */
646 ret
= pCreateTimerQueueTimer(&t4
, q
, timer_queue_cb1
, &n4
, 10000,
648 ok(ret
, "CreateTimerQueueTimer\n");
650 /* Start soon, but delay so long it won't run again. */
653 ret
= pCreateTimerQueueTimer(&t5
, q
, timer_queue_cb1
, &n5
, 0,
655 ok(ret
, "CreateTimerQueueTimer\n");
657 /* Give them a chance to do some work. */
660 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
663 ok(ret
, "DeleteTimerQueueEx\n");
664 ok(n1
== 1, "Timer callback 1\n");
665 ok(n2
< n3
, "Timer callback 2 should be much slower than 3\n");
667 ok(n4
== 0, "Timer callback 4\n");
669 ok(n5
== 1, "Timer callback 5\n");
671 /* Test synchronous deletion of the queue with event trigger. */
672 e
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
675 skip("Failed to create timer queue descruction event\n");
679 q
= pCreateTimerQueue();
681 ok(q
!= NULL
, "CreateTimerQueue\n");
683 SetLastError(0xdeadbeef);
684 ret
= pDeleteTimerQueueEx(q
, e
);
685 ok(!ret
, "DeleteTimerQueueEx\n");
688 ok(GetLastError() == ERROR_IO_PENDING
, "DeleteTimerQueueEx\n");
689 ok(WaitForSingleObject(e
, 250) == WAIT_OBJECT_0
,
690 "Timer destruction event not triggered\n");
694 /* Test deleting/changing a timer in execution. */
695 q
= pCreateTimerQueue();
697 ok(q
!= NULL
, "CreateTimerQueue\n");
703 ret
= pCreateTimerQueueTimer(&t2
, q
, timer_queue_cb2
, &d2
, 10,
706 ok(ret
, "CreateTimerQueueTimer\n");
712 ret
= pCreateTimerQueueTimer(&t3
, q
, timer_queue_cb3
, &d3
, 10,
715 ok(ret
, "CreateTimerQueueTimer\n");
719 ret
= pDeleteTimerQueueEx(q
, INVALID_HANDLE_VALUE
);
722 ok(ret
, "DeleteTimerQueueEx\n");
723 ok(d2
.num_calls
== d2
.max_calls
, "DeleteTimerQueueTimer\n");
724 ok(d3
.num_calls
== d3
.max_calls
, "ChangeTimerQueueTimer\n");
730 HMODULE hdll
= GetModuleHandle("kernel32");
731 pChangeTimerQueueTimer
= (void*)GetProcAddress(hdll
, "ChangeTimerQueueTimer");
732 pCreateTimerQueue
= (void*)GetProcAddress(hdll
, "CreateTimerQueue");
733 pCreateTimerQueueTimer
= (void*)GetProcAddress(hdll
, "CreateTimerQueueTimer");
734 pCreateWaitableTimerA
= (void*)GetProcAddress(hdll
, "CreateWaitableTimerA");
735 pDeleteTimerQueueEx
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueEx");
736 pDeleteTimerQueueTimer
= (void*)GetProcAddress(hdll
, "DeleteTimerQueueTimer");
737 pOpenWaitableTimerA
= (void*)GetProcAddress(hdll
, "OpenWaitableTimerA");
739 test_signalandwait();
744 test_waitable_timer();
745 test_iocp_callback();