Merge from amd64-branch:
[reactos.git] / rostests / winetests / kernel32 / sync.c
1 /*
2 * Synchronization tests
3 *
4 * Copyright 2005 Mike McCormack for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define _WIN32_WINNT 0x500
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windef.h>
26 #include <winbase.h>
27
28 #include "wine/test.h"
29
30 static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG);
31 static HANDLE (WINAPI *pCreateTimerQueue)(void);
32 static BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK,
33 PVOID, DWORD, DWORD, ULONG);
34 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR);
35 static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE);
36 static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE);
37 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR);
38
39 static void test_signalandwait(void)
40 {
41 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
42 HMODULE kernel32;
43 DWORD r;
44 int i;
45 HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
46
47 kernel32 = GetModuleHandle("kernel32");
48 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
49
50 if (!pSignalObjectAndWait)
51 return;
52
53 /* invalid parameters */
54 r = pSignalObjectAndWait(NULL, NULL, 0, 0);
55 if (r == ERROR_INVALID_FUNCTION)
56 {
57 win_skip("SignalObjectAndWait is not implemented\n");
58 return; /* Win98/ME */
59 }
60 ok( r == WAIT_FAILED, "should fail\n");
61
62 event[0] = CreateEvent(NULL, 0, 0, NULL);
63 event[1] = CreateEvent(NULL, 1, 1, NULL);
64
65 ok( event[0] && event[1], "failed to create event flags\n");
66
67 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
68 ok( r == WAIT_FAILED, "should fail\n");
69
70 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
71 ok( r == WAIT_FAILED, "should fail\n");
72
73
74 /* valid parameters */
75 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
76 ok( r == WAIT_OBJECT_0, "should succeed\n");
77
78 /* event[0] is now signalled */
79 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
80 ok( r == WAIT_OBJECT_0, "should succeed\n");
81
82 /* event[0] is not signalled */
83 r = WaitForSingleObject(event[0], 0);
84 ok( r == WAIT_TIMEOUT, "event was signalled\n");
85
86 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
87 ok( r == WAIT_OBJECT_0, "should succeed\n");
88
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");
93
94 CloseHandle(event[0]);
95 CloseHandle(event[1]);
96
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++)
100 {
101 maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
102 ok( maxevents[i] != 0, "should create enough events\n");
103 }
104 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
105 ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
106
107 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
108 if (maxevents[i]) CloseHandle(maxevents[i]);
109
110 /* semaphores */
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");
114
115 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
116 ok( r == WAIT_OBJECT_0, "should succeed\n");
117
118 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
119 ok( r == WAIT_FAILED, "should fail\n");
120
121 r = ReleaseSemaphore(semaphore[0],1,NULL);
122 ok( r == FALSE, "should fail\n");
123
124 r = ReleaseSemaphore(semaphore[1],1,NULL);
125 ok( r == TRUE, "should succeed\n");
126
127 CloseHandle(semaphore[0]);
128 CloseHandle(semaphore[1]);
129
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");
136 CloseHandle(file);
137 }
138
139 static void test_mutex(void)
140 {
141 DWORD wait_ret;
142 BOOL ret;
143 HANDLE hCreated;
144 HANDLE hOpened;
145
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);
150
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());
160
161 /* test case sensitivity */
162
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());
169
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());
176
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);
182
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);
188
189 CloseHandle(hCreated);
190 }
191
192 static void test_slist(void)
193 {
194 struct item
195 {
196 SLIST_ENTRY entry;
197 int value;
198 } item1, item2, item3, *pitem;
199
200 SLIST_HEADER slist_header;
201 PSLIST_ENTRY entry;
202 USHORT size;
203
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);
209 HMODULE kernel32;
210
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)
222 {
223 win_skip("some required slist entrypoints were not found, skipping tests\n");
224 return;
225 }
226
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);
231
232 item1.value = 1;
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);
237
238 item2.value = 2;
239 entry = pInterlockedPushEntrySList(&slist_header, &item2.entry);
240 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
241 if (entry != NULL)
242 {
243 pitem = (struct item*) entry;
244 ok(pitem->value == 1, "previous entry in slist wasn't the one added\n");
245 }
246 size = pQueryDepthSList(&slist_header);
247 ok(size == 2, "slist with 2 items has size %d\n", size);
248
249 item3.value = 3;
250 entry = pInterlockedPushEntrySList(&slist_header, &item3.entry);
251 ok(entry != NULL, "previous entry in non-empty slist was NULL\n");
252 if (entry != NULL)
253 {
254 pitem = (struct item*) entry;
255 ok(pitem->value == 2, "previous entry in slist wasn't the one added\n");
256 }
257 size = pQueryDepthSList(&slist_header);
258 ok(size == 3, "slist with 3 items has size %d\n", size);
259
260 entry = pInterlockedPopEntrySList(&slist_header);
261 ok(entry != NULL, "entry shouldn't be NULL\n");
262 if (entry != NULL)
263 {
264 pitem = (struct item*) entry;
265 ok(pitem->value == 3, "unexpected entry removed\n");
266 }
267 size = pQueryDepthSList(&slist_header);
268 ok(size == 2, "slist with 2 items has size %d\n", size);
269
270 entry = pInterlockedFlushSList(&slist_header);
271 size = pQueryDepthSList(&slist_header);
272 ok(size == 0, "flushed slist should be empty, size is %d\n", size);
273 if (size == 0)
274 {
275 ok(pInterlockedPopEntrySList(&slist_header) == NULL,
276 "popping empty slist didn't return NULL\n");
277 }
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");
280 }
281
282 static void test_event(void)
283 {
284 HANDLE handle, handle2;
285 SECURITY_ATTRIBUTES sa;
286 SECURITY_DESCRIPTOR sd;
287 ACL acl;
288
289 /* no sd */
290 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event");
291 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
292 CloseHandle(handle);
293
294 sa.nLength = sizeof(sa);
295 sa.lpSecurityDescriptor = &sd;
296 sa.bInheritHandle = FALSE;
297
298 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
299
300 /* blank sd */
301 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event");
302 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError());
303 CloseHandle(handle);
304
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());
309 CloseHandle(handle);
310
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());
316 CloseHandle(handle);
317
318 /* test case sensitivity */
319
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());
324
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 );
330
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 );
336
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 );
341
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());
348
349 CloseHandle( handle );
350 }
351
352 static void test_semaphore(void)
353 {
354 HANDLE handle, handle2;
355
356 /* test case sensitivity */
357
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());
362
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 );
368
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 );
374
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 );
379
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());
386
387 CloseHandle( handle );
388 }
389
390 static void test_waitable_timer(void)
391 {
392 HANDLE handle, handle2;
393
394 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA)
395 {
396 win_skip("{Create,Open}WaitableTimerA() is not available\n");
397 return;
398 }
399
400 /* test case sensitivity */
401
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());
406
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 );
412
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 );
418
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 );
423
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());
430
431 CloseHandle( handle );
432 }
433
434 static HANDLE sem = 0;
435
436 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
437 {
438 ReleaseSemaphore(sem, 1, NULL);
439 }
440
441 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL;
442
443 static void test_iocp_callback(void)
444 {
445 char temp_path[MAX_PATH];
446 char filename[MAX_PATH];
447 DWORD ret;
448 BOOL retb;
449 static const char prefix[] = "pfx";
450 HANDLE hFile;
451 HMODULE hmod = GetModuleHandleA("kernel32.dll");
452 DWORD bytesWritten;
453 const char *buffer = "12345678123456781234567812345678";
454 OVERLAPPED overlapped;
455
456 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback");
457 if(!p_BindIoCompletionCallback) {
458 win_skip("BindIoCompletionCallback not found in this DLL\n");
459 return;
460 }
461
462 sem = CreateSemaphore(NULL, 0, 1, NULL);
463 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n");
464
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");
468
469 ret = GetTempFileNameA(temp_path, prefix, 0, filename);
470 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
471
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());
475
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());
479
480 ret = CloseHandle(hFile);
481 ok( ret, "CloseHandle: error %d\n", GetLastError());
482 ret = DeleteFileA(filename);
483 ok( ret, "DeleteFileA: error %d\n", GetLastError());
484
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());
488
489 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0);
490 ok(retb == TRUE, "BindIoCompletionCallback failed\n");
491
492 memset(&overlapped, 0, sizeof(overlapped));
493 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped);
494 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError());
495
496 ret = WaitForSingleObject(sem, 5000);
497 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n");
498 CloseHandle(sem);
499
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());
506
507 ret = CloseHandle(hFile);
508 ok( ret, "CloseHandle: error %d\n", GetLastError());
509 ret = DeleteFileA(filename);
510 ok( ret, "DeleteFileA: error %d\n", GetLastError());
511
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);
518 if (!retb)
519 ok(GetLastError() == ERROR_INVALID_PARAMETER,
520 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
521 else
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());
527
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());
533 }
534
535 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut)
536 {
537 int *pn = p;
538 ok(timedOut, "Timer callbacks should always time out\n");
539 ++*pn;
540 }
541
542 struct timer_queue_data1
543 {
544 int num_calls;
545 int max_calls;
546 HANDLE q, t;
547 };
548
549 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
550 {
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)
554 {
555 BOOL ret;
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");
562 }
563 }
564
565 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
566 {
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)
570 {
571 /* Basically kill the timer since it won't have time to run
572 again. */
573 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0);
574 ok(ret, "ChangeTimerQueueTimer\n");
575 }
576 }
577
578 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
579 {
580 struct timer_queue_data1 *d = p;
581 ok(timedOut, "Timer callbacks should always time out\n");
582 if (d->t)
583 {
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");
591 ++d->num_calls;
592 }
593 }
594
595 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut)
596 {
597 DWORD_PTR delay = (DWORD_PTR) p;
598 ok(timedOut, "Timer callbacks should always time out\n");
599 if (delay)
600 Sleep(delay);
601 }
602
603 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut)
604 {
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)
610 {
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. */
616 BOOL ret;
617 HANDLE t;
618
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");
624
625 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0);
626 ok(ret, "CreateTimerQueueTimer\n");
627 ok(t != NULL, "CreateTimerQueueTimer\n");
628
629 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE);
630 ok(ret, "DeleteTimerQueueTimer\n");
631
632 /* Now we stay alive by hanging around in the callback. */
633 Sleep(500);
634 }
635 }
636
637 static void test_timer_queue(void)
638 {
639 HANDLE q, t1, t2, t3, t4, t5;
640 int n1, n2, n3, n4, n5;
641 struct timer_queue_data1 d1, d2, d3, d4;
642 HANDLE e, et1, et2;
643 BOOL ret;
644
645 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer
646 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer)
647 {
648 win_skip("TimerQueue API not present\n");
649 return;
650 }
651
652 /* Test asynchronous deletion of the queue. */
653 q = pCreateTimerQueue();
654 ok(q != NULL, "CreateTimerQueue\n");
655
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",
660 GetLastError());
661
662 /* Test synchronous deletion of the queue and running timers. */
663 q = pCreateTimerQueue();
664 ok(q != NULL, "CreateTimerQueue\n");
665
666 /* Called once. */
667 t1 = NULL;
668 n1 = 0;
669 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0,
670 0, 0);
671 ok(ret, "CreateTimerQueueTimer\n");
672 ok(t1 != NULL, "CreateTimerQueueTimer\n");
673
674 /* A slow one. */
675 t2 = NULL;
676 n2 = 0;
677 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0,
678 100, 0);
679 ok(ret, "CreateTimerQueueTimer\n");
680 ok(t2 != NULL, "CreateTimerQueueTimer\n");
681
682 /* A fast one. */
683 t3 = NULL;
684 n3 = 0;
685 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0,
686 10, 0);
687 ok(ret, "CreateTimerQueueTimer\n");
688 ok(t3 != NULL, "CreateTimerQueueTimer\n");
689
690 /* Start really late (it won't start). */
691 t4 = NULL;
692 n4 = 0;
693 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000,
694 10, 0);
695 ok(ret, "CreateTimerQueueTimer\n");
696 ok(t4 != NULL, "CreateTimerQueueTimer\n");
697
698 /* Start soon, but delay so long it won't run again. */
699 t5 = NULL;
700 n5 = 0;
701 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0,
702 10000, 0);
703 ok(ret, "CreateTimerQueueTimer\n");
704 ok(t5 != NULL, "CreateTimerQueueTimer\n");
705
706 /* Give them a chance to do some work. */
707 Sleep(500);
708
709 /* Test deleting a once-only timer. */
710 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE);
711 ok(ret, "DeleteTimerQueueTimer\n");
712
713 /* A periodic timer. */
714 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
715 ok(ret, "DeleteTimerQueueTimer\n");
716
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");
723
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)
729 {
730 skip("Failed to create timer queue descruction event\n");
731 return;
732 }
733
734 q = pCreateTimerQueue();
735 ok(q != NULL, "CreateTimerQueue\n");
736
737 /* Run once and finish quickly (should be done when we delete it). */
738 t1 = NULL;
739 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0);
740 ok(ret, "CreateTimerQueueTimer\n");
741 ok(t1 != NULL, "CreateTimerQueueTimer\n");
742
743 /* Run once and finish slowly (shouldn't be done when we delete it). */
744 t2 = NULL;
745 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0,
746 0, 0);
747 ok(ret, "CreateTimerQueueTimer\n");
748 ok(t2 != NULL, "CreateTimerQueueTimer\n");
749
750 /* Run once and finish quickly (should be done when we delete it). */
751 t3 = NULL;
752 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0);
753 ok(ret, "CreateTimerQueueTimer\n");
754 ok(t3 != NULL, "CreateTimerQueueTimer\n");
755
756 /* Run once and finish slowly (shouldn't be done when we delete it). */
757 t4 = NULL;
758 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0,
759 0, 0);
760 ok(ret, "CreateTimerQueueTimer\n");
761 ok(t4 != NULL, "CreateTimerQueueTimer\n");
762
763 /* Give them a chance to start. */
764 Sleep(400);
765
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",
772 GetLastError());
773
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",
779 GetLastError());
780
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",
786 GetLastError());
787 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0,
788 "Timer destruction event not triggered\n");
789
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",
795 GetLastError());
796 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0,
797 "Timer destruction event not triggered\n");
798
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",
803 GetLastError());
804 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0,
805 "Queue destruction event not triggered\n");
806 CloseHandle(e);
807
808 /* Test deleting/changing a timer in execution. */
809 q = pCreateTimerQueue();
810 ok(q != NULL, "CreateTimerQueue\n");
811
812 /* Test changing a once-only timer before it fires (this is allowed,
813 whereas after it fires you cannot). */
814 n1 = 0;
815 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000,
816 0, 0);
817 ok(ret, "CreateTimerQueueTimer\n");
818 ok(t1 != NULL, "CreateTimerQueueTimer\n");
819 ret = pChangeTimerQueueTimer(q, t1, 0, 0);
820 ok(ret, "ChangeTimerQueueTimer\n");
821
822 d2.t = t2 = NULL;
823 d2.num_calls = 0;
824 d2.max_calls = 3;
825 d2.q = q;
826 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10,
827 10, 0);
828 d2.t = t2;
829 ok(ret, "CreateTimerQueueTimer\n");
830 ok(t2 != NULL, "CreateTimerQueueTimer\n");
831
832 d3.t = t3 = NULL;
833 d3.num_calls = 0;
834 d3.max_calls = 4;
835 d3.q = q;
836 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10,
837 10, 0);
838 d3.t = t3;
839 ok(ret, "CreateTimerQueueTimer\n");
840 ok(t3 != NULL, "CreateTimerQueueTimer\n");
841
842 d4.t = t4 = NULL;
843 d4.num_calls = 0;
844 d4.q = q;
845 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10,
846 0, 0);
847 d4.t = t4;
848 ok(ret, "CreateTimerQueueTimer\n");
849 ok(t4 != NULL, "CreateTimerQueueTimer\n");
850
851 Sleep(500);
852
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");
859
860 /* Test an obscure bug that was in the original implementation. */
861 q = pCreateTimerQueue();
862 ok(q != NULL, "CreateTimerQueue\n");
863
864 /* All the work is done in the callback. */
865 d1.t = t1 = NULL;
866 d1.num_calls = 0;
867 d1.q = q;
868 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100,
869 100, WT_EXECUTELONGFUNCTION);
870 d1.t = t1;
871 ok(ret, "CreateTimerQueueTimer\n");
872 ok(t1 != NULL, "CreateTimerQueueTimer\n");
873
874 Sleep(750);
875
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",
880 GetLastError());
881 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n");
882
883 /* Test functions on the default timer queue. */
884 t1 = NULL;
885 n1 = 0;
886 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000,
887 1000, 0);
888 ok(ret, "CreateTimerQueueTimer, default queue\n");
889 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n");
890
891 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
892 ok(ret, "ChangeTimerQueueTimer, default queue\n");
893
894 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
895 ok(ret, "DeleteTimerQueueTimer, default queue\n");
896
897 /* Try mixing default and non-default queues. Apparently this works. */
898 q = pCreateTimerQueue();
899 ok(q != NULL, "CreateTimerQueue\n");
900
901 t1 = NULL;
902 n1 = 0;
903 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000,
904 1000, 0);
905 ok(ret, "CreateTimerQueueTimer\n");
906 ok(t1 != NULL, "CreateTimerQueueTimer\n");
907
908 t2 = NULL;
909 n2 = 0;
910 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000,
911 1000, 0);
912 ok(ret, "CreateTimerQueueTimer\n");
913 ok(t2 != NULL, "CreateTimerQueueTimer\n");
914
915 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000);
916 ok(ret, "ChangeTimerQueueTimer\n");
917
918 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000);
919 ok(ret, "ChangeTimerQueueTimer\n");
920
921 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE);
922 ok(ret, "DeleteTimerQueueTimer\n");
923
924 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE);
925 ok(ret, "DeleteTimerQueueTimer\n");
926
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",
933 GetLastError());
934
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",
939 GetLastError());
940 }
941
942 START_TEST(sync)
943 {
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");
952
953 test_signalandwait();
954 test_mutex();
955 test_slist();
956 test_event();
957 test_semaphore();
958 test_waitable_timer();
959 test_iocp_callback();
960 test_timer_queue();
961 }