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 #ifndef __REACTOS__ 22 #define _WIN32_WINNT 0x500 23 #endif 24 #include <stdarg.h> 25 #include <stdlib.h> 26 #include <stdio.h> 27 #include <windef.h> 28 #include <winbase.h> 29 #include <winternl.h> 30 31 #include "wine/test.h" 32 33 #ifdef __REACTOS__ 34 #define QueryDepthSList(x) RtlQueryDepthSList(x) 35 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y) 36 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x) 37 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x) 38 #endif 39 40 #undef __fastcall 41 #define __fastcall __stdcall 42 43 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE); 44 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL); 45 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE); 46 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*); 47 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*); 48 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID); 49 50 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE); 51 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD); 52 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG); 53 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE); 54 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE); 55 56 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK); 57 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK); 58 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK); 59 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK); 60 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); 61 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); 62 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); 63 64 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); 65 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); 66 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); 67 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); 68 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, 69 PSLIST_ENTRY last, ULONG count); 70 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first, 71 PSLIST_ENTRY last, ULONG count); 72 73 #ifdef __i386__ 74 75 #include "pshpack1.h" 76 struct fastcall_thunk 77 { 78 BYTE pop_edx; /* popl %edx (ret addr) */ 79 BYTE pop_eax; /* popl %eax (func) */ 80 BYTE pop_ecx; /* popl %ecx (param 1) */ 81 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */ 82 WORD jmp_eax; /* jmp *%eax */ 83 }; 84 #include "poppack.h" 85 86 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d); 87 88 static void init_fastcall_thunk(void) 89 { 90 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 91 thunk->pop_edx = 0x5a; /* popl %edx */ 92 thunk->pop_eax = 0x58; /* popl %eax */ 93 thunk->pop_ecx = 0x59; /* popl %ecx */ 94 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */ 95 thunk->xchg[1] = 0x14; 96 thunk->xchg[2] = 0x24; 97 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */ 98 call_fastcall_func4 = (void *)thunk; 99 } 100 101 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \ 102 (const void *)(b), (const void *)(c), (const void *)(d)) 103 104 #else /* __i386__ */ 105 106 #define init_fastcall_thunk() do { } while(0) 107 #define call_func4(func, a, b, c, d) func(a, b, c, d) 108 109 #endif /* __i386__ */ 110 111 static void test_signalandwait(void) 112 { 113 DWORD r; 114 HANDLE event[2], semaphore[2], file; 115 int i; 116 117 /* invalid parameters */ 118 r = SignalObjectAndWait(NULL, NULL, 0, 0); 119 ok( r == WAIT_FAILED, "should fail\n"); 120 121 event[0] = CreateEventW(NULL, 0, 0, NULL); 122 event[1] = CreateEventW(NULL, 1, 1, NULL); 123 124 ok( event[0] && event[1], "failed to create event flags\n"); 125 126 r = SignalObjectAndWait(event[0], NULL, 0, FALSE); 127 ok( r == WAIT_FAILED, "should fail\n"); 128 129 r = SignalObjectAndWait(NULL, event[0], 0, FALSE); 130 ok( r == WAIT_FAILED, "should fail\n"); 131 132 133 /* valid parameters */ 134 r = SignalObjectAndWait(event[0], event[1], 0, FALSE); 135 ok( r == WAIT_OBJECT_0, "should succeed\n"); 136 137 /* event[0] is now signalled - we repeat this test multiple times 138 * to ensure that the wineserver handles this situation properly. */ 139 for (i = 0; i < 10000; i++) 140 { 141 r = SignalObjectAndWait(event[0], event[0], 0, FALSE); 142 ok(r == WAIT_OBJECT_0, "should succeed\n"); 143 } 144 145 /* event[0] is not signalled */ 146 r = WaitForSingleObject(event[0], 0); 147 ok( r == WAIT_TIMEOUT, "event was signalled\n"); 148 149 r = SignalObjectAndWait(event[0], event[0], 0, FALSE); 150 ok( r == WAIT_OBJECT_0, "should succeed\n"); 151 152 /* clear event[1] and check for a timeout */ 153 ok(ResetEvent(event[1]), "failed to clear event[1]\n"); 154 r = SignalObjectAndWait(event[0], event[1], 0, FALSE); 155 ok( r == WAIT_TIMEOUT, "should timeout\n"); 156 157 CloseHandle(event[0]); 158 CloseHandle(event[1]); 159 160 /* semaphores */ 161 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL ); 162 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL ); 163 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n"); 164 165 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 166 ok( r == WAIT_OBJECT_0, "should succeed\n"); 167 168 r = SignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 169 ok( r == WAIT_FAILED, "should fail\n"); 170 171 r = ReleaseSemaphore(semaphore[0],1,NULL); 172 ok( r == FALSE, "should fail\n"); 173 174 r = ReleaseSemaphore(semaphore[1],1,NULL); 175 ok( r == TRUE, "should succeed\n"); 176 177 CloseHandle(semaphore[0]); 178 CloseHandle(semaphore[1]); 179 180 /* try a registry key */ 181 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 182 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); 183 r = SignalObjectAndWait(file, file, 0, FALSE); 184 ok( r == WAIT_FAILED, "should fail\n"); 185 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n"); 186 CloseHandle(file); 187 } 188 189 static void test_mutex(void) 190 { 191 DWORD wait_ret; 192 BOOL ret; 193 HANDLE hCreated; 194 HANDLE hOpened; 195 int i; 196 DWORD failed = 0; 197 198 SetLastError(0xdeadbeef); 199 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 200 ok(hOpened == NULL, "OpenMutex succeeded\n"); 201 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 202 203 SetLastError(0xdeadbeef); 204 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex"); 205 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError()); 206 207 SetLastError(0xdeadbeef); 208 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 209 todo_wine 210 ok(hOpened == NULL, "OpenMutex succeeded\n"); 211 todo_wine 212 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError()); 213 214 SetLastError(0xdeadbeef); 215 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex"); 216 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 217 wait_ret = WaitForSingleObject(hOpened, INFINITE); 218 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError()); 219 CloseHandle(hOpened); 220 221 for(i=0; i < 31; i++) 222 { 223 wait_ret = WaitForSingleObject(hCreated, INFINITE); 224 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret); 225 } 226 227 SetLastError(0xdeadbeef); 228 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); 229 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 230 wait_ret = WaitForSingleObject(hOpened, INFINITE); 231 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); 232 CloseHandle(hOpened); 233 234 for (i = 0; i < 32; i++) 235 { 236 SetLastError(0xdeadbeef); 237 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex"); 238 if(hOpened != NULL) 239 { 240 SetLastError(0xdeadbeef); 241 ret = ReleaseMutex(hOpened); 242 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i); 243 CloseHandle(hOpened); 244 } 245 else 246 { 247 if ((1 << i) == ACCESS_SYSTEM_SECURITY) 248 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i); 249 else 250 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i); 251 ReleaseMutex(hCreated); 252 failed |=0x1 << i; 253 } 254 } 255 256 todo_wine 257 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed); 258 259 SetLastError(0xdeadbeef); 260 ret = ReleaseMutex(hCreated); 261 ok(!ret && (GetLastError() == ERROR_NOT_OWNER), 262 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError()); 263 264 /* test case sensitivity */ 265 266 SetLastError(0xdeadbeef); 267 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX"); 268 ok(!hOpened, "OpenMutex succeeded\n"); 269 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 270 271 SetLastError(0xdeadbeef); 272 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex"); 273 ok(!hOpened, "OpenMutex succeeded\n"); 274 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 275 276 SetLastError(0xdeadbeef); 277 hOpened = OpenMutexA(READ_CONTROL, FALSE, NULL); 278 ok(!hOpened, "OpenMutex succeeded\n"); 279 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 280 281 SetLastError(0xdeadbeef); 282 hOpened = OpenMutexW(READ_CONTROL, FALSE, NULL); 283 ok(!hOpened, "OpenMutex succeeded\n"); 284 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 285 286 SetLastError(0xdeadbeef); 287 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex"); 288 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 289 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 290 CloseHandle(hOpened); 291 292 SetLastError(0xdeadbeef); 293 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX"); 294 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 295 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 296 CloseHandle(hOpened); 297 298 CloseHandle(hCreated); 299 } 300 301 static void test_slist(void) 302 { 303 struct item 304 { 305 SLIST_ENTRY entry; 306 int value; 307 } item1, item2, item3, *item; 308 SLIST_HEADER slist_header; 309 SLIST_ENTRY *entry; 310 USHORT size; 311 int i; 312 313 item1.value = 1; 314 item2.value = 2; 315 item3.value = 3; 316 317 memset(&slist_header, 0xff, sizeof(slist_header)); 318 InitializeSListHead(&slist_header); 319 size = QueryDepthSList(&slist_header); 320 ok(size == 0, "Expected size == 0, got %u\n", size); 321 322 /* test PushEntry, PopEntry and Flush */ 323 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 324 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 325 size = QueryDepthSList(&slist_header); 326 ok(size == 1, "Expected size == 1, got %u\n", size); 327 328 entry = InterlockedPushEntrySList(&slist_header, &item2.entry); 329 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 330 item = CONTAINING_RECORD(entry, struct item, entry); 331 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 332 size = QueryDepthSList(&slist_header); 333 ok(size == 2, "Expected size == 2, got %u\n", size); 334 335 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 336 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 337 item = CONTAINING_RECORD(entry, struct item, entry); 338 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 339 size = QueryDepthSList(&slist_header); 340 ok(size == 3, "Expected size == 3, got %u\n", size); 341 342 entry = InterlockedPopEntrySList(&slist_header); 343 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 344 item = CONTAINING_RECORD(entry, struct item, entry); 345 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 346 size = QueryDepthSList(&slist_header); 347 ok(size == 2, "Expected size == 2, got %u\n", size); 348 349 entry = InterlockedFlushSList(&slist_header); 350 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 351 item = CONTAINING_RECORD(entry, struct item, entry); 352 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 353 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 354 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 355 size = QueryDepthSList(&slist_header); 356 ok(size == 0, "Expected size == 0, got %u\n", size); 357 entry = InterlockedPopEntrySList(&slist_header); 358 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 359 360 /* test RtlInterlockedPushListSList */ 361 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 362 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 363 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42); 364 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 365 item = CONTAINING_RECORD(entry, struct item, entry); 366 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 367 size = QueryDepthSList(&slist_header); 368 ok(size == 43, "Expected size == 43, got %u\n", size); 369 370 entry = InterlockedPopEntrySList(&slist_header); 371 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 372 item = CONTAINING_RECORD(entry, struct item, entry); 373 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 374 size = QueryDepthSList(&slist_header); 375 ok(size == 42, "Expected size == 42, got %u\n", size); 376 377 entry = InterlockedPopEntrySList(&slist_header); 378 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 379 item = CONTAINING_RECORD(entry, struct item, entry); 380 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 381 size = QueryDepthSList(&slist_header); 382 ok(size == 41, "Expected size == 41, got %u\n", size); 383 384 entry = InterlockedPopEntrySList(&slist_header); 385 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 386 item = CONTAINING_RECORD(entry, struct item, entry); 387 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 388 size = QueryDepthSList(&slist_header); 389 ok(size == 40, "Expected size == 40, got %u\n", size); 390 391 entry = InterlockedPopEntrySList(&slist_header); 392 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 393 size = QueryDepthSList(&slist_header); 394 ok(size == 40, "Expected size == 40, got %u\n", size); 395 396 entry = InterlockedFlushSList(&slist_header); 397 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 398 size = QueryDepthSList(&slist_header); 399 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size); 400 401 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 402 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 403 entry = InterlockedFlushSList(&slist_header); 404 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 405 item = CONTAINING_RECORD(entry, struct item, entry); 406 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 407 size = QueryDepthSList(&slist_header); 408 ok(size == 0, "Expected size == 0, got %u\n", size); 409 410 /* test RtlInterlockedPushListSListEx */ 411 if (pRtlInterlockedPushListSListEx) 412 { 413 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 414 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 415 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42); 416 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 417 item = CONTAINING_RECORD(entry, struct item, entry); 418 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 419 size = QueryDepthSList(&slist_header); 420 ok(size == 43, "Expected size == 43, got %u\n", size); 421 422 entry = InterlockedFlushSList(&slist_header); 423 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 424 item = CONTAINING_RECORD(entry, struct item, entry); 425 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 426 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 427 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 428 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 429 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 430 size = QueryDepthSList(&slist_header); 431 ok(size == 0, "Expected size == 0, got %u\n", size); 432 } 433 else 434 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n"); 435 436 /* test with a lot of items */ 437 for (i = 0; i < 65536; i++) 438 { 439 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item)); 440 item->value = i + 1; 441 entry = InterlockedPushEntrySList(&slist_header, &item->entry); 442 if (i) 443 { 444 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 445 item = CONTAINING_RECORD(entry, struct item, entry); 446 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 447 } 448 else 449 { 450 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 451 } 452 size = QueryDepthSList(&slist_header); 453 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size); 454 } 455 456 entry = InterlockedFlushSList(&slist_header); 457 for (i = 65536; i > 0; i--) 458 { 459 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 460 item = CONTAINING_RECORD(entry, struct item, entry); 461 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 462 entry = item->entry.Next; 463 HeapFree(GetProcessHeap(), 0, item); 464 } 465 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 466 size = QueryDepthSList(&slist_header); 467 ok(size == 0, "Expected size == 0, got %u\n", size); 468 entry = InterlockedPopEntrySList(&slist_header); 469 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 470 } 471 472 static void test_event(void) 473 { 474 HANDLE handle, handle2; 475 SECURITY_ATTRIBUTES sa; 476 SECURITY_DESCRIPTOR sd; 477 ACL acl; 478 DWORD ret; 479 BOOL val; 480 481 /* no sd */ 482 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 483 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 484 CloseHandle(handle); 485 486 sa.nLength = sizeof(sa); 487 sa.lpSecurityDescriptor = &sd; 488 sa.bInheritHandle = FALSE; 489 490 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 491 492 /* blank sd */ 493 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 494 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 495 CloseHandle(handle); 496 497 /* sd with NULL dacl */ 498 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); 499 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 500 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 501 CloseHandle(handle); 502 503 /* sd with empty dacl */ 504 InitializeAcl(&acl, sizeof(acl), ACL_REVISION); 505 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE); 506 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 507 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 508 CloseHandle(handle); 509 510 /* test case sensitivity */ 511 512 SetLastError(0xdeadbeef); 513 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 514 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError()); 515 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 516 517 SetLastError(0xdeadbeef); 518 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 519 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 520 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 521 CloseHandle( handle2 ); 522 523 SetLastError(0xdeadbeef); 524 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT"); 525 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 526 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 527 CloseHandle( handle2 ); 528 529 SetLastError(0xdeadbeef); 530 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event"); 531 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError()); 532 CloseHandle( handle2 ); 533 534 SetLastError(0xdeadbeef); 535 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT"); 536 ok( !handle2, "OpenEvent succeeded\n"); 537 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 538 539 SetLastError(0xdeadbeef); 540 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, NULL ); 541 ok( !handle2, "OpenEvent succeeded\n"); 542 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 543 544 SetLastError(0xdeadbeef); 545 handle2 = OpenEventW( EVENT_ALL_ACCESS, FALSE, NULL ); 546 ok( !handle2, "OpenEvent succeeded\n"); 547 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 548 549 CloseHandle( handle ); 550 551 /* resource notifications are events too */ 552 553 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification) 554 { 555 trace( "memory resource notifications not supported\n" ); 556 return; 557 } 558 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 ); 559 ok( !handle, "CreateMemoryResourceNotification succeeded\n" ); 560 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 561 ret = pQueryMemoryResourceNotification( handle, &val ); 562 ok( !ret, "QueryMemoryResourceNotification succeeded\n" ); 563 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 564 565 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification ); 566 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() ); 567 ret = WaitForSingleObject( handle, 10 ); 568 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret ); 569 570 val = ~0; 571 ret = pQueryMemoryResourceNotification( handle, &val ); 572 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 573 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 574 ret = CloseHandle( handle ); 575 ok( ret, "CloseHandle failed err %u\n", GetLastError() ); 576 577 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 578 val = ~0; 579 ret = pQueryMemoryResourceNotification( handle, &val ); 580 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 581 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 582 CloseHandle( handle ); 583 } 584 585 static void test_semaphore(void) 586 { 587 HANDLE handle, handle2; 588 589 /* test case sensitivity */ 590 591 SetLastError(0xdeadbeef); 592 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 593 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError()); 594 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 595 596 SetLastError(0xdeadbeef); 597 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 598 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 599 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 600 CloseHandle( handle2 ); 601 602 SetLastError(0xdeadbeef); 603 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE"); 604 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 605 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 606 CloseHandle( handle2 ); 607 608 SetLastError(0xdeadbeef); 609 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore"); 610 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError()); 611 CloseHandle( handle2 ); 612 613 SetLastError(0xdeadbeef); 614 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE"); 615 ok( !handle2, "OpenSemaphore succeeded\n"); 616 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 617 618 SetLastError(0xdeadbeef); 619 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, NULL ); 620 ok( !handle2, "OpenSemaphore succeeded\n"); 621 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 622 623 SetLastError(0xdeadbeef); 624 handle2 = OpenSemaphoreW( SEMAPHORE_ALL_ACCESS, FALSE, NULL ); 625 ok( !handle2, "OpenSemaphore succeeded\n"); 626 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 627 628 CloseHandle( handle ); 629 } 630 631 static void test_waitable_timer(void) 632 { 633 HANDLE handle, handle2; 634 635 /* test case sensitivity */ 636 637 SetLastError(0xdeadbeef); 638 handle = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 639 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError()); 640 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 641 642 SetLastError(0xdeadbeef); 643 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 644 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 645 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 646 CloseHandle( handle2 ); 647 648 SetLastError(0xdeadbeef); 649 handle2 = CreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER"); 650 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 651 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 652 CloseHandle( handle2 ); 653 654 SetLastError(0xdeadbeef); 655 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer"); 656 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError()); 657 CloseHandle( handle2 ); 658 659 SetLastError(0xdeadbeef); 660 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER"); 661 ok( !handle2, "OpenWaitableTimer succeeded\n"); 662 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 663 664 SetLastError(0xdeadbeef); 665 handle2 = OpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, NULL ); 666 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError()); 667 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 668 669 SetLastError(0xdeadbeef); 670 handle2 = OpenWaitableTimerW( TIMER_ALL_ACCESS, FALSE, NULL ); 671 ok( !handle2, "OpenWaitableTimer failed with error %d\n", GetLastError()); 672 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError()); 673 674 CloseHandle( handle ); 675 } 676 677 static HANDLE sem = 0; 678 679 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped) 680 { 681 ReleaseSemaphore(sem, 1, NULL); 682 } 683 684 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL; 685 686 static void test_iocp_callback(void) 687 { 688 char temp_path[MAX_PATH]; 689 char filename[MAX_PATH]; 690 DWORD ret; 691 BOOL retb; 692 static const char prefix[] = "pfx"; 693 HANDLE hFile; 694 HMODULE hmod = GetModuleHandleA("kernel32.dll"); 695 DWORD bytesWritten; 696 const char *buffer = "12345678123456781234567812345678"; 697 OVERLAPPED overlapped; 698 699 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback"); 700 if(!p_BindIoCompletionCallback) { 701 win_skip("BindIoCompletionCallback not found in this DLL\n"); 702 return; 703 } 704 705 sem = CreateSemaphoreW(NULL, 0, 1, NULL); 706 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n"); 707 708 ret = GetTempPathA(MAX_PATH, temp_path); 709 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 710 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 711 712 ret = GetTempFileNameA(temp_path, prefix, 0, filename); 713 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 714 715 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 716 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 717 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 718 719 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 720 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n"); 721 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 722 723 ret = CloseHandle(hFile); 724 ok( ret, "CloseHandle: error %d\n", GetLastError()); 725 ret = DeleteFileA(filename); 726 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 727 728 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 729 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 730 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 731 732 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 733 ok(retb == TRUE, "BindIoCompletionCallback failed\n"); 734 735 memset(&overlapped, 0, sizeof(overlapped)); 736 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped); 737 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError()); 738 739 ret = WaitForSingleObject(sem, 5000); 740 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n"); 741 CloseHandle(sem); 742 743 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 744 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n"); 745 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 746 retb = p_BindIoCompletionCallback(hFile, NULL, 0); 747 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n"); 748 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 749 750 ret = CloseHandle(hFile); 751 ok( ret, "CloseHandle: error %d\n", GetLastError()); 752 ret = DeleteFileA(filename); 753 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 754 755 /* win2k3 requires the Flags parameter to be zero */ 756 SetLastError(0xdeadbeef); 757 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 758 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 759 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 760 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345); 761 if (!retb) 762 ok(GetLastError() == ERROR_INVALID_PARAMETER, 763 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 764 else 765 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n"); 766 ret = CloseHandle(hFile); 767 ok( ret, "CloseHandle: error %d\n", GetLastError()); 768 ret = DeleteFileA(filename); 769 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 770 771 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0); 772 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n"); 773 ok(GetLastError() == ERROR_INVALID_HANDLE || 774 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */ 775 "Last error is %d\n", GetLastError()); 776 } 777 778 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut) 779 { 780 int *pn = p; 781 ok(timedOut, "Timer callbacks should always time out\n"); 782 ++*pn; 783 } 784 785 struct timer_queue_data1 786 { 787 int num_calls; 788 int max_calls; 789 HANDLE q, t; 790 }; 791 792 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut) 793 { 794 struct timer_queue_data1 *d = p; 795 ok(timedOut, "Timer callbacks should always time out\n"); 796 if (d->t && ++d->num_calls == d->max_calls) 797 { 798 BOOL ret; 799 SetLastError(0xdeadbeef); 800 /* Note, XP SP2 does *not* do any deadlock checking, so passing 801 INVALID_HANDLE_VALUE here will just hang. */ 802 ret = DeleteTimerQueueTimer(d->q, d->t, NULL); 803 ok(!ret, "DeleteTimerQueueTimer\n"); 804 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 805 } 806 } 807 808 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut) 809 { 810 struct timer_queue_data1 *d = p; 811 ok(timedOut, "Timer callbacks should always time out\n"); 812 if (d->t && ++d->num_calls == d->max_calls) 813 { 814 /* Basically kill the timer since it won't have time to run 815 again. */ 816 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 10000, 0); 817 ok(ret, "ChangeTimerQueueTimer\n"); 818 } 819 } 820 821 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut) 822 { 823 struct timer_queue_data1 *d = p; 824 ok(timedOut, "Timer callbacks should always time out\n"); 825 if (d->t) 826 { 827 /* This tests whether a timer gets flagged for deletion before 828 or after the callback runs. If we start this timer with a 829 period of zero (run once), then ChangeTimerQueueTimer will 830 fail if the timer is already flagged. Hence we really run 831 only once. Otherwise we will run multiple times. */ 832 BOOL ret = ChangeTimerQueueTimer(d->q, d->t, 50, 50); 833 ok(ret, "ChangeTimerQueueTimer\n"); 834 ++d->num_calls; 835 } 836 } 837 838 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut) 839 { 840 DWORD_PTR delay = (DWORD_PTR) p; 841 ok(timedOut, "Timer callbacks should always time out\n"); 842 if (delay) 843 Sleep(delay); 844 } 845 846 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut) 847 { 848 struct timer_queue_data1 *d = p; 849 ok(timedOut, "Timer callbacks should always time out\n"); 850 /* This tests an original implementation bug where a deleted timer may get 851 to run, but it is tricky to set up. */ 852 if (d->q && d->num_calls++ == 0) 853 { 854 /* First run: delete ourselves, then insert and remove a timer 855 that goes in front of us in the sorted timeout list. Once 856 removed, we will still timeout at the faster timer's due time, 857 but this should be a no-op if we are bug-free. There should 858 not be a second run. We can test the value of num_calls later. */ 859 BOOL ret; 860 HANDLE t; 861 862 /* The delete will pend while we are in this callback. */ 863 SetLastError(0xdeadbeef); 864 ret = DeleteTimerQueueTimer(d->q, d->t, NULL); 865 ok(!ret, "DeleteTimerQueueTimer\n"); 866 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 867 868 ret = CreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0); 869 ok(ret, "CreateTimerQueueTimer\n"); 870 ok(t != NULL, "CreateTimerQueueTimer\n"); 871 872 ret = DeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE); 873 ok(ret, "DeleteTimerQueueTimer\n"); 874 875 /* Now we stay alive by hanging around in the callback. */ 876 Sleep(500); 877 } 878 } 879 880 static void test_timer_queue(void) 881 { 882 HANDLE q, t0, t1, t2, t3, t4, t5; 883 int n0, n1, n2, n3, n4, n5; 884 struct timer_queue_data1 d1, d2, d3, d4; 885 HANDLE e, et1, et2; 886 BOOL ret, ret0; 887 888 /* Test asynchronous deletion of the queue. */ 889 q = CreateTimerQueue(); 890 ok(q != NULL, "CreateTimerQueue\n"); 891 892 SetLastError(0xdeadbeef); 893 ret = DeleteTimerQueueEx(q, NULL); 894 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 895 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 896 GetLastError()); 897 898 /* Test synchronous deletion of the queue and running timers. */ 899 q = CreateTimerQueue(); 900 ok(q != NULL, "CreateTimerQueue\n"); 901 902 /* Not called. */ 903 t0 = NULL; 904 n0 = 0; 905 ret = CreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 300, 0); 906 ok(ret, "CreateTimerQueueTimer\n"); 907 ok(t0 != NULL, "CreateTimerQueueTimer\n"); 908 ret0 = DeleteTimerQueueTimer(q, t0, NULL); 909 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) || 910 broken(ret0), /* Win 2000 & XP & 2003 */ 911 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError()); 912 913 /* Called once. */ 914 t1 = NULL; 915 n1 = 0; 916 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0); 917 ok(ret, "CreateTimerQueueTimer\n"); 918 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 919 920 /* A slow one. */ 921 t2 = NULL; 922 n2 = 0; 923 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0); 924 ok(ret, "CreateTimerQueueTimer\n"); 925 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 926 927 /* A fast one. */ 928 t3 = NULL; 929 n3 = 0; 930 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0); 931 ok(ret, "CreateTimerQueueTimer\n"); 932 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 933 934 /* Start really late (it won't start). */ 935 t4 = NULL; 936 n4 = 0; 937 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0); 938 ok(ret, "CreateTimerQueueTimer\n"); 939 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 940 941 /* Start soon, but delay so long it won't run again. */ 942 t5 = NULL; 943 n5 = 0; 944 ret = CreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0); 945 ok(ret, "CreateTimerQueueTimer\n"); 946 ok(t5 != NULL, "CreateTimerQueueTimer\n"); 947 948 /* Give them a chance to do some work. */ 949 Sleep(500); 950 951 /* Test deleting a once-only timer. */ 952 ret = DeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE); 953 ok(ret, "DeleteTimerQueueTimer\n"); 954 955 /* A periodic timer. */ 956 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); 957 ok(ret, "DeleteTimerQueueTimer\n"); 958 959 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 960 ok(ret, "DeleteTimerQueueEx\n"); 961 todo_wine 962 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0); 963 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1); 964 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3); 965 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4); 966 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5); 967 968 /* Test synchronous deletion of the timer/queue with event trigger. */ 969 e = CreateEventW(NULL, TRUE, FALSE, NULL); 970 et1 = CreateEventW(NULL, TRUE, FALSE, NULL); 971 et2 = CreateEventW(NULL, TRUE, FALSE, NULL); 972 if (!e || !et1 || !et2) 973 { 974 skip("Failed to create timer queue descruction event\n"); 975 return; 976 } 977 978 q = CreateTimerQueue(); 979 ok(q != NULL, "CreateTimerQueue\n"); 980 981 /* Run once and finish quickly (should be done when we delete it). */ 982 t1 = NULL; 983 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0); 984 ok(ret, "CreateTimerQueueTimer\n"); 985 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 986 987 /* Run once and finish slowly (shouldn't be done when we delete it). */ 988 t2 = NULL; 989 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0); 990 ok(ret, "CreateTimerQueueTimer\n"); 991 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 992 993 /* Run once and finish quickly (should be done when we delete it). */ 994 t3 = NULL; 995 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0); 996 ok(ret, "CreateTimerQueueTimer\n"); 997 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 998 999 /* Run once and finish slowly (shouldn't be done when we delete it). */ 1000 t4 = NULL; 1001 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 0, 0); 1002 ok(ret, "CreateTimerQueueTimer\n"); 1003 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 1004 1005 /* Give them a chance to start. */ 1006 Sleep(400); 1007 1008 /* DeleteTimerQueueTimer always returns PENDING with a NULL event, 1009 even if the timer is finished. */ 1010 SetLastError(0xdeadbeef); 1011 ret = DeleteTimerQueueTimer(q, t1, NULL); 1012 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1013 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1014 GetLastError()); 1015 1016 SetLastError(0xdeadbeef); 1017 ret = DeleteTimerQueueTimer(q, t2, NULL); 1018 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1019 ok(GetLastError() == ERROR_IO_PENDING, 1020 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1021 GetLastError()); 1022 1023 SetLastError(0xdeadbeef); 1024 ret = DeleteTimerQueueTimer(q, t3, et1); 1025 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1026 ok(GetLastError() == 0xdeadbeef, 1027 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n", 1028 GetLastError()); 1029 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0, 1030 "Timer destruction event not triggered\n"); 1031 1032 SetLastError(0xdeadbeef); 1033 ret = DeleteTimerQueueTimer(q, t4, et2); 1034 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1035 ok(GetLastError() == ERROR_IO_PENDING, 1036 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1037 GetLastError()); 1038 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0, 1039 "Timer destruction event not triggered\n"); 1040 1041 SetLastError(0xdeadbeef); 1042 ret = DeleteTimerQueueEx(q, e); 1043 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1044 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1045 GetLastError()); 1046 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0, 1047 "Queue destruction event not triggered\n"); 1048 CloseHandle(e); 1049 1050 /* Test deleting/changing a timer in execution. */ 1051 q = CreateTimerQueue(); 1052 ok(q != NULL, "CreateTimerQueue\n"); 1053 1054 /* Test changing a once-only timer before it fires (this is allowed, 1055 whereas after it fires you cannot). */ 1056 n1 = 0; 1057 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 0, 0); 1058 ok(ret, "CreateTimerQueueTimer\n"); 1059 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1060 ret = ChangeTimerQueueTimer(q, t1, 0, 0); 1061 ok(ret, "ChangeTimerQueueTimer\n"); 1062 1063 d2.t = t2 = NULL; 1064 d2.num_calls = 0; 1065 d2.max_calls = 3; 1066 d2.q = q; 1067 ret = CreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 10, 0); 1068 d2.t = t2; 1069 ok(ret, "CreateTimerQueueTimer\n"); 1070 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1071 1072 d3.t = t3 = NULL; 1073 d3.num_calls = 0; 1074 d3.max_calls = 4; 1075 d3.q = q; 1076 ret = CreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 10, 0); 1077 d3.t = t3; 1078 ok(ret, "CreateTimerQueueTimer\n"); 1079 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 1080 1081 d4.t = t4 = NULL; 1082 d4.num_calls = 0; 1083 d4.q = q; 1084 ret = CreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 0, 0); 1085 d4.t = t4; 1086 ok(ret, "CreateTimerQueueTimer\n"); 1087 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 1088 1089 Sleep(500); 1090 1091 ret = DeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 1092 ok(ret, "DeleteTimerQueueEx\n"); 1093 ok(n1 == 1, "ChangeTimerQueueTimer\n"); 1094 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n"); 1095 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); 1096 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n"); 1097 1098 /* Test an obscure bug that was in the original implementation. */ 1099 q = CreateTimerQueue(); 1100 ok(q != NULL, "CreateTimerQueue\n"); 1101 1102 /* All the work is done in the callback. */ 1103 d1.t = t1 = NULL; 1104 d1.num_calls = 0; 1105 d1.q = q; 1106 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 100, WT_EXECUTELONGFUNCTION); 1107 d1.t = t1; 1108 ok(ret, "CreateTimerQueueTimer\n"); 1109 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1110 1111 Sleep(750); 1112 1113 SetLastError(0xdeadbeef); 1114 ret = DeleteTimerQueueEx(q, NULL); 1115 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1116 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1117 GetLastError()); 1118 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n"); 1119 1120 /* Test functions on the default timer queue. */ 1121 t1 = NULL; 1122 n1 = 0; 1123 ret = CreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1000, 0); 1124 ok(ret, "CreateTimerQueueTimer, default queue\n"); 1125 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n"); 1126 1127 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1128 ok(ret, "ChangeTimerQueueTimer, default queue\n"); 1129 1130 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1131 ok(ret, "DeleteTimerQueueTimer, default queue\n"); 1132 1133 /* Try mixing default and non-default queues. Apparently this works. */ 1134 q = CreateTimerQueue(); 1135 ok(q != NULL, "CreateTimerQueue\n"); 1136 1137 t1 = NULL; 1138 n1 = 0; 1139 ret = CreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1000, 0); 1140 ok(ret, "CreateTimerQueueTimer\n"); 1141 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1142 1143 t2 = NULL; 1144 n2 = 0; 1145 ret = CreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1000, 0); 1146 ok(ret, "CreateTimerQueueTimer\n"); 1147 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1148 1149 ret = ChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1150 ok(ret, "ChangeTimerQueueTimer\n"); 1151 1152 ret = ChangeTimerQueueTimer(q, t2, 2000, 2000); 1153 ok(ret, "ChangeTimerQueueTimer\n"); 1154 1155 ret = DeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1156 ok(ret, "DeleteTimerQueueTimer\n"); 1157 1158 ret = DeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); 1159 ok(ret, "DeleteTimerQueueTimer\n"); 1160 1161 /* Try to delete the default queue? In any case: not allowed. */ 1162 SetLastError(0xdeadbeef); 1163 ret = DeleteTimerQueueEx(NULL, NULL); 1164 ok(!ret, "DeleteTimerQueueEx call was expected to fail\n"); 1165 ok(GetLastError() == ERROR_INVALID_HANDLE, 1166 "DeleteTimerQueueEx, GetLastError: expected ERROR_INVALID_HANDLE, got %d\n", 1167 GetLastError()); 1168 1169 SetLastError(0xdeadbeef); 1170 ret = DeleteTimerQueueEx(q, NULL); 1171 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1172 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1173 GetLastError()); 1174 } 1175 1176 static HANDLE modify_handle(HANDLE handle, DWORD modify) 1177 { 1178 DWORD tmp = HandleToULong(handle); 1179 tmp |= modify; 1180 return ULongToHandle(tmp); 1181 } 1182 1183 static void test_WaitForSingleObject(void) 1184 { 1185 HANDLE signaled, nonsignaled, invalid; 1186 LARGE_INTEGER timeout; 1187 NTSTATUS status; 1188 DWORD ret; 1189 1190 signaled = CreateEventW(NULL, TRUE, TRUE, NULL); 1191 nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL); 1192 invalid = (HANDLE) 0xdeadbee0; 1193 1194 /* invalid handle with different values for lower 2 bits */ 1195 SetLastError(0xdeadbeef); 1196 ret = WaitForSingleObject(invalid, 0); 1197 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1198 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1199 1200 SetLastError(0xdeadbeef); 1201 ret = WaitForSingleObject(modify_handle(invalid, 1), 0); 1202 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1203 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1204 1205 SetLastError(0xdeadbeef); 1206 ret = WaitForSingleObject(modify_handle(invalid, 2), 0); 1207 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1208 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1209 1210 SetLastError(0xdeadbeef); 1211 ret = WaitForSingleObject(modify_handle(invalid, 3), 0); 1212 ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %d\n", ret); 1213 ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); 1214 1215 /* valid handle with different values for lower 2 bits */ 1216 SetLastError(0xdeadbeef); 1217 ret = WaitForSingleObject(nonsignaled, 0); 1218 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1219 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1220 1221 SetLastError(0xdeadbeef); 1222 ret = WaitForSingleObject(modify_handle(nonsignaled, 1), 0); 1223 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1224 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1225 1226 SetLastError(0xdeadbeef); 1227 ret = WaitForSingleObject(modify_handle(nonsignaled, 2), 0); 1228 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1229 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1230 1231 SetLastError(0xdeadbeef); 1232 ret = WaitForSingleObject(modify_handle(nonsignaled, 3), 0); 1233 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %d\n", ret); 1234 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1235 1236 /* valid handle with different values for lower 2 bits */ 1237 SetLastError(0xdeadbeef); 1238 ret = WaitForSingleObject(signaled, 0); 1239 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1240 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1241 1242 SetLastError(0xdeadbeef); 1243 ret = WaitForSingleObject(modify_handle(signaled, 1), 0); 1244 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1245 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1246 1247 SetLastError(0xdeadbeef); 1248 ret = WaitForSingleObject(modify_handle(signaled, 2), 0); 1249 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1250 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1251 1252 SetLastError(0xdeadbeef); 1253 ret = WaitForSingleObject(modify_handle(signaled, 3), 0); 1254 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %d\n", ret); 1255 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1256 1257 /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */ 1258 ret = WaitForSingleObject(GetCurrentProcess(), 100); 1259 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret); 1260 1261 ret = WaitForSingleObject(GetCurrentThread(), 100); 1262 ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", ret); 1263 1264 timeout.QuadPart = -1000000; 1265 status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout); 1266 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status); 1267 1268 timeout.QuadPart = -1000000; 1269 status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); 1270 ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08x\n", status); 1271 1272 CloseHandle(signaled); 1273 CloseHandle(nonsignaled); 1274 } 1275 1276 static void test_WaitForMultipleObjects(void) 1277 { 1278 LARGE_INTEGER timeout; 1279 NTSTATUS status; 1280 DWORD r; 1281 int i; 1282 HANDLE maxevents[MAXIMUM_WAIT_OBJECTS]; 1283 1284 /* create the maximum number of events and make sure 1285 * we can wait on that many */ 1286 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1287 { 1288 maxevents[i] = CreateEventW(NULL, i==0, TRUE, NULL); 1289 ok( maxevents[i] != 0, "should create enough events\n"); 1290 } 1291 1292 /* a manual-reset event remains signaled, an auto-reset event is cleared */ 1293 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1294 ok( r == WAIT_OBJECT_0, "should signal lowest handle first, got %d\n", r); 1295 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1296 ok( r == WAIT_OBJECT_0, "should signal handle #0 first, got %d\n", r); 1297 ok(ResetEvent(maxevents[0]), "ResetEvent\n"); 1298 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) 1299 { 1300 /* the lowest index is checked first and remaining events are untouched */ 1301 r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 0); 1302 ok( r == WAIT_OBJECT_0+i, "should signal handle #%d first, got %d\n", i, r); 1303 } 1304 1305 /* run same test with Nt* call */ 1306 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1307 SetEvent(maxevents[i]); 1308 1309 /* a manual-reset event remains signaled, an auto-reset event is cleared */ 1310 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1311 ok(status == STATUS_WAIT_0, "should signal lowest handle first, got %08x\n", status); 1312 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1313 ok(status == STATUS_WAIT_0, "should signal handle #0 first, got %08x\n", status); 1314 ok(ResetEvent(maxevents[0]), "ResetEvent\n"); 1315 for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) 1316 { 1317 /* the lowest index is checked first and remaining events are untouched */ 1318 status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, FALSE, NULL); 1319 ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08x\n", i, status); 1320 } 1321 1322 for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) 1323 if (maxevents[i]) CloseHandle(maxevents[i]); 1324 1325 /* in contrast to WaitForSingleObject, pseudo handles are not allowed in 1326 * WaitForMultipleObjects and NtWaitForMultipleObjects */ 1327 maxevents[0] = GetCurrentProcess(); 1328 SetLastError(0xdeadbeef); 1329 r = WaitForMultipleObjects(1, maxevents, FALSE, 100); 1330 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r); 1331 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, 1332 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 1333 1334 maxevents[0] = GetCurrentThread(); 1335 SetLastError(0xdeadbeef); 1336 r = WaitForMultipleObjects(1, maxevents, FALSE, 100); 1337 todo_wine ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %u\n", r); 1338 todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, 1339 "expected ERROR_INVALID_HANDLE, got %u\n", GetLastError()); 1340 1341 timeout.QuadPart = -1000000; 1342 maxevents[0] = GetCurrentProcess(); 1343 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); 1344 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status); 1345 1346 timeout.QuadPart = -1000000; 1347 maxevents[0] = GetCurrentThread(); 1348 status = pNtWaitForMultipleObjects(1, maxevents, TRUE, FALSE, &timeout); 1349 todo_wine ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08x\n", status); 1350 } 1351 1352 static BOOL g_initcallback_ret, g_initcallback_called; 1353 static void *g_initctxt; 1354 1355 static BOOL CALLBACK initonce_callback(INIT_ONCE *initonce, void *parameter, void **ctxt) 1356 { 1357 g_initcallback_called = TRUE; 1358 /* zero bit set means here that initialization is taking place - initialization locked */ 1359 ok(g_initctxt == *ctxt, "got wrong context value %p, expected %p\n", *ctxt, g_initctxt); 1360 ok(initonce->Ptr == (void*)0x1, "got %p\n", initonce->Ptr); 1361 ok(parameter == (void*)0xdeadbeef, "got wrong parameter\n"); 1362 return g_initcallback_ret; 1363 } 1364 1365 static void test_initonce(void) 1366 { 1367 INIT_ONCE initonce; 1368 BOOL ret, pending; 1369 1370 if (!pInitOnceInitialize || !pInitOnceExecuteOnce) 1371 { 1372 win_skip("one-time initialization API not supported\n"); 1373 return; 1374 } 1375 1376 /* blocking initialization with callback */ 1377 initonce.Ptr = (void*)0xdeadbeef; 1378 pInitOnceInitialize(&initonce); 1379 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1380 1381 /* initialisation completed successfully */ 1382 g_initcallback_ret = TRUE; 1383 g_initctxt = NULL; 1384 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1385 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1386 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr); 1387 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1388 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1389 1390 /* so it's been called already so won't be called again */ 1391 g_initctxt = NULL; 1392 g_initcallback_called = FALSE; 1393 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1394 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1395 ok(initonce.Ptr == (void*)0x2, "got %p\n", initonce.Ptr); 1396 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1397 ok(!g_initcallback_called, "got %d\n", g_initcallback_called); 1398 1399 pInitOnceInitialize(&initonce); 1400 g_initcallback_called = FALSE; 1401 /* 2 lower order bits should never be used, you'll get a crash in result */ 1402 g_initctxt = (void*)0xFFFFFFF0; 1403 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1404 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1405 ok(initonce.Ptr == (void*)0xFFFFFFF2, "got %p\n", initonce.Ptr); 1406 ok(g_initctxt == (void*)0xFFFFFFF0, "got %p\n", g_initctxt); 1407 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1408 1409 /* callback failed */ 1410 g_initcallback_ret = FALSE; 1411 g_initcallback_called = FALSE; 1412 g_initctxt = NULL; 1413 pInitOnceInitialize(&initonce); 1414 SetLastError( 0xdeadbeef ); 1415 ret = pInitOnceExecuteOnce(&initonce, initonce_callback, (void*)0xdeadbeef, &g_initctxt); 1416 ok(!ret && GetLastError() == 0xdeadbeef, "got wrong ret value %d err %u\n", ret, GetLastError()); 1417 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1418 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1419 ok(g_initcallback_called, "got %d\n", g_initcallback_called); 1420 1421 /* blocking initialization without a callback */ 1422 pInitOnceInitialize(&initonce); 1423 g_initctxt = NULL; 1424 pending = FALSE; 1425 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1426 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1427 ok(pending, "got %d\n", pending); 1428 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1429 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1430 /* another attempt to begin initialization with block a single thread */ 1431 1432 g_initctxt = NULL; 1433 pending = 0xf; 1434 SetLastError( 0xdeadbeef ); 1435 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1436 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1437 ok(pending == 0xf, "got %d\n", pending); 1438 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1439 ok(g_initctxt == NULL, "got %p\n", g_initctxt); 1440 1441 g_initctxt = (void*)0xdeadbee0; 1442 SetLastError( 0xdeadbeef ); 1443 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, g_initctxt); 1444 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1445 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1446 1447 /* once failed already */ 1448 g_initctxt = (void*)0xdeadbee0; 1449 ret = pInitOnceComplete(&initonce, 0, g_initctxt); 1450 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1451 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1452 1453 pInitOnceInitialize(&initonce); 1454 SetLastError( 0xdeadbeef ); 1455 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1456 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1457 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1458 1459 SetLastError( 0xdeadbeef ); 1460 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1461 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1462 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1463 1464 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1465 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1466 ok(pending, "got %d\n", pending); 1467 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1468 1469 SetLastError( 0xdeadbeef ); 1470 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1471 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1472 1473 SetLastError( 0xdeadbeef ); 1474 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1475 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1476 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1477 1478 SetLastError( 0xdeadbeef ); 1479 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbeef); 1480 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1481 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1482 1483 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1484 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1485 ok(initonce.Ptr == NULL, "got %p\n", initonce.Ptr); 1486 1487 pInitOnceInitialize(&initonce); 1488 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1489 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1490 ok(pending, "got %d\n", pending); 1491 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1492 1493 SetLastError( 0xdeadbeef ); 1494 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1495 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1496 1497 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1498 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1499 ok(pending, "got %d\n", pending); 1500 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1501 1502 SetLastError( 0xdeadbeef ); 1503 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED, NULL); 1504 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1505 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1506 1507 SetLastError( 0xdeadbeef ); 1508 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1509 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1510 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1511 1512 SetLastError( 0xdeadbeef ); 1513 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbeef); 1514 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1515 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1516 1517 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0); 1518 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1519 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1520 1521 SetLastError( 0xdeadbeef ); 1522 ret = pInitOnceComplete(&initonce, INIT_ONCE_INIT_FAILED | INIT_ONCE_ASYNC, NULL); 1523 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1524 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1525 1526 pInitOnceInitialize(&initonce); 1527 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1528 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1529 ok(pending, "got %d\n", pending); 1530 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1531 1532 /* test INIT_ONCE_CHECK_ONLY */ 1533 1534 pInitOnceInitialize(&initonce); 1535 SetLastError( 0xdeadbeef ); 1536 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1537 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1538 SetLastError( 0xdeadbeef ); 1539 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1540 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1541 1542 ret = pInitOnceBeginInitialize(&initonce, 0, &pending, &g_initctxt); 1543 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1544 ok(pending, "got %d\n", pending); 1545 ok(initonce.Ptr == (void*)1, "got %p\n", initonce.Ptr); 1546 1547 SetLastError( 0xdeadbeef ); 1548 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1549 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1550 SetLastError( 0xdeadbeef ); 1551 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1552 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1553 1554 ret = pInitOnceComplete(&initonce, 0, (void *)0xdeadbee0); 1555 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1556 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1557 1558 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1559 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError()); 1560 ok(!pending, "got %d\n", pending); 1561 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1562 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr); 1563 1564 SetLastError( 0xdeadbeef ); 1565 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1566 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1567 1568 pInitOnceInitialize(&initonce); 1569 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_ASYNC, &pending, &g_initctxt); 1570 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1571 ok(pending, "got %d\n", pending); 1572 ok(initonce.Ptr == (void*)3, "got %p\n", initonce.Ptr); 1573 1574 SetLastError( 0xdeadbeef ); 1575 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1576 ok(!ret && GetLastError() == ERROR_GEN_FAILURE, "wrong ret %d err %u\n", ret, GetLastError()); 1577 SetLastError( 0xdeadbeef ); 1578 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1579 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1580 1581 ret = pInitOnceComplete(&initonce, INIT_ONCE_ASYNC, (void *)0xdeadbee0); 1582 ok(ret, "wrong ret %d err %u\n", ret, GetLastError()); 1583 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1584 1585 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY, &pending, &g_initctxt); 1586 ok(ret, "got wrong ret value %d err %u\n", ret, GetLastError()); 1587 ok(!pending, "got %d\n", pending); 1588 ok(initonce.Ptr == (void*)0xdeadbee2, "got %p\n", initonce.Ptr); 1589 ok(g_initctxt == (void*)0xdeadbee0, "got %p\n", initonce.Ptr); 1590 1591 SetLastError( 0xdeadbeef ); 1592 ret = pInitOnceBeginInitialize(&initonce, INIT_ONCE_CHECK_ONLY|INIT_ONCE_ASYNC, &pending, &g_initctxt); 1593 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "wrong ret %d err %u\n", ret, GetLastError()); 1594 } 1595 1596 static CONDITION_VARIABLE buffernotempty = CONDITION_VARIABLE_INIT; 1597 static CONDITION_VARIABLE buffernotfull = CONDITION_VARIABLE_INIT; 1598 static CRITICAL_SECTION buffercrit; 1599 static BOOL condvar_stop = FALSE, condvar_sleeperr = FALSE; 1600 static LONG bufferlen,totalproduced,totalconsumed; 1601 static LONG condvar_producer_sleepcnt,condvar_consumer_sleepcnt; 1602 1603 #define BUFFER_SIZE 5 1604 1605 static DWORD WINAPI condvar_producer(LPVOID x) { 1606 DWORD sleepinterval = 5; 1607 1608 while (1) { 1609 Sleep(sleepinterval); 1610 if (sleepinterval > 1) 1611 sleepinterval -= 1; 1612 1613 EnterCriticalSection(&buffercrit); 1614 while ((bufferlen == BUFFER_SIZE) && !condvar_stop) { 1615 condvar_producer_sleepcnt++; 1616 if (!pSleepConditionVariableCS(&buffernotfull, &buffercrit, sleepinterval)) { 1617 if (GetLastError() != ERROR_TIMEOUT) 1618 condvar_sleeperr = TRUE; 1619 } 1620 } 1621 if (condvar_stop) { 1622 LeaveCriticalSection(&buffercrit); 1623 break; 1624 } 1625 bufferlen++; 1626 totalproduced++; 1627 LeaveCriticalSection(&buffercrit); 1628 pWakeConditionVariable(&buffernotempty); 1629 } 1630 return 0; 1631 } 1632 1633 static DWORD WINAPI condvar_consumer(LPVOID x) { 1634 DWORD *cnt = (DWORD*)x; 1635 DWORD sleepinterval = 1; 1636 1637 while (1) { 1638 EnterCriticalSection(&buffercrit); 1639 while ((bufferlen == 0) && !condvar_stop) { 1640 condvar_consumer_sleepcnt++; 1641 if (!pSleepConditionVariableCS (&buffernotempty, &buffercrit, sleepinterval)) { 1642 if (GetLastError() != ERROR_TIMEOUT) 1643 condvar_sleeperr = TRUE; 1644 } 1645 } 1646 if (condvar_stop && (bufferlen == 0)) { 1647 LeaveCriticalSection(&buffercrit); 1648 break; 1649 } 1650 bufferlen--; 1651 totalconsumed++; 1652 (*cnt)++; 1653 LeaveCriticalSection(&buffercrit); 1654 pWakeConditionVariable(&buffernotfull); 1655 Sleep(sleepinterval); 1656 if (sleepinterval < 5) sleepinterval += 1; 1657 } 1658 return 0; 1659 } 1660 1661 static void test_condvars_consumer_producer(void) 1662 { 1663 HANDLE hp1,hp2,hp3,hc1,hc2,hc3; 1664 DWORD dummy; 1665 DWORD cnt1,cnt2,cnt3; 1666 1667 if (!pInitializeConditionVariable) { 1668 /* function is not yet in XP, only in newer Windows */ 1669 win_skip("no condition variable support.\n"); 1670 return; 1671 } 1672 1673 /* Implement a producer / consumer scheme with non-full / non-empty triggers */ 1674 1675 /* If we have static initialized condition variables, InitializeConditionVariable 1676 * is not strictly necessary. 1677 * pInitializeConditionVariable(&buffernotfull); 1678 */ 1679 pInitializeConditionVariable(&buffernotempty); 1680 InitializeCriticalSection(&buffercrit); 1681 1682 /* Larger Test: consumer/producer example */ 1683 1684 bufferlen = totalproduced = totalconsumed = cnt1 = cnt2 = cnt3 = 0; 1685 1686 hp1 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1687 hp2 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1688 hp3 = CreateThread(NULL, 0, condvar_producer, NULL, 0, &dummy); 1689 hc1 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt1, 0, &dummy); 1690 hc2 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt2, 0, &dummy); 1691 hc3 = CreateThread(NULL, 0, condvar_consumer, (PVOID)&cnt3, 0, &dummy); 1692 1693 /* Limit run to 0.5 seconds. */ 1694 Sleep(500); 1695 1696 /* tear down start */ 1697 condvar_stop = TRUE; 1698 1699 /* final wake up call */ 1700 pWakeAllConditionVariable (&buffernotfull); 1701 pWakeAllConditionVariable (&buffernotempty); 1702 1703 /* (mostly an implementation detail) 1704 * ok(buffernotfull.Ptr == NULL, "buffernotfull.Ptr is %p\n", buffernotfull.Ptr); 1705 */ 1706 1707 WaitForSingleObject(hp1, 1000); 1708 WaitForSingleObject(hp2, 1000); 1709 WaitForSingleObject(hp3, 1000); 1710 WaitForSingleObject(hc1, 1000); 1711 WaitForSingleObject(hc2, 1000); 1712 WaitForSingleObject(hc3, 1000); 1713 1714 ok(totalconsumed == totalproduced, 1715 "consumed %d != produced %d\n", totalconsumed, totalproduced); 1716 ok (!condvar_sleeperr, "error occurred during SleepConditionVariableCS\n"); 1717 1718 /* Checking cnt1 - cnt2 for non-0 would be not good, the case where 1719 * one consumer does not get anything to do is possible. */ 1720 trace("produced %d, c1 %d, c2 %d, c3 %d\n", totalproduced, cnt1, cnt2, cnt3); 1721 /* The sleeps of the producer or consumer should not go above 100* produced count, 1722 * otherwise the implementation does not sleep correctly. But yet again, this is 1723 * not hard defined. */ 1724 trace("producer sleep %d, consumer sleep %d\n", condvar_producer_sleepcnt, condvar_consumer_sleepcnt); 1725 } 1726 1727 /* Sample test for some sequence of events happening, sequenced using "condvar_seq" */ 1728 static DWORD condvar_seq = 0; 1729 static CONDITION_VARIABLE condvar_base = CONDITION_VARIABLE_INIT; 1730 static CRITICAL_SECTION condvar_crit; 1731 static SRWLOCK condvar_srwlock; 1732 1733 /* Sequence of wake/sleep to check boundary conditions: 1734 * 0: init 1735 * 1: producer emits a WakeConditionVariable without consumer waiting. 1736 * 2: consumer sleeps without a wake expecting timeout 1737 * 3: producer emits a WakeAllConditionVariable without consumer waiting. 1738 * 4: consumer sleeps without a wake expecting timeout 1739 * 5: a wake is handed to a SleepConditionVariableCS 1740 * 6: a wakeall is handed to a SleepConditionVariableCS 1741 * 7: sleep after above should timeout 1742 * 8: wake with crit section locked into the sleep timeout 1743 * 1744 * the following tests will only be executed if InitializeSRWLock is available 1745 * 1746 * 9: producer (exclusive) wakes up consumer (exclusive) 1747 * 10: producer (exclusive) wakes up consumer (shared) 1748 * 11: producer (shared) wakes up consumer (exclusive) 1749 * 12: producer (shared) wakes up consumer (shared) 1750 * 13: end 1751 */ 1752 static DWORD WINAPI condvar_base_producer(LPVOID x) { 1753 while (condvar_seq < 1) Sleep(1); 1754 1755 pWakeConditionVariable (&condvar_base); 1756 condvar_seq = 2; 1757 1758 while (condvar_seq < 3) Sleep(1); 1759 pWakeAllConditionVariable (&condvar_base); 1760 condvar_seq = 4; 1761 1762 while (condvar_seq < 5) Sleep(1); 1763 EnterCriticalSection (&condvar_crit); 1764 pWakeConditionVariable (&condvar_base); 1765 LeaveCriticalSection (&condvar_crit); 1766 while (condvar_seq < 6) Sleep(1); 1767 EnterCriticalSection (&condvar_crit); 1768 pWakeAllConditionVariable (&condvar_base); 1769 LeaveCriticalSection (&condvar_crit); 1770 1771 while (condvar_seq < 8) Sleep(1); 1772 EnterCriticalSection (&condvar_crit); 1773 pWakeConditionVariable (&condvar_base); 1774 Sleep(50); 1775 LeaveCriticalSection (&condvar_crit); 1776 1777 /* skip over remaining tests if InitializeSRWLock is not available */ 1778 if (!pInitializeSRWLock) 1779 return 0; 1780 1781 while (condvar_seq < 9) Sleep(1); 1782 pAcquireSRWLockExclusive(&condvar_srwlock); 1783 pWakeConditionVariable(&condvar_base); 1784 pReleaseSRWLockExclusive(&condvar_srwlock); 1785 1786 while (condvar_seq < 10) Sleep(1); 1787 pAcquireSRWLockExclusive(&condvar_srwlock); 1788 pWakeConditionVariable(&condvar_base); 1789 pReleaseSRWLockExclusive(&condvar_srwlock); 1790 1791 while (condvar_seq < 11) Sleep(1); 1792 pAcquireSRWLockShared(&condvar_srwlock); 1793 pWakeConditionVariable(&condvar_base); 1794 pReleaseSRWLockShared(&condvar_srwlock); 1795 1796 while (condvar_seq < 12) Sleep(1); 1797 Sleep(50); /* ensure that consumer waits for cond variable */ 1798 pAcquireSRWLockShared(&condvar_srwlock); 1799 pWakeConditionVariable(&condvar_base); 1800 pReleaseSRWLockShared(&condvar_srwlock); 1801 1802 return 0; 1803 } 1804 1805 static DWORD WINAPI condvar_base_consumer(LPVOID x) { 1806 BOOL ret; 1807 1808 while (condvar_seq < 2) Sleep(1); 1809 1810 /* wake was emitted, but we were not sleeping */ 1811 EnterCriticalSection (&condvar_crit); 1812 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1813 LeaveCriticalSection (&condvar_crit); 1814 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1815 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1816 1817 condvar_seq = 3; 1818 while (condvar_seq < 4) Sleep(1); 1819 1820 /* wake all was emitted, but we were not sleeping */ 1821 EnterCriticalSection (&condvar_crit); 1822 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1823 LeaveCriticalSection (&condvar_crit); 1824 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1825 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1826 1827 EnterCriticalSection (&condvar_crit); 1828 condvar_seq = 5; 1829 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); 1830 LeaveCriticalSection (&condvar_crit); 1831 ok (ret, "SleepConditionVariableCS should return TRUE on good wake\n"); 1832 1833 EnterCriticalSection (&condvar_crit); 1834 condvar_seq = 6; 1835 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 200); 1836 LeaveCriticalSection (&condvar_crit); 1837 ok (ret, "SleepConditionVariableCS should return TRUE on good wakeall\n"); 1838 condvar_seq = 7; 1839 1840 EnterCriticalSection (&condvar_crit); 1841 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1842 LeaveCriticalSection (&condvar_crit); 1843 ok (!ret, "SleepConditionVariableCS should return FALSE on out of band wake\n"); 1844 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on out of band wake, not %d\n", GetLastError()); 1845 1846 EnterCriticalSection (&condvar_crit); 1847 condvar_seq = 8; 1848 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 20); 1849 LeaveCriticalSection (&condvar_crit); 1850 ok (ret, "SleepConditionVariableCS should still return TRUE on crit unlock delay\n"); 1851 1852 /* skip over remaining tests if InitializeSRWLock is not available */ 1853 if (!pInitializeSRWLock) 1854 { 1855 win_skip("no srw lock support.\n"); 1856 condvar_seq = 13; /* end */ 1857 return 0; 1858 } 1859 1860 pAcquireSRWLockExclusive(&condvar_srwlock); 1861 condvar_seq = 9; 1862 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); 1863 pReleaseSRWLockExclusive(&condvar_srwlock); 1864 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1865 1866 pAcquireSRWLockShared(&condvar_srwlock); 1867 condvar_seq = 10; 1868 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); 1869 pReleaseSRWLockShared(&condvar_srwlock); 1870 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1871 1872 pAcquireSRWLockExclusive(&condvar_srwlock); 1873 condvar_seq = 11; 1874 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, 0); 1875 pReleaseSRWLockExclusive(&condvar_srwlock); 1876 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1877 1878 pAcquireSRWLockShared(&condvar_srwlock); 1879 condvar_seq = 12; 1880 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 200, CONDITION_VARIABLE_LOCKMODE_SHARED); 1881 pReleaseSRWLockShared(&condvar_srwlock); 1882 ok (ret, "pSleepConditionVariableSRW should return TRUE on good wake\n"); 1883 1884 condvar_seq = 13; 1885 return 0; 1886 } 1887 1888 static void test_condvars_base(void) { 1889 HANDLE hp, hc; 1890 DWORD dummy; 1891 BOOL ret; 1892 1893 1894 if (!pInitializeConditionVariable) { 1895 /* function is not yet in XP, only in newer Windows */ 1896 win_skip("no condition variable support.\n"); 1897 return; 1898 } 1899 1900 InitializeCriticalSection (&condvar_crit); 1901 1902 if (pInitializeSRWLock) 1903 pInitializeSRWLock(&condvar_srwlock); 1904 1905 EnterCriticalSection (&condvar_crit); 1906 ret = pSleepConditionVariableCS(&condvar_base, &condvar_crit, 10); 1907 LeaveCriticalSection (&condvar_crit); 1908 1909 ok (!ret, "SleepConditionVariableCS should return FALSE on untriggered condvar\n"); 1910 ok (GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableCS should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1911 1912 if (pInitializeSRWLock) 1913 { 1914 pAcquireSRWLockExclusive(&condvar_srwlock); 1915 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, 0); 1916 pReleaseSRWLockExclusive(&condvar_srwlock); 1917 1918 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); 1919 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1920 1921 pAcquireSRWLockShared(&condvar_srwlock); 1922 ret = pSleepConditionVariableSRW(&condvar_base, &condvar_srwlock, 10, CONDITION_VARIABLE_LOCKMODE_SHARED); 1923 pReleaseSRWLockShared(&condvar_srwlock); 1924 1925 ok(!ret, "SleepConditionVariableSRW should return FALSE on untriggered condvar\n"); 1926 ok(GetLastError() == ERROR_TIMEOUT, "SleepConditionVariableSRW should return ERROR_TIMEOUT on untriggered condvar, not %d\n", GetLastError()); 1927 } 1928 1929 1930 hp = CreateThread(NULL, 0, condvar_base_producer, NULL, 0, &dummy); 1931 hc = CreateThread(NULL, 0, condvar_base_consumer, NULL, 0, &dummy); 1932 1933 condvar_seq = 1; /* go */ 1934 1935 while (condvar_seq < 9) 1936 Sleep (5); 1937 WaitForSingleObject(hp, 100); 1938 WaitForSingleObject(hc, 100); 1939 } 1940 1941 static LONG srwlock_seq = 0; 1942 static SRWLOCK srwlock_base; 1943 static struct 1944 { 1945 LONG wrong_execution_order; 1946 LONG samethread_excl_excl; 1947 LONG samethread_excl_shared; 1948 LONG samethread_shared_excl; 1949 LONG multithread_excl_excl; 1950 LONG excl_not_preferred; 1951 LONG trylock_excl; 1952 LONG trylock_shared; 1953 } srwlock_base_errors; 1954 1955 /* Sequence of acquire/release to check boundary conditions: 1956 * 0: init 1957 * 1958 * 1: thread2 acquires an exclusive lock and tries to acquire a second exclusive lock 1959 * 2: thread1 expects a deadlock and releases the waiting lock 1960 * thread2 releases the lock again 1961 * 1962 * 3: thread2 acquires an exclusive lock and tries to acquire a shared lock 1963 * 4: thread1 expects a deadlock and releases the waiting lock 1964 * thread2 releases the lock again 1965 * 1966 * 5: thread2 acquires a shared lock and tries to acquire an exclusive lock 1967 * 6: thread1 expects a deadlock and releases the waiting lock 1968 * thread2 releases the lock again 1969 * 1970 * 7: thread2 acquires and releases two nested shared locks 1971 * 1972 * 8: thread1 acquires an exclusive lock 1973 * 9: thread2 tries to acquire the exclusive lock, too 1974 * thread1 releases the exclusive lock again 1975 * 10: thread2 enters the exclusive lock and leaves it immediately again 1976 * 1977 * 11: thread1 acquires a shared lock 1978 * 12: thread2 acquires and releases a shared lock 1979 * thread1 releases the lock again 1980 * 1981 * 13: thread1 acquires a shared lock 1982 * 14: thread2 tries to acquire an exclusive lock 1983 * 15: thread3 tries to acquire a shared lock 1984 * 16: thread1 releases the shared lock 1985 * 17: thread2 wakes up and releases the exclusive lock 1986 * 18: thread3 wakes up and releases the shared lock 1987 * 1988 * the following tests will only be executed if TryAcquireSRWLock* is available 1989 * 1990 * 19: thread1 calls TryAcquireSRWLockExclusive which should return TRUE 1991 * thread1 checks the result of recursive calls to TryAcquireSRWLock* 1992 * thread1 releases the exclusive lock 1993 * 1994 * thread1 calls TryAcquireSRWLockShared which should return TRUE 1995 * thread1 checks the result of recursive calls to TryAcquireSRWLock* 1996 * thread1 releases the shared lock 1997 * 1998 * thread1 acquires an exclusive lock 1999 * 20: thread2 calls TryAcquireSRWLockShared which should return FALSE 2000 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2001 * 21: thread1 releases the exclusive lock 2002 * 2003 * thread1 acquires an shared lock 2004 * 22: thread2 calls TryAcquireSRWLockShared which should return TRUE 2005 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2006 * 23: thread1 releases the shared lock 2007 * 2008 * thread1 acquires a shared lock and tries to acquire an exclusive lock 2009 * 24: thread2 calls TryAcquireSRWLockShared which should return FALSE 2010 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2011 * 25: thread1 releases the exclusive lock 2012 * 2013 * thread1 acquires two shared locks 2014 * 26: thread2 calls TryAcquireSRWLockShared which should return TRUE 2015 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2016 * 27: thread1 releases one shared lock 2017 * 28: thread2 calls TryAcquireSRWLockShared which should return TRUE 2018 * thread2 calls TryAcquireSRWLockExclusive which should return FALSE 2019 * 29: thread1 releases the second shared lock 2020 * 30: thread2 calls TryAcquireSRWLockShared which should return TRUE 2021 * thread2 calls TryAcquireSRWLockExclusive which should return TRUE 2022 * 2023 * 31: end 2024 */ 2025 2026 static DWORD WINAPI srwlock_base_thread1(LPVOID x) 2027 { 2028 /* seq 2 */ 2029 while (srwlock_seq < 2) Sleep(1); 2030 Sleep(100); 2031 if (InterlockedIncrement(&srwlock_seq) != 3) 2032 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl); 2033 pReleaseSRWLockExclusive(&srwlock_base); 2034 2035 /* seq 4 */ 2036 while (srwlock_seq < 4) Sleep(1); 2037 Sleep(100); 2038 if (InterlockedIncrement(&srwlock_seq) != 5) 2039 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared); 2040 pReleaseSRWLockExclusive(&srwlock_base); 2041 2042 /* seq 6 */ 2043 while (srwlock_seq < 6) Sleep(1); 2044 Sleep(100); 2045 if (InterlockedIncrement(&srwlock_seq) != 7) 2046 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl); 2047 pReleaseSRWLockShared(&srwlock_base); 2048 2049 /* seq 8 */ 2050 while (srwlock_seq < 8) Sleep(1); 2051 pAcquireSRWLockExclusive(&srwlock_base); 2052 if (InterlockedIncrement(&srwlock_seq) != 9) 2053 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2054 Sleep(100); 2055 if (InterlockedIncrement(&srwlock_seq) != 10) 2056 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl); 2057 pReleaseSRWLockExclusive(&srwlock_base); 2058 2059 /* seq 11 */ 2060 while (srwlock_seq < 11) Sleep(1); 2061 pAcquireSRWLockShared(&srwlock_base); 2062 if (InterlockedIncrement(&srwlock_seq) != 12) 2063 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2064 2065 /* seq 13 */ 2066 while (srwlock_seq < 13) Sleep(1); 2067 pReleaseSRWLockShared(&srwlock_base); 2068 pAcquireSRWLockShared(&srwlock_base); 2069 if (InterlockedIncrement(&srwlock_seq) != 14) 2070 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2071 2072 /* seq 16 */ 2073 while (srwlock_seq < 16) Sleep(1); 2074 Sleep(50); /* ensure that both the exclusive and shared access thread are queued */ 2075 if (InterlockedIncrement(&srwlock_seq) != 17) 2076 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2077 pReleaseSRWLockShared(&srwlock_base); 2078 2079 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2080 if (!pTryAcquireSRWLockExclusive) 2081 return 0; 2082 2083 /* seq 19 */ 2084 while (srwlock_seq < 19) Sleep(1); 2085 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2086 { 2087 if (pTryAcquireSRWLockShared(&srwlock_base)) 2088 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2089 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2090 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2091 pReleaseSRWLockExclusive(&srwlock_base); 2092 } 2093 else 2094 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2095 2096 if (pTryAcquireSRWLockShared(&srwlock_base)) 2097 { 2098 if (pTryAcquireSRWLockShared(&srwlock_base)) 2099 pReleaseSRWLockShared(&srwlock_base); 2100 else 2101 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2102 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2103 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2104 pReleaseSRWLockShared(&srwlock_base); 2105 } 2106 else 2107 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2108 2109 pAcquireSRWLockExclusive(&srwlock_base); 2110 if (InterlockedIncrement(&srwlock_seq) != 20) 2111 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2112 2113 /* seq 21 */ 2114 while (srwlock_seq < 21) Sleep(1); 2115 pReleaseSRWLockExclusive(&srwlock_base); 2116 pAcquireSRWLockShared(&srwlock_base); 2117 if (InterlockedIncrement(&srwlock_seq) != 22) 2118 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2119 2120 /* seq 23 */ 2121 while (srwlock_seq < 23) Sleep(1); 2122 pReleaseSRWLockShared(&srwlock_base); 2123 pAcquireSRWLockShared(&srwlock_base); 2124 if (InterlockedIncrement(&srwlock_seq) != 24) 2125 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2126 2127 /* seq 25 */ 2128 pAcquireSRWLockExclusive(&srwlock_base); 2129 if (srwlock_seq != 25) 2130 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2131 pReleaseSRWLockExclusive(&srwlock_base); 2132 2133 pAcquireSRWLockShared(&srwlock_base); 2134 pAcquireSRWLockShared(&srwlock_base); 2135 if (InterlockedIncrement(&srwlock_seq) != 26) 2136 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2137 2138 /* seq 27 */ 2139 while (srwlock_seq < 27) Sleep(1); 2140 pReleaseSRWLockShared(&srwlock_base); 2141 if (InterlockedIncrement(&srwlock_seq) != 28) 2142 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2143 2144 /* seq 29 */ 2145 while (srwlock_seq < 29) Sleep(1); 2146 pReleaseSRWLockShared(&srwlock_base); 2147 if (InterlockedIncrement(&srwlock_seq) != 30) 2148 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2149 2150 return 0; 2151 } 2152 2153 static DWORD WINAPI srwlock_base_thread2(LPVOID x) 2154 { 2155 /* seq 1 */ 2156 while (srwlock_seq < 1) Sleep(1); 2157 pAcquireSRWLockExclusive(&srwlock_base); 2158 if (InterlockedIncrement(&srwlock_seq) != 2) 2159 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2160 2161 /* seq 3 */ 2162 pAcquireSRWLockExclusive(&srwlock_base); 2163 if (srwlock_seq != 3) 2164 InterlockedIncrement(&srwlock_base_errors.samethread_excl_excl); 2165 pReleaseSRWLockExclusive(&srwlock_base); 2166 pAcquireSRWLockExclusive(&srwlock_base); 2167 if (InterlockedIncrement(&srwlock_seq) != 4) 2168 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2169 2170 /* seq 5 */ 2171 pAcquireSRWLockShared(&srwlock_base); 2172 if (srwlock_seq != 5) 2173 InterlockedIncrement(&srwlock_base_errors.samethread_excl_shared); 2174 pReleaseSRWLockShared(&srwlock_base); 2175 pAcquireSRWLockShared(&srwlock_base); 2176 if (InterlockedIncrement(&srwlock_seq) != 6) 2177 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2178 2179 /* seq 7 */ 2180 pAcquireSRWLockExclusive(&srwlock_base); 2181 if (srwlock_seq != 7) 2182 InterlockedIncrement(&srwlock_base_errors.samethread_shared_excl); 2183 pReleaseSRWLockExclusive(&srwlock_base); 2184 pAcquireSRWLockShared(&srwlock_base); 2185 pAcquireSRWLockShared(&srwlock_base); 2186 pReleaseSRWLockShared(&srwlock_base); 2187 pReleaseSRWLockShared(&srwlock_base); 2188 if (InterlockedIncrement(&srwlock_seq) != 8) 2189 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2190 2191 /* seq 9, 10 */ 2192 while (srwlock_seq < 9) Sleep(1); 2193 pAcquireSRWLockExclusive(&srwlock_base); 2194 if (srwlock_seq != 10) 2195 InterlockedIncrement(&srwlock_base_errors.multithread_excl_excl); 2196 pReleaseSRWLockExclusive(&srwlock_base); 2197 if (InterlockedIncrement(&srwlock_seq) != 11) 2198 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2199 2200 /* seq 12 */ 2201 while (srwlock_seq < 12) Sleep(1); 2202 pAcquireSRWLockShared(&srwlock_base); 2203 pReleaseSRWLockShared(&srwlock_base); 2204 if (InterlockedIncrement(&srwlock_seq) != 13) 2205 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2206 2207 /* seq 14 */ 2208 while (srwlock_seq < 14) Sleep(1); 2209 if (InterlockedIncrement(&srwlock_seq) != 15) 2210 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2211 2212 /* seq 17 */ 2213 pAcquireSRWLockExclusive(&srwlock_base); 2214 if (srwlock_seq != 17) 2215 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2216 if (InterlockedIncrement(&srwlock_seq) != 18) 2217 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2218 pReleaseSRWLockExclusive(&srwlock_base); 2219 2220 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2221 if (!pTryAcquireSRWLockExclusive) 2222 return 0; 2223 2224 /* seq 20 */ 2225 while (srwlock_seq < 20) Sleep(1); 2226 if (pTryAcquireSRWLockShared(&srwlock_base)) 2227 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2228 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2229 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2230 if (InterlockedIncrement(&srwlock_seq) != 21) 2231 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2232 2233 /* seq 22 */ 2234 while (srwlock_seq < 22) Sleep(1); 2235 if (pTryAcquireSRWLockShared(&srwlock_base)) 2236 pReleaseSRWLockShared(&srwlock_base); 2237 else 2238 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2239 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2240 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2241 if (InterlockedIncrement(&srwlock_seq) != 23) 2242 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2243 2244 /* seq 24 */ 2245 while (srwlock_seq < 24) Sleep(1); 2246 Sleep(50); /* ensure that exclusive access request is queued */ 2247 if (pTryAcquireSRWLockShared(&srwlock_base)) 2248 { 2249 pReleaseSRWLockShared(&srwlock_base); 2250 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2251 } 2252 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2253 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2254 if (InterlockedIncrement(&srwlock_seq) != 25) 2255 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2256 pReleaseSRWLockShared(&srwlock_base); 2257 2258 /* seq 26 */ 2259 while (srwlock_seq < 26) Sleep(1); 2260 if (pTryAcquireSRWLockShared(&srwlock_base)) 2261 pReleaseSRWLockShared(&srwlock_base); 2262 else 2263 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2264 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2265 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2266 if (InterlockedIncrement(&srwlock_seq) != 27) 2267 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2268 2269 /* seq 28 */ 2270 while (srwlock_seq < 28) Sleep(1); 2271 if (pTryAcquireSRWLockShared(&srwlock_base)) 2272 pReleaseSRWLockShared(&srwlock_base); 2273 else 2274 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2275 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2276 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2277 if (InterlockedIncrement(&srwlock_seq) != 29) 2278 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2279 2280 /* seq 30 */ 2281 while (srwlock_seq < 30) Sleep(1); 2282 if (pTryAcquireSRWLockShared(&srwlock_base)) 2283 pReleaseSRWLockShared(&srwlock_base); 2284 else 2285 InterlockedIncrement(&srwlock_base_errors.trylock_shared); 2286 if (pTryAcquireSRWLockExclusive(&srwlock_base)) 2287 pReleaseSRWLockExclusive(&srwlock_base); 2288 else 2289 InterlockedIncrement(&srwlock_base_errors.trylock_excl); 2290 if (InterlockedIncrement(&srwlock_seq) != 31) 2291 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2292 2293 return 0; 2294 } 2295 2296 static DWORD WINAPI srwlock_base_thread3(LPVOID x) 2297 { 2298 /* seq 15 */ 2299 while (srwlock_seq < 15) Sleep(1); 2300 Sleep(50); /* some delay, so that thread2 can try to acquire a second exclusive lock */ 2301 if (InterlockedIncrement(&srwlock_seq) != 16) 2302 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2303 2304 /* seq 18 */ 2305 pAcquireSRWLockShared(&srwlock_base); 2306 if (srwlock_seq != 18) 2307 InterlockedIncrement(&srwlock_base_errors.excl_not_preferred); 2308 pReleaseSRWLockShared(&srwlock_base); 2309 if (InterlockedIncrement(&srwlock_seq) != 19) 2310 InterlockedIncrement(&srwlock_base_errors.wrong_execution_order); 2311 2312 /* skip over remaining tests if TryAcquireSRWLock* is not available */ 2313 if (!pTryAcquireSRWLockExclusive) 2314 { 2315 /* function is only in Windows 7 and newer */ 2316 win_skip("no srw trylock support.\n"); 2317 srwlock_seq = 31; /* end */ 2318 return 0; 2319 } 2320 2321 return 0; 2322 } 2323 2324 static void test_srwlock_base(void) 2325 { 2326 HANDLE h1, h2, h3; 2327 DWORD dummy; 2328 2329 if (!pInitializeSRWLock) 2330 { 2331 /* function is not yet in XP, only in newer Windows */ 2332 win_skip("no srw lock support.\n"); 2333 return; 2334 } 2335 2336 pInitializeSRWLock(&srwlock_base); 2337 memset(&srwlock_base_errors, 0, sizeof(srwlock_base_errors)); 2338 2339 h1 = CreateThread(NULL, 0, srwlock_base_thread1, NULL, 0, &dummy); 2340 h2 = CreateThread(NULL, 0, srwlock_base_thread2, NULL, 0, &dummy); 2341 h3 = CreateThread(NULL, 0, srwlock_base_thread3, NULL, 0, &dummy); 2342 2343 srwlock_seq = 1; /* go */ 2344 while (srwlock_seq < 31) 2345 Sleep(5); 2346 2347 WaitForSingleObject(h1, 100); 2348 WaitForSingleObject(h2, 100); 2349 WaitForSingleObject(h3, 100); 2350 2351 ok(!srwlock_base_errors.wrong_execution_order, 2352 "thread commands were executed in the wrong order (occurred %d times).\n", 2353 srwlock_base_errors.wrong_execution_order); 2354 2355 ok(!srwlock_base_errors.samethread_excl_excl, 2356 "AcquireSRWLockExclusive didn't block when called multiple times from the same thread (occurred %d times).\n", 2357 srwlock_base_errors.samethread_excl_excl); 2358 2359 ok(!srwlock_base_errors.samethread_excl_shared, 2360 "AcquireSRWLockShared didn't block when the same thread holds an exclusive lock (occurred %d times).\n", 2361 srwlock_base_errors.samethread_excl_shared); 2362 2363 ok(!srwlock_base_errors.samethread_shared_excl, 2364 "AcquireSRWLockExclusive didn't block when the same thread holds a shared lock (occurred %d times).\n", 2365 srwlock_base_errors.samethread_shared_excl); 2366 2367 ok(!srwlock_base_errors.multithread_excl_excl, 2368 "AcquireSRWLockExclusive didn't block when a second thread holds the exclusive lock (occurred %d times).\n", 2369 srwlock_base_errors.multithread_excl_excl); 2370 2371 ok(!srwlock_base_errors.excl_not_preferred, 2372 "thread waiting for exclusive access to the SHMLock was not preferred (occurred %d times).\n", 2373 srwlock_base_errors.excl_not_preferred); 2374 2375 ok(!srwlock_base_errors.trylock_excl, 2376 "TryAcquireSRWLockExclusive didn't behave as expected (occurred %d times).\n", 2377 srwlock_base_errors.trylock_excl); 2378 2379 ok(!srwlock_base_errors.trylock_shared, 2380 "TryAcquireSRWLockShared didn't behave as expected (occurred %d times).\n", 2381 srwlock_base_errors.trylock_shared); 2382 2383 } 2384 2385 static SRWLOCK srwlock_example; 2386 static LONG srwlock_protected_value = 0; 2387 static LONG srwlock_example_errors = 0, srwlock_inside = 0, srwlock_cnt = 0; 2388 static BOOL srwlock_stop = FALSE; 2389 2390 static DWORD WINAPI srwlock_example_thread(LPVOID x) { 2391 DWORD *cnt = x; 2392 LONG old; 2393 2394 while (!srwlock_stop) 2395 { 2396 2397 /* periodically request exclusive access */ 2398 if (InterlockedIncrement(&srwlock_cnt) % 13 == 0) 2399 { 2400 pAcquireSRWLockExclusive(&srwlock_example); 2401 if (InterlockedIncrement(&srwlock_inside) != 1) 2402 InterlockedIncrement(&srwlock_example_errors); 2403 2404 InterlockedIncrement(&srwlock_protected_value); 2405 Sleep(1); 2406 2407 if (InterlockedDecrement(&srwlock_inside) != 0) 2408 InterlockedIncrement(&srwlock_example_errors); 2409 pReleaseSRWLockExclusive(&srwlock_example); 2410 } 2411 2412 /* request shared access */ 2413 pAcquireSRWLockShared(&srwlock_example); 2414 InterlockedIncrement(&srwlock_inside); 2415 old = srwlock_protected_value; 2416 2417 (*cnt)++; 2418 Sleep(1); 2419 2420 if (old != srwlock_protected_value) 2421 InterlockedIncrement(&srwlock_example_errors); 2422 InterlockedDecrement(&srwlock_inside); 2423 pReleaseSRWLockShared(&srwlock_example); 2424 } 2425 2426 return 0; 2427 } 2428 2429 static void test_srwlock_example(void) 2430 { 2431 HANDLE h1, h2, h3; 2432 DWORD dummy; 2433 DWORD cnt1, cnt2, cnt3; 2434 2435 if (!pInitializeSRWLock) { 2436 /* function is not yet in XP, only in newer Windows */ 2437 win_skip("no srw lock support.\n"); 2438 return; 2439 } 2440 2441 pInitializeSRWLock(&srwlock_example); 2442 2443 cnt1 = cnt2 = cnt3 = 0; 2444 2445 h1 = CreateThread(NULL, 0, srwlock_example_thread, &cnt1, 0, &dummy); 2446 h2 = CreateThread(NULL, 0, srwlock_example_thread, &cnt2, 0, &dummy); 2447 h3 = CreateThread(NULL, 0, srwlock_example_thread, &cnt3, 0, &dummy); 2448 2449 /* limit run to 1 second. */ 2450 Sleep(1000); 2451 2452 /* tear down start */ 2453 srwlock_stop = TRUE; 2454 2455 WaitForSingleObject(h1, 1000); 2456 WaitForSingleObject(h2, 1000); 2457 WaitForSingleObject(h3, 1000); 2458 2459 ok(!srwlock_inside, "threads didn't terminate properly, srwlock_inside is %d.\n", srwlock_inside); 2460 ok(!srwlock_example_errors, "errors occurred while running SRWLock example test (number of errors: %d)\n", 2461 srwlock_example_errors); 2462 2463 trace("number of shared accesses per thread are c1 %d, c2 %d, c3 %d\n", cnt1, cnt2, cnt3); 2464 trace("number of total exclusive accesses is %d\n", srwlock_protected_value); 2465 } 2466 2467 static DWORD WINAPI alertable_wait_thread(void *param) 2468 { 2469 HANDLE *semaphores = param; 2470 LARGE_INTEGER timeout; 2471 NTSTATUS status; 2472 DWORD result; 2473 2474 ReleaseSemaphore(semaphores[0], 1, NULL); 2475 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 1000, TRUE); 2476 ok(result == WAIT_IO_COMPLETION, "expected WAIT_IO_COMPLETION, got %u\n", result); 2477 result = WaitForMultipleObjectsEx(1, &semaphores[1], TRUE, 200, TRUE); 2478 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2479 2480 ReleaseSemaphore(semaphores[0], 1, NULL); 2481 timeout.QuadPart = -10000000; 2482 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2483 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status); 2484 timeout.QuadPart = -2000000; 2485 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2486 ok(status == STATUS_WAIT_0, "expected STATUS_WAIT_0, got %08x\n", status); 2487 2488 ReleaseSemaphore(semaphores[0], 1, NULL); 2489 timeout.QuadPart = -10000000; 2490 status = pNtWaitForMultipleObjects(1, &semaphores[1], FALSE, TRUE, &timeout); 2491 ok(status == STATUS_USER_APC, "expected STATUS_USER_APC, got %08x\n", status); 2492 result = WaitForSingleObject(semaphores[0], 0); 2493 ok(result == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", result); 2494 2495 return 0; 2496 } 2497 2498 static void CALLBACK alertable_wait_apc(ULONG_PTR userdata) 2499 { 2500 HANDLE *semaphores = (void *)userdata; 2501 ReleaseSemaphore(semaphores[1], 1, NULL); 2502 } 2503 2504 static void CALLBACK alertable_wait_apc2(ULONG_PTR userdata) 2505 { 2506 HANDLE *semaphores = (void *)userdata; 2507 DWORD result; 2508 2509 result = WaitForSingleObject(semaphores[0], 1000); 2510 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2511 } 2512 2513 static void test_alertable_wait(void) 2514 { 2515 HANDLE thread, semaphores[2]; 2516 DWORD result; 2517 2518 semaphores[0] = CreateSemaphoreW(NULL, 0, 2, NULL); 2519 ok(semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError()); 2520 semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL); 2521 ok(semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError()); 2522 thread = CreateThread(NULL, 0, alertable_wait_thread, semaphores, 0, NULL); 2523 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError()); 2524 2525 result = WaitForSingleObject(semaphores[0], 1000); 2526 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2527 Sleep(100); /* ensure the thread is blocking in WaitForMultipleObjectsEx */ 2528 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores); 2529 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2530 2531 result = WaitForSingleObject(semaphores[0], 1000); 2532 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2533 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */ 2534 result = QueueUserAPC(alertable_wait_apc, thread, (ULONG_PTR)semaphores); 2535 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2536 2537 result = WaitForSingleObject(semaphores[0], 1000); 2538 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2539 Sleep(100); /* ensure the thread is blocking in NtWaitForMultipleObjects */ 2540 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores); 2541 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2542 result = QueueUserAPC(alertable_wait_apc2, thread, (ULONG_PTR)semaphores); 2543 ok(result != 0, "QueueUserAPC failed with %u\n", GetLastError()); 2544 ReleaseSemaphore(semaphores[0], 2, NULL); 2545 2546 result = WaitForSingleObject(thread, 1000); 2547 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2548 CloseHandle(thread); 2549 CloseHandle(semaphores[0]); 2550 CloseHandle(semaphores[1]); 2551 } 2552 2553 struct apc_deadlock_info 2554 { 2555 PROCESS_INFORMATION *pi; 2556 HANDLE event; 2557 BOOL running; 2558 }; 2559 2560 static DWORD WINAPI apc_deadlock_thread(void *param) 2561 { 2562 struct apc_deadlock_info *info = param; 2563 PROCESS_INFORMATION *pi = info->pi; 2564 NTSTATUS status; 2565 SIZE_T size; 2566 void *base; 2567 2568 while (info->running) 2569 { 2570 base = NULL; 2571 size = 0x1000; 2572 status = pNtAllocateVirtualMemory(pi->hProcess, &base, 0, &size, 2573 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 2574 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status); 2575 ok(base != NULL, "expected base != NULL, got %p\n", base); 2576 SetEvent(info->event); 2577 2578 size = 0; 2579 status = pNtFreeVirtualMemory(pi->hProcess, &base, &size, MEM_RELEASE); 2580 ok(!status, "expected STATUS_SUCCESS, got %08x\n", status); 2581 SetEvent(info->event); 2582 } 2583 2584 return 0; 2585 } 2586 2587 static void test_apc_deadlock(void) 2588 { 2589 struct apc_deadlock_info info; 2590 PROCESS_INFORMATION pi; 2591 STARTUPINFOA si = { sizeof(si) }; 2592 char cmdline[MAX_PATH]; 2593 HANDLE event, thread; 2594 DWORD result; 2595 BOOL success; 2596 char **argv; 2597 int i; 2598 2599 winetest_get_mainargs(&argv); 2600 sprintf(cmdline, "\"%s\" sync apc_deadlock", argv[0]); 2601 success = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 2602 ok(success, "CreateProcess failed with %u\n", GetLastError()); 2603 2604 event = CreateEventA(NULL, FALSE, FALSE, NULL); 2605 ok(event != NULL, "CreateEvent failed with %u\n", GetLastError()); 2606 2607 info.pi = π 2608 info.event = event; 2609 info.running = TRUE; 2610 2611 thread = CreateThread(NULL, 0, apc_deadlock_thread, &info, 0, NULL); 2612 ok(thread != NULL, "CreateThread failed with %u\n", GetLastError()); 2613 result = WaitForSingleObject(event, 1000); 2614 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2615 2616 for (i = 0; i < 1000; i++) 2617 { 2618 result = SuspendThread(pi.hThread); 2619 ok(result == 0, "expected 0, got %u\n", result); 2620 2621 WaitForSingleObject(event, 0); /* reset event */ 2622 result = WaitForSingleObject(event, 1000); 2623 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2624 2625 result = ResumeThread(pi.hThread); 2626 ok(result == 1, "expected 1, got %u\n", result); 2627 Sleep(1); 2628 } 2629 2630 info.running = FALSE; 2631 result = WaitForSingleObject(thread, 1000); 2632 ok(result == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", result); 2633 CloseHandle(thread); 2634 CloseHandle(event); 2635 2636 TerminateProcess(pi.hProcess, 0); 2637 CloseHandle(pi.hThread); 2638 CloseHandle(pi.hProcess); 2639 } 2640 2641 START_TEST(sync) 2642 { 2643 char **argv; 2644 int argc; 2645 HMODULE hdll = GetModuleHandleA("kernel32.dll"); 2646 HMODULE hntdll = GetModuleHandleA("ntdll.dll"); 2647 #ifdef __REACTOS__ 2648 HMODULE hdll_vista = GetModuleHandleA("kernel32_vista.dll"); 2649 #endif 2650 2651 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize"); 2652 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce"); 2653 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize"); 2654 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete"); 2655 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable"); 2656 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS"); 2657 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW"); 2658 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable"); 2659 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable"); 2660 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock"); 2661 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive"); 2662 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared"); 2663 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive"); 2664 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared"); 2665 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive"); 2666 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); 2667 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); 2668 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); 2669 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); 2670 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); 2671 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); 2672 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx"); 2673 2674 #ifdef __REACTOS__ 2675 if (!pInitializeConditionVariable) 2676 { 2677 pInitializeConditionVariable = (void *)GetProcAddress(hdll_vista, "InitializeConditionVariable"); 2678 pSleepConditionVariableCS = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableCS"); 2679 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll_vista, "SleepConditionVariableSRW"); 2680 pWakeAllConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeAllConditionVariable"); 2681 pWakeConditionVariable = (void *)GetProcAddress(hdll_vista, "WakeConditionVariable"); 2682 } 2683 2684 if (!pInitializeSRWLock) 2685 { 2686 pInitializeSRWLock = (void *)GetProcAddress(hdll_vista, "InitializeSRWLock"); 2687 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockExclusive"); 2688 pAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "AcquireSRWLockShared"); 2689 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockExclusive"); 2690 pReleaseSRWLockShared = (void *)GetProcAddress(hdll_vista, "ReleaseSRWLockShared"); 2691 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockExclusive"); 2692 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll_vista, "TryAcquireSRWLockShared"); 2693 } 2694 #endif 2695 2696 argc = winetest_get_mainargs( &argv ); 2697 if (argc >= 3) 2698 { 2699 if (!strcmp(argv[2], "apc_deadlock")) 2700 { 2701 for (;;) SleepEx(INFINITE, TRUE); 2702 } 2703 return; 2704 } 2705 2706 init_fastcall_thunk(); 2707 test_signalandwait(); 2708 test_mutex(); 2709 test_slist(); 2710 test_event(); 2711 test_semaphore(); 2712 test_waitable_timer(); 2713 test_iocp_callback(); 2714 test_timer_queue(); 2715 test_WaitForSingleObject(); 2716 test_WaitForMultipleObjects(); 2717 test_initonce(); 2718 test_condvars_base(); 2719 test_condvars_consumer_producer(); 2720 test_srwlock_base(); 2721 test_srwlock_example(); 2722 test_alertable_wait(); 2723 test_apc_deadlock(); 2724 } 2725