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 #include "precomp.h" 22 23 #define QueryDepthSList(x) RtlQueryDepthSList(x) 24 #define InterlockedPushEntrySList(x,y) RtlInterlockedPushEntrySList(x,y) 25 #define InterlockedPopEntrySList(x) RtlInterlockedPopEntrySList(x) 26 #define InterlockedFlushSList(x) RtlInterlockedFlushSList(x) 27 28 #undef __fastcall 29 #define __fastcall __stdcall 30 31 static BOOL (WINAPI *pChangeTimerQueueTimer)(HANDLE, HANDLE, ULONG, ULONG); 32 static HANDLE (WINAPI *pCreateTimerQueue)(void); 33 static BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE, HANDLE, WAITORTIMERCALLBACK, 34 PVOID, DWORD, DWORD, ULONG); 35 static HANDLE (WINAPI *pCreateWaitableTimerA)(SECURITY_ATTRIBUTES*,BOOL,LPCSTR); 36 static BOOL (WINAPI *pDeleteTimerQueueEx)(HANDLE, HANDLE); 37 static BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE, HANDLE, HANDLE); 38 static HANDLE (WINAPI *pOpenWaitableTimerA)(DWORD,BOOL,LPCSTR); 39 static HANDLE (WINAPI *pCreateMemoryResourceNotification)(MEMORY_RESOURCE_NOTIFICATION_TYPE); 40 static BOOL (WINAPI *pQueryMemoryResourceNotification)(HANDLE, PBOOL); 41 static VOID (WINAPI *pInitOnceInitialize)(PINIT_ONCE); 42 static BOOL (WINAPI *pInitOnceExecuteOnce)(PINIT_ONCE,PINIT_ONCE_FN,PVOID,LPVOID*); 43 static BOOL (WINAPI *pInitOnceBeginInitialize)(PINIT_ONCE,DWORD,BOOL*,LPVOID*); 44 static BOOL (WINAPI *pInitOnceComplete)(PINIT_ONCE,DWORD,LPVOID); 45 46 static VOID (WINAPI *pInitializeConditionVariable)(PCONDITION_VARIABLE); 47 static BOOL (WINAPI *pSleepConditionVariableCS)(PCONDITION_VARIABLE,PCRITICAL_SECTION,DWORD); 48 static BOOL (WINAPI *pSleepConditionVariableSRW)(PCONDITION_VARIABLE,PSRWLOCK,DWORD,ULONG); 49 static VOID (WINAPI *pWakeAllConditionVariable)(PCONDITION_VARIABLE); 50 static VOID (WINAPI *pWakeConditionVariable)(PCONDITION_VARIABLE); 51 52 static VOID (WINAPI *pInitializeSRWLock)(PSRWLOCK); 53 static VOID (WINAPI *pAcquireSRWLockExclusive)(PSRWLOCK); 54 static VOID (WINAPI *pAcquireSRWLockShared)(PSRWLOCK); 55 static VOID (WINAPI *pReleaseSRWLockExclusive)(PSRWLOCK); 56 static VOID (WINAPI *pReleaseSRWLockShared)(PSRWLOCK); 57 static BOOLEAN (WINAPI *pTryAcquireSRWLockExclusive)(PSRWLOCK); 58 static BOOLEAN (WINAPI *pTryAcquireSRWLockShared)(PSRWLOCK); 59 60 static NTSTATUS (WINAPI *pNtAllocateVirtualMemory)(HANDLE, PVOID *, ULONG, SIZE_T *, ULONG, ULONG); 61 static NTSTATUS (WINAPI *pNtFreeVirtualMemory)(HANDLE, PVOID *, SIZE_T *, ULONG); 62 static NTSTATUS (WINAPI *pNtWaitForSingleObject)(HANDLE, BOOLEAN, const LARGE_INTEGER *); 63 static NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); 64 static PSLIST_ENTRY (__fastcall *pRtlInterlockedPushListSList)(PSLIST_HEADER list, PSLIST_ENTRY first, 65 PSLIST_ENTRY last, ULONG count); 66 static PSLIST_ENTRY (WINAPI *pRtlInterlockedPushListSListEx)(PSLIST_HEADER list, PSLIST_ENTRY first, 67 PSLIST_ENTRY last, ULONG count); 68 69 #ifdef __i386__ 70 71 #include "pshpack1.h" 72 struct fastcall_thunk 73 { 74 BYTE pop_edx; /* popl %edx (ret addr) */ 75 BYTE pop_eax; /* popl %eax (func) */ 76 BYTE pop_ecx; /* popl %ecx (param 1) */ 77 BYTE xchg[3]; /* xchgl (%esp),%edx (param 2) */ 78 WORD jmp_eax; /* jmp *%eax */ 79 }; 80 #include "poppack.h" 81 82 static void * (WINAPI *call_fastcall_func4)(void *func, const void *a, const void *b, const void *c, const void *d); 83 84 static void init_fastcall_thunk(void) 85 { 86 struct fastcall_thunk *thunk = VirtualAlloc(NULL, sizeof(*thunk), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 87 thunk->pop_edx = 0x5a; /* popl %edx */ 88 thunk->pop_eax = 0x58; /* popl %eax */ 89 thunk->pop_ecx = 0x59; /* popl %ecx */ 90 thunk->xchg[0] = 0x87; /* xchgl (%esp),%edx */ 91 thunk->xchg[1] = 0x14; 92 thunk->xchg[2] = 0x24; 93 thunk->jmp_eax = 0xe0ff; /* jmp *%eax */ 94 call_fastcall_func4 = (void *)thunk; 95 } 96 97 #define call_func4(func, a, b, c, d) call_fastcall_func4(func, (const void *)(a), \ 98 (const void *)(b), (const void *)(c), (const void *)(d)) 99 100 #else /* __i386__ */ 101 102 #define init_fastcall_thunk() do { } while(0) 103 #define call_func4(func, a, b, c, d) func(a, b, c, d) 104 105 #endif /* __i386__ */ 106 107 static void test_signalandwait(void) 108 { 109 DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL); 110 HMODULE kernel32; 111 DWORD r; 112 HANDLE event[2], semaphore[2], file; 113 int i; 114 115 kernel32 = GetModuleHandleA("kernel32.dll"); 116 pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait"); 117 118 if (!pSignalObjectAndWait) 119 return; 120 121 /* invalid parameters */ 122 r = pSignalObjectAndWait(NULL, NULL, 0, 0); 123 if (r == ERROR_INVALID_FUNCTION) 124 { 125 win_skip("SignalObjectAndWait is not implemented\n"); 126 return; /* Win98/ME */ 127 } 128 ok( r == WAIT_FAILED, "should fail\n"); 129 130 event[0] = CreateEventW(NULL, 0, 0, NULL); 131 event[1] = CreateEventW(NULL, 1, 1, NULL); 132 133 ok( event[0] && event[1], "failed to create event flags\n"); 134 135 r = pSignalObjectAndWait(event[0], NULL, 0, FALSE); 136 ok( r == WAIT_FAILED, "should fail\n"); 137 138 r = pSignalObjectAndWait(NULL, event[0], 0, FALSE); 139 ok( r == WAIT_FAILED, "should fail\n"); 140 141 142 /* valid parameters */ 143 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE); 144 ok( r == WAIT_OBJECT_0, "should succeed\n"); 145 146 /* event[0] is now signalled - we repeat this test multiple times 147 * to ensure that the wineserver handles this situation properly. */ 148 for (i = 0; i < 10000; i++) 149 { 150 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE); 151 ok(r == WAIT_OBJECT_0, "should succeed\n"); 152 } 153 154 /* event[0] is not signalled */ 155 r = WaitForSingleObject(event[0], 0); 156 ok( r == WAIT_TIMEOUT, "event was signalled\n"); 157 158 r = pSignalObjectAndWait(event[0], event[0], 0, FALSE); 159 ok( r == WAIT_OBJECT_0, "should succeed\n"); 160 161 /* clear event[1] and check for a timeout */ 162 ok(ResetEvent(event[1]), "failed to clear event[1]\n"); 163 r = pSignalObjectAndWait(event[0], event[1], 0, FALSE); 164 ok( r == WAIT_TIMEOUT, "should timeout\n"); 165 166 CloseHandle(event[0]); 167 CloseHandle(event[1]); 168 169 /* semaphores */ 170 semaphore[0] = CreateSemaphoreW( NULL, 0, 1, NULL ); 171 semaphore[1] = CreateSemaphoreW( NULL, 1, 1, NULL ); 172 ok( semaphore[0] && semaphore[1], "failed to create semaphore\n"); 173 174 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 175 ok( r == WAIT_OBJECT_0, "should succeed\n"); 176 177 r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE); 178 ok( r == WAIT_FAILED, "should fail\n"); 179 180 r = ReleaseSemaphore(semaphore[0],1,NULL); 181 ok( r == FALSE, "should fail\n"); 182 183 r = ReleaseSemaphore(semaphore[1],1,NULL); 184 ok( r == TRUE, "should succeed\n"); 185 186 CloseHandle(semaphore[0]); 187 CloseHandle(semaphore[1]); 188 189 /* try a registry key */ 190 file = CreateFileA("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 191 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); 192 r = pSignalObjectAndWait(file, file, 0, FALSE); 193 ok( r == WAIT_FAILED, "should fail\n"); 194 ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n"); 195 CloseHandle(file); 196 } 197 198 static void test_mutex(void) 199 { 200 DWORD wait_ret; 201 BOOL ret; 202 HANDLE hCreated; 203 HANDLE hOpened; 204 int i; 205 DWORD failed = 0; 206 207 SetLastError(0xdeadbeef); 208 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 209 ok(hOpened == NULL, "OpenMutex succeeded\n"); 210 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 211 212 SetLastError(0xdeadbeef); 213 hCreated = CreateMutexA(NULL, FALSE, "WineTestMutex"); 214 ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError()); 215 216 SetLastError(0xdeadbeef); 217 hOpened = OpenMutexA(0, FALSE, "WineTestMutex"); 218 todo_wine 219 ok(hOpened == NULL, "OpenMutex succeeded\n"); 220 todo_wine 221 ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError()); 222 223 SetLastError(0xdeadbeef); 224 hOpened = OpenMutexA(GENERIC_EXECUTE, FALSE, "WineTestMutex"); 225 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 226 wait_ret = WaitForSingleObject(hOpened, INFINITE); 227 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError()); 228 CloseHandle(hOpened); 229 230 for(i=0; i < 31; i++) 231 { 232 wait_ret = WaitForSingleObject(hCreated, INFINITE); 233 ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret); 234 } 235 236 SetLastError(0xdeadbeef); 237 hOpened = OpenMutexA(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); 238 ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); 239 wait_ret = WaitForSingleObject(hOpened, INFINITE); 240 ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); 241 CloseHandle(hOpened); 242 243 for (i = 0; i < 32; i++) 244 { 245 SetLastError(0xdeadbeef); 246 hOpened = OpenMutexA(0x1 << i, FALSE, "WineTestMutex"); 247 if(hOpened != NULL) 248 { 249 SetLastError(0xdeadbeef); 250 ret = ReleaseMutex(hOpened); 251 ok(ret, "ReleaseMutex failed with error %d, access %x\n", GetLastError(), 1 << i); 252 CloseHandle(hOpened); 253 } 254 else 255 { 256 if ((1 << i) == ACCESS_SYSTEM_SECURITY) 257 todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "wrong error %u, access %x\n", GetLastError(), 1 << i); 258 else 259 todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u, , access %x\n", GetLastError(), 1 << i); 260 ReleaseMutex(hCreated); 261 failed |=0x1 << i; 262 } 263 } 264 265 todo_wine 266 ok( failed == 0x0de0fffe, "open succeeded when it shouldn't: %x\n", failed); 267 268 SetLastError(0xdeadbeef); 269 ret = ReleaseMutex(hCreated); 270 ok(!ret && (GetLastError() == ERROR_NOT_OWNER), 271 "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError()); 272 273 /* test case sensitivity */ 274 275 SetLastError(0xdeadbeef); 276 hOpened = OpenMutexA(READ_CONTROL, FALSE, "WINETESTMUTEX"); 277 ok(!hOpened, "OpenMutex succeeded\n"); 278 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 279 280 SetLastError(0xdeadbeef); 281 hOpened = OpenMutexA(READ_CONTROL, FALSE, "winetestmutex"); 282 ok(!hOpened, "OpenMutex succeeded\n"); 283 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 284 285 SetLastError(0xdeadbeef); 286 hOpened = CreateMutexA(NULL, FALSE, "WineTestMutex"); 287 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 288 ok(GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 289 CloseHandle(hOpened); 290 291 SetLastError(0xdeadbeef); 292 hOpened = CreateMutexA(NULL, FALSE, "WINETESTMUTEX"); 293 ok(hOpened != NULL, "CreateMutex failed with error %d\n", GetLastError()); 294 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 295 CloseHandle(hOpened); 296 297 CloseHandle(hCreated); 298 } 299 300 static void test_slist(void) 301 { 302 struct item 303 { 304 SLIST_ENTRY entry; 305 int value; 306 } item1, item2, item3, *item; 307 SLIST_HEADER slist_header; 308 SLIST_ENTRY *entry; 309 USHORT size; 310 int i; 311 312 item1.value = 1; 313 item2.value = 2; 314 item3.value = 3; 315 316 memset(&slist_header, 0xff, sizeof(slist_header)); 317 InitializeSListHead(&slist_header); 318 size = QueryDepthSList(&slist_header); 319 ok(size == 0, "Expected size == 0, got %u\n", size); 320 321 /* test PushEntry, PopEntry and Flush */ 322 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 323 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 324 size = QueryDepthSList(&slist_header); 325 ok(size == 1, "Expected size == 1, got %u\n", size); 326 327 entry = InterlockedPushEntrySList(&slist_header, &item2.entry); 328 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 329 item = CONTAINING_RECORD(entry, struct item, entry); 330 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 331 size = QueryDepthSList(&slist_header); 332 ok(size == 2, "Expected size == 2, got %u\n", size); 333 334 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 335 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 336 item = CONTAINING_RECORD(entry, struct item, entry); 337 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 338 size = QueryDepthSList(&slist_header); 339 ok(size == 3, "Expected size == 3, got %u\n", size); 340 341 entry = InterlockedPopEntrySList(&slist_header); 342 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 343 item = CONTAINING_RECORD(entry, struct item, entry); 344 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 345 size = QueryDepthSList(&slist_header); 346 ok(size == 2, "Expected size == 2, got %u\n", size); 347 348 entry = InterlockedFlushSList(&slist_header); 349 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 350 item = CONTAINING_RECORD(entry, struct item, entry); 351 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 352 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 353 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 354 size = QueryDepthSList(&slist_header); 355 ok(size == 0, "Expected size == 0, got %u\n", size); 356 entry = InterlockedPopEntrySList(&slist_header); 357 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 358 359 /* test RtlInterlockedPushListSList */ 360 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 361 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 362 entry = call_func4(pRtlInterlockedPushListSList, &slist_header, &item2.entry, &item1.entry, 42); 363 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 364 item = CONTAINING_RECORD(entry, struct item, entry); 365 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 366 size = QueryDepthSList(&slist_header); 367 ok(size == 43, "Expected size == 43, got %u\n", size); 368 369 entry = InterlockedPopEntrySList(&slist_header); 370 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 371 item = CONTAINING_RECORD(entry, struct item, entry); 372 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 373 size = QueryDepthSList(&slist_header); 374 ok(size == 42, "Expected size == 42, got %u\n", size); 375 376 entry = InterlockedPopEntrySList(&slist_header); 377 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 378 item = CONTAINING_RECORD(entry, struct item, entry); 379 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 380 size = QueryDepthSList(&slist_header); 381 ok(size == 41, "Expected size == 41, got %u\n", size); 382 383 entry = InterlockedPopEntrySList(&slist_header); 384 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 385 item = CONTAINING_RECORD(entry, struct item, entry); 386 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 387 size = QueryDepthSList(&slist_header); 388 ok(size == 40, "Expected size == 40, got %u\n", size); 389 390 entry = InterlockedPopEntrySList(&slist_header); 391 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 392 size = QueryDepthSList(&slist_header); 393 ok(size == 40, "Expected size == 40, got %u\n", size); 394 395 entry = InterlockedFlushSList(&slist_header); 396 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 397 size = QueryDepthSList(&slist_header); 398 ok(size == 40 || broken(size == 0) /* >= Win 8 */, "Expected size == 40, got %u\n", size); 399 400 entry = InterlockedPushEntrySList(&slist_header, &item1.entry); 401 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 402 entry = InterlockedFlushSList(&slist_header); 403 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 404 item = CONTAINING_RECORD(entry, struct item, entry); 405 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 406 size = QueryDepthSList(&slist_header); 407 ok(size == 0, "Expected size == 0, got %u\n", size); 408 409 /* test RtlInterlockedPushListSListEx */ 410 if (pRtlInterlockedPushListSListEx) 411 { 412 entry = InterlockedPushEntrySList(&slist_header, &item3.entry); 413 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 414 entry = pRtlInterlockedPushListSListEx(&slist_header, &item2.entry, &item1.entry, 42); 415 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 416 item = CONTAINING_RECORD(entry, struct item, entry); 417 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 418 size = QueryDepthSList(&slist_header); 419 ok(size == 43, "Expected size == 43, got %u\n", size); 420 421 entry = InterlockedFlushSList(&slist_header); 422 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 423 item = CONTAINING_RECORD(entry, struct item, entry); 424 ok(item->value == 2, "Expected item->value == 2, got %u\n", item->value); 425 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 426 ok(item->value == 1, "Expected item->value == 1, got %u\n", item->value); 427 item = CONTAINING_RECORD(item->entry.Next, struct item, entry); 428 ok(item->value == 3, "Expected item->value == 3, got %u\n", item->value); 429 size = QueryDepthSList(&slist_header); 430 ok(size == 0, "Expected size == 0, got %u\n", size); 431 } 432 else 433 win_skip("RtlInterlockedPushListSListEx not available, skipping tests\n"); 434 435 /* test with a lot of items */ 436 for (i = 0; i < 65536; i++) 437 { 438 item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item)); 439 item->value = i + 1; 440 entry = InterlockedPushEntrySList(&slist_header, &item->entry); 441 if (i) 442 { 443 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 444 item = CONTAINING_RECORD(entry, struct item, entry); 445 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 446 } 447 else 448 { 449 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 450 } 451 size = QueryDepthSList(&slist_header); 452 ok(size == ((i + 1) & 0xffff), "Expected size == %u, got %u\n", (i + 1) & 0xffff, size); 453 } 454 455 entry = InterlockedFlushSList(&slist_header); 456 for (i = 65536; i > 0; i--) 457 { 458 ok(entry != NULL, "Expected entry != NULL, got %p\n", entry); 459 item = CONTAINING_RECORD(entry, struct item, entry); 460 ok(item->value == i, "Expected item->value == %u, got %u\n", i, item->value); 461 entry = item->entry.Next; 462 HeapFree(GetProcessHeap(), 0, item); 463 } 464 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 465 size = QueryDepthSList(&slist_header); 466 ok(size == 0, "Expected size == 0, got %u\n", size); 467 entry = InterlockedPopEntrySList(&slist_header); 468 ok(entry == NULL, "Expected entry == NULL, got %p\n", entry); 469 } 470 471 static void test_event(void) 472 { 473 HANDLE handle, handle2; 474 SECURITY_ATTRIBUTES sa; 475 SECURITY_DESCRIPTOR sd; 476 ACL acl; 477 DWORD ret; 478 BOOL val; 479 480 /* no sd */ 481 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 482 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 483 CloseHandle(handle); 484 485 sa.nLength = sizeof(sa); 486 sa.lpSecurityDescriptor = &sd; 487 sa.bInheritHandle = FALSE; 488 489 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 490 491 /* blank sd */ 492 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 493 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 494 CloseHandle(handle); 495 496 /* sd with NULL dacl */ 497 SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); 498 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 499 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 500 CloseHandle(handle); 501 502 /* sd with empty dacl */ 503 InitializeAcl(&acl, sizeof(acl), ACL_REVISION); 504 SetSecurityDescriptorDacl(&sd, TRUE, &acl, FALSE); 505 handle = CreateEventA(&sa, FALSE, FALSE, __FILE__ ": Test Event"); 506 ok(handle != NULL, "CreateEventW with blank sd failed with error %d\n", GetLastError()); 507 CloseHandle(handle); 508 509 /* test case sensitivity */ 510 511 SetLastError(0xdeadbeef); 512 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 513 ok( handle != NULL, "CreateEvent failed with error %u\n", GetLastError()); 514 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 515 516 SetLastError(0xdeadbeef); 517 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 518 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 519 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 520 CloseHandle( handle2 ); 521 522 SetLastError(0xdeadbeef); 523 handle2 = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": TEST EVENT"); 524 ok( handle2 != NULL, "CreateEvent failed with error %d\n", GetLastError()); 525 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 526 CloseHandle( handle2 ); 527 528 SetLastError(0xdeadbeef); 529 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": Test Event"); 530 ok( handle2 != NULL, "OpenEvent failed with error %d\n", GetLastError()); 531 CloseHandle( handle2 ); 532 533 SetLastError(0xdeadbeef); 534 handle2 = OpenEventA( EVENT_ALL_ACCESS, FALSE, __FILE__ ": TEST EVENT"); 535 ok( !handle2, "OpenEvent succeeded\n"); 536 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 537 538 CloseHandle( handle ); 539 540 /* resource notifications are events too */ 541 542 if (!pCreateMemoryResourceNotification || !pQueryMemoryResourceNotification) 543 { 544 trace( "memory resource notifications not supported\n" ); 545 return; 546 } 547 handle = pCreateMemoryResourceNotification( HighMemoryResourceNotification + 1 ); 548 ok( !handle, "CreateMemoryResourceNotification succeeded\n" ); 549 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 550 ret = pQueryMemoryResourceNotification( handle, &val ); 551 ok( !ret, "QueryMemoryResourceNotification succeeded\n" ); 552 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 553 554 handle = pCreateMemoryResourceNotification( LowMemoryResourceNotification ); 555 ok( handle != 0, "CreateMemoryResourceNotification failed err %u\n", GetLastError() ); 556 ret = WaitForSingleObject( handle, 10 ); 557 ok( ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT, "WaitForSingleObject wrong ret %u\n", ret ); 558 559 val = ~0; 560 ret = pQueryMemoryResourceNotification( handle, &val ); 561 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 562 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 563 ret = CloseHandle( handle ); 564 ok( ret, "CloseHandle failed err %u\n", GetLastError() ); 565 566 handle = CreateEventA(NULL, FALSE, FALSE, __FILE__ ": Test Event"); 567 val = ~0; 568 ret = pQueryMemoryResourceNotification( handle, &val ); 569 ok( ret, "QueryMemoryResourceNotification failed err %u\n", GetLastError() ); 570 ok( val == FALSE || val == TRUE, "wrong value %u\n", val ); 571 CloseHandle( handle ); 572 } 573 574 static void test_semaphore(void) 575 { 576 HANDLE handle, handle2; 577 578 /* test case sensitivity */ 579 580 SetLastError(0xdeadbeef); 581 handle = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 582 ok(handle != NULL, "CreateSemaphore failed with error %u\n", GetLastError()); 583 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 584 585 SetLastError(0xdeadbeef); 586 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": Test Semaphore"); 587 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 588 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 589 CloseHandle( handle2 ); 590 591 SetLastError(0xdeadbeef); 592 handle2 = CreateSemaphoreA(NULL, 0, 1, __FILE__ ": TEST SEMAPHORE"); 593 ok( handle2 != NULL, "CreateSemaphore failed with error %d\n", GetLastError()); 594 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 595 CloseHandle( handle2 ); 596 597 SetLastError(0xdeadbeef); 598 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": Test Semaphore"); 599 ok( handle2 != NULL, "OpenSemaphore failed with error %d\n", GetLastError()); 600 CloseHandle( handle2 ); 601 602 SetLastError(0xdeadbeef); 603 handle2 = OpenSemaphoreA( SEMAPHORE_ALL_ACCESS, FALSE, __FILE__ ": TEST SEMAPHORE"); 604 ok( !handle2, "OpenSemaphore succeeded\n"); 605 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError()); 606 607 CloseHandle( handle ); 608 } 609 610 static void test_waitable_timer(void) 611 { 612 HANDLE handle, handle2; 613 614 if (!pCreateWaitableTimerA || !pOpenWaitableTimerA) 615 { 616 win_skip("{Create,Open}WaitableTimerA() is not available\n"); 617 return; 618 } 619 620 /* test case sensitivity */ 621 622 SetLastError(0xdeadbeef); 623 handle = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 624 ok(handle != NULL, "CreateWaitableTimer failed with error %u\n", GetLastError()); 625 ok(GetLastError() == 0, "wrong error %u\n", GetLastError()); 626 627 SetLastError(0xdeadbeef); 628 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": Test WaitableTimer"); 629 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 630 ok( GetLastError() == ERROR_ALREADY_EXISTS, "wrong error %u\n", GetLastError()); 631 CloseHandle( handle2 ); 632 633 SetLastError(0xdeadbeef); 634 handle2 = pCreateWaitableTimerA(NULL, FALSE, __FILE__ ": TEST WAITABLETIMER"); 635 ok( handle2 != NULL, "CreateWaitableTimer failed with error %d\n", GetLastError()); 636 ok( GetLastError() == 0, "wrong error %u\n", GetLastError()); 637 CloseHandle( handle2 ); 638 639 SetLastError(0xdeadbeef); 640 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": Test WaitableTimer"); 641 ok( handle2 != NULL, "OpenWaitableTimer failed with error %d\n", GetLastError()); 642 CloseHandle( handle2 ); 643 644 SetLastError(0xdeadbeef); 645 handle2 = pOpenWaitableTimerA( TIMER_ALL_ACCESS, FALSE, __FILE__ ": TEST WAITABLETIMER"); 646 ok( !handle2, "OpenWaitableTimer succeeded\n"); 647 ok( GetLastError() == ERROR_FILE_NOT_FOUND || 648 GetLastError() == ERROR_INVALID_NAME, /* win98 */ 649 "wrong error %u\n", GetLastError()); 650 651 CloseHandle( handle ); 652 } 653 654 static HANDLE sem = 0; 655 656 static void CALLBACK iocp_callback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped) 657 { 658 ReleaseSemaphore(sem, 1, NULL); 659 } 660 661 static BOOL (WINAPI *p_BindIoCompletionCallback)( HANDLE FileHandle, LPOVERLAPPED_COMPLETION_ROUTINE Function, ULONG Flags) = NULL; 662 663 static void test_iocp_callback(void) 664 { 665 char temp_path[MAX_PATH]; 666 char filename[MAX_PATH]; 667 DWORD ret; 668 BOOL retb; 669 static const char prefix[] = "pfx"; 670 HANDLE hFile; 671 HMODULE hmod = GetModuleHandleA("kernel32.dll"); 672 DWORD bytesWritten; 673 const char *buffer = "12345678123456781234567812345678"; 674 OVERLAPPED overlapped; 675 676 p_BindIoCompletionCallback = (void*)GetProcAddress(hmod, "BindIoCompletionCallback"); 677 if(!p_BindIoCompletionCallback) { 678 win_skip("BindIoCompletionCallback not found in this DLL\n"); 679 return; 680 } 681 682 sem = CreateSemaphoreW(NULL, 0, 1, NULL); 683 ok(sem != INVALID_HANDLE_VALUE, "Creating a semaphore failed\n"); 684 685 ret = GetTempPathA(MAX_PATH, temp_path); 686 ok(ret != 0, "GetTempPathA error %d\n", GetLastError()); 687 ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n"); 688 689 ret = GetTempFileNameA(temp_path, prefix, 0, filename); 690 ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError()); 691 692 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 693 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0); 694 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 695 696 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 697 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a file that wasn't created with FILE_FLAG_OVERLAPPED\n"); 698 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 699 700 ret = CloseHandle(hFile); 701 ok( ret, "CloseHandle: error %d\n", GetLastError()); 702 ret = DeleteFileA(filename); 703 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 704 705 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 706 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 707 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 708 709 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 710 ok(retb == TRUE, "BindIoCompletionCallback failed\n"); 711 712 memset(&overlapped, 0, sizeof(overlapped)); 713 retb = WriteFile(hFile, buffer, 4, &bytesWritten, &overlapped); 714 ok(retb == TRUE || GetLastError() == ERROR_IO_PENDING, "WriteFile failed, lastError = %d\n", GetLastError()); 715 716 ret = WaitForSingleObject(sem, 5000); 717 ok(ret == WAIT_OBJECT_0, "Wait for the IO completion callback failed\n"); 718 CloseHandle(sem); 719 720 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 0); 721 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the same callback on the file again\n"); 722 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 723 retb = p_BindIoCompletionCallback(hFile, NULL, 0); 724 ok(retb == FALSE, "BindIoCompletionCallback succeeded when setting the callback to NULL\n"); 725 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error is %d\n", GetLastError()); 726 727 ret = CloseHandle(hFile); 728 ok( ret, "CloseHandle: error %d\n", GetLastError()); 729 ret = DeleteFileA(filename); 730 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 731 732 /* win2k3 requires the Flags parameter to be zero */ 733 SetLastError(0xdeadbeef); 734 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, 735 CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED, 0); 736 ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %d\n", GetLastError()); 737 retb = p_BindIoCompletionCallback(hFile, iocp_callback, 12345); 738 if (!retb) 739 ok(GetLastError() == ERROR_INVALID_PARAMETER, 740 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); 741 else 742 ok(retb == TRUE, "BindIoCompletionCallback failed with Flags != 0\n"); 743 ret = CloseHandle(hFile); 744 ok( ret, "CloseHandle: error %d\n", GetLastError()); 745 ret = DeleteFileA(filename); 746 ok( ret, "DeleteFileA: error %d\n", GetLastError()); 747 748 retb = p_BindIoCompletionCallback(NULL, iocp_callback, 0); 749 ok(retb == FALSE, "BindIoCompletionCallback succeeded on a NULL file\n"); 750 ok(GetLastError() == ERROR_INVALID_HANDLE || 751 GetLastError() == ERROR_INVALID_PARAMETER, /* vista */ 752 "Last error is %d\n", GetLastError()); 753 } 754 755 static void CALLBACK timer_queue_cb1(PVOID p, BOOLEAN timedOut) 756 { 757 int *pn = p; 758 ok(timedOut, "Timer callbacks should always time out\n"); 759 ++*pn; 760 } 761 762 struct timer_queue_data1 763 { 764 int num_calls; 765 int max_calls; 766 HANDLE q, t; 767 }; 768 769 static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut) 770 { 771 struct timer_queue_data1 *d = p; 772 ok(timedOut, "Timer callbacks should always time out\n"); 773 if (d->t && ++d->num_calls == d->max_calls) 774 { 775 BOOL ret; 776 SetLastError(0xdeadbeef); 777 /* Note, XP SP2 does *not* do any deadlock checking, so passing 778 INVALID_HANDLE_VALUE here will just hang. */ 779 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL); 780 ok(!ret, "DeleteTimerQueueTimer\n"); 781 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 782 } 783 } 784 785 static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut) 786 { 787 struct timer_queue_data1 *d = p; 788 ok(timedOut, "Timer callbacks should always time out\n"); 789 if (d->t && ++d->num_calls == d->max_calls) 790 { 791 /* Basically kill the timer since it won't have time to run 792 again. */ 793 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0); 794 ok(ret, "ChangeTimerQueueTimer\n"); 795 } 796 } 797 798 static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut) 799 { 800 struct timer_queue_data1 *d = p; 801 ok(timedOut, "Timer callbacks should always time out\n"); 802 if (d->t) 803 { 804 /* This tests whether a timer gets flagged for deletion before 805 or after the callback runs. If we start this timer with a 806 period of zero (run once), then ChangeTimerQueueTimer will 807 fail if the timer is already flagged. Hence we really run 808 only once. Otherwise we will run multiple times. */ 809 BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50); 810 ok(ret, "ChangeTimerQueueTimer\n"); 811 ++d->num_calls; 812 } 813 } 814 815 static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut) 816 { 817 DWORD_PTR delay = (DWORD_PTR) p; 818 ok(timedOut, "Timer callbacks should always time out\n"); 819 if (delay) 820 Sleep(delay); 821 } 822 823 static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut) 824 { 825 struct timer_queue_data1 *d = p; 826 ok(timedOut, "Timer callbacks should always time out\n"); 827 /* This tests an original implementation bug where a deleted timer may get 828 to run, but it is tricky to set up. */ 829 if (d->q && d->num_calls++ == 0) 830 { 831 /* First run: delete ourselves, then insert and remove a timer 832 that goes in front of us in the sorted timeout list. Once 833 removed, we will still timeout at the faster timer's due time, 834 but this should be a no-op if we are bug-free. There should 835 not be a second run. We can test the value of num_calls later. */ 836 BOOL ret; 837 HANDLE t; 838 839 /* The delete will pend while we are in this callback. */ 840 SetLastError(0xdeadbeef); 841 ret = pDeleteTimerQueueTimer(d->q, d->t, NULL); 842 ok(!ret, "DeleteTimerQueueTimer\n"); 843 ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); 844 845 ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0); 846 ok(ret, "CreateTimerQueueTimer\n"); 847 ok(t != NULL, "CreateTimerQueueTimer\n"); 848 849 ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE); 850 ok(ret, "DeleteTimerQueueTimer\n"); 851 852 /* Now we stay alive by hanging around in the callback. */ 853 Sleep(500); 854 } 855 } 856 857 static void test_timer_queue(void) 858 { 859 HANDLE q, t0, t1, t2, t3, t4, t5; 860 int n0, n1, n2, n3, n4, n5; 861 struct timer_queue_data1 d1, d2, d3, d4; 862 HANDLE e, et1, et2; 863 BOOL ret, ret0; 864 865 if (!pChangeTimerQueueTimer || !pCreateTimerQueue || !pCreateTimerQueueTimer 866 || !pDeleteTimerQueueEx || !pDeleteTimerQueueTimer) 867 { 868 win_skip("TimerQueue API not present\n"); 869 return; 870 } 871 872 /* Test asynchronous deletion of the queue. */ 873 q = pCreateTimerQueue(); 874 ok(q != NULL, "CreateTimerQueue\n"); 875 876 SetLastError(0xdeadbeef); 877 ret = pDeleteTimerQueueEx(q, NULL); 878 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 879 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 880 GetLastError()); 881 882 /* Test synchronous deletion of the queue and running timers. */ 883 q = pCreateTimerQueue(); 884 ok(q != NULL, "CreateTimerQueue\n"); 885 886 /* Not called. */ 887 t0 = NULL; 888 n0 = 0; 889 ret = pCreateTimerQueueTimer(&t0, q, timer_queue_cb1, &n0, 0, 890 300, 0); 891 ok(ret, "CreateTimerQueueTimer\n"); 892 ok(t0 != NULL, "CreateTimerQueueTimer\n"); 893 ret0 = pDeleteTimerQueueTimer(q, t0, NULL); 894 ok((!ret0 && GetLastError() == ERROR_IO_PENDING) || 895 broken(ret0), /* Win 2000 & XP & 2003 */ 896 "DeleteTimerQueueTimer ret=%d le=%u\n", ret0, GetLastError()); 897 898 /* Called once. */ 899 t1 = NULL; 900 n1 = 0; 901 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 902 0, 0); 903 ok(ret, "CreateTimerQueueTimer\n"); 904 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 905 906 /* A slow one. */ 907 t2 = NULL; 908 n2 = 0; 909 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 910 100, 0); 911 ok(ret, "CreateTimerQueueTimer\n"); 912 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 913 914 /* A fast one. */ 915 t3 = NULL; 916 n3 = 0; 917 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 918 10, 0); 919 ok(ret, "CreateTimerQueueTimer\n"); 920 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 921 922 /* Start really late (it won't start). */ 923 t4 = NULL; 924 n4 = 0; 925 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 926 10, 0); 927 ok(ret, "CreateTimerQueueTimer\n"); 928 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 929 930 /* Start soon, but delay so long it won't run again. */ 931 t5 = NULL; 932 n5 = 0; 933 ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 934 10000, 0); 935 ok(ret, "CreateTimerQueueTimer\n"); 936 ok(t5 != NULL, "CreateTimerQueueTimer\n"); 937 938 /* Give them a chance to do some work. */ 939 Sleep(500); 940 941 /* Test deleting a once-only timer. */ 942 ret = pDeleteTimerQueueTimer(q, t1, INVALID_HANDLE_VALUE); 943 ok(ret, "DeleteTimerQueueTimer\n"); 944 945 /* A periodic timer. */ 946 ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); 947 ok(ret, "DeleteTimerQueueTimer\n"); 948 949 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 950 ok(ret, "DeleteTimerQueueEx\n"); 951 todo_wine 952 ok(n0 == 1 || broken(ret0 && n0 == 0), "Timer callback 0 expected 1 got %d\n", n0); 953 ok(n1 == 1, "Timer callback 1 expected 1 got %d\n", n1); 954 ok(n2 < n3, "Timer callback 2 & 3 expected %d < %d\n", n2, n3); 955 ok(n4 == 0, "Timer callback 4 expected 0 got %d\n", n4); 956 ok(n5 == 1, "Timer callback 5 expected 1 got %d\n", n5); 957 958 /* Test synchronous deletion of the timer/queue with event trigger. */ 959 e = CreateEventW(NULL, TRUE, FALSE, NULL); 960 et1 = CreateEventW(NULL, TRUE, FALSE, NULL); 961 et2 = CreateEventW(NULL, TRUE, FALSE, NULL); 962 if (!e || !et1 || !et2) 963 { 964 skip("Failed to create timer queue descruction event\n"); 965 return; 966 } 967 968 q = pCreateTimerQueue(); 969 ok(q != NULL, "CreateTimerQueue\n"); 970 971 /* Run once and finish quickly (should be done when we delete it). */ 972 t1 = NULL; 973 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb5, NULL, 0, 0, 0); 974 ok(ret, "CreateTimerQueueTimer\n"); 975 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 976 977 /* Run once and finish slowly (shouldn't be done when we delete it). */ 978 t2 = NULL; 979 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb5, (PVOID) 1000, 0, 980 0, 0); 981 ok(ret, "CreateTimerQueueTimer\n"); 982 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 983 984 /* Run once and finish quickly (should be done when we delete it). */ 985 t3 = NULL; 986 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb5, NULL, 0, 0, 0); 987 ok(ret, "CreateTimerQueueTimer\n"); 988 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 989 990 /* Run once and finish slowly (shouldn't be done when we delete it). */ 991 t4 = NULL; 992 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb5, (PVOID) 1000, 0, 993 0, 0); 994 ok(ret, "CreateTimerQueueTimer\n"); 995 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 996 997 /* Give them a chance to start. */ 998 Sleep(400); 999 1000 /* DeleteTimerQueueTimer always returns PENDING with a NULL event, 1001 even if the timer is finished. */ 1002 SetLastError(0xdeadbeef); 1003 ret = pDeleteTimerQueueTimer(q, t1, NULL); 1004 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1005 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1006 GetLastError()); 1007 1008 SetLastError(0xdeadbeef); 1009 ret = pDeleteTimerQueueTimer(q, t2, NULL); 1010 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1011 ok(GetLastError() == ERROR_IO_PENDING, 1012 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1013 GetLastError()); 1014 1015 SetLastError(0xdeadbeef); 1016 ret = pDeleteTimerQueueTimer(q, t3, et1); 1017 ok(ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1018 ok(GetLastError() == 0xdeadbeef, 1019 "DeleteTimerQueueTimer, GetLastError: expected 0xdeadbeef, got %d\n", 1020 GetLastError()); 1021 ok(WaitForSingleObject(et1, 250) == WAIT_OBJECT_0, 1022 "Timer destruction event not triggered\n"); 1023 1024 SetLastError(0xdeadbeef); 1025 ret = pDeleteTimerQueueTimer(q, t4, et2); 1026 ok(!ret, "DeleteTimerQueueTimer call was expected to fail\n"); 1027 ok(GetLastError() == ERROR_IO_PENDING, 1028 "DeleteTimerQueueTimer, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1029 GetLastError()); 1030 ok(WaitForSingleObject(et2, 1000) == WAIT_OBJECT_0, 1031 "Timer destruction event not triggered\n"); 1032 1033 SetLastError(0xdeadbeef); 1034 ret = pDeleteTimerQueueEx(q, e); 1035 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1036 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1037 GetLastError()); 1038 ok(WaitForSingleObject(e, 250) == WAIT_OBJECT_0, 1039 "Queue destruction event not triggered\n"); 1040 CloseHandle(e); 1041 1042 /* Test deleting/changing a timer in execution. */ 1043 q = pCreateTimerQueue(); 1044 ok(q != NULL, "CreateTimerQueue\n"); 1045 1046 /* Test changing a once-only timer before it fires (this is allowed, 1047 whereas after it fires you cannot). */ 1048 n1 = 0; 1049 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, 1050 0, 0); 1051 ok(ret, "CreateTimerQueueTimer\n"); 1052 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1053 ret = pChangeTimerQueueTimer(q, t1, 0, 0); 1054 ok(ret, "ChangeTimerQueueTimer\n"); 1055 1056 d2.t = t2 = NULL; 1057 d2.num_calls = 0; 1058 d2.max_calls = 3; 1059 d2.q = q; 1060 ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb2, &d2, 10, 1061 10, 0); 1062 d2.t = t2; 1063 ok(ret, "CreateTimerQueueTimer\n"); 1064 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1065 1066 d3.t = t3 = NULL; 1067 d3.num_calls = 0; 1068 d3.max_calls = 4; 1069 d3.q = q; 1070 ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb3, &d3, 10, 1071 10, 0); 1072 d3.t = t3; 1073 ok(ret, "CreateTimerQueueTimer\n"); 1074 ok(t3 != NULL, "CreateTimerQueueTimer\n"); 1075 1076 d4.t = t4 = NULL; 1077 d4.num_calls = 0; 1078 d4.q = q; 1079 ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb4, &d4, 10, 1080 0, 0); 1081 d4.t = t4; 1082 ok(ret, "CreateTimerQueueTimer\n"); 1083 ok(t4 != NULL, "CreateTimerQueueTimer\n"); 1084 1085 Sleep(500); 1086 1087 ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); 1088 ok(ret, "DeleteTimerQueueEx\n"); 1089 ok(n1 == 1, "ChangeTimerQueueTimer\n"); 1090 ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n"); 1091 ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); 1092 ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n"); 1093 1094 /* Test an obscure bug that was in the original implementation. */ 1095 q = pCreateTimerQueue(); 1096 ok(q != NULL, "CreateTimerQueue\n"); 1097 1098 /* All the work is done in the callback. */ 1099 d1.t = t1 = NULL; 1100 d1.num_calls = 0; 1101 d1.q = q; 1102 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, 1103 100, WT_EXECUTELONGFUNCTION); 1104 d1.t = t1; 1105 ok(ret, "CreateTimerQueueTimer\n"); 1106 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1107 1108 Sleep(750); 1109 1110 SetLastError(0xdeadbeef); 1111 ret = pDeleteTimerQueueEx(q, NULL); 1112 ok(ret /* vista */ || GetLastError() == ERROR_IO_PENDING, 1113 "DeleteTimerQueueEx, GetLastError: expected ERROR_IO_PENDING, got %d\n", 1114 GetLastError()); 1115 ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n"); 1116 1117 /* Test functions on the default timer queue. */ 1118 t1 = NULL; 1119 n1 = 0; 1120 ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, 1121 1000, 0); 1122 ok(ret, "CreateTimerQueueTimer, default queue\n"); 1123 ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n"); 1124 1125 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1126 ok(ret, "ChangeTimerQueueTimer, default queue\n"); 1127 1128 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1129 ok(ret, "DeleteTimerQueueTimer, default queue\n"); 1130 1131 /* Try mixing default and non-default queues. Apparently this works. */ 1132 q = pCreateTimerQueue(); 1133 ok(q != NULL, "CreateTimerQueue\n"); 1134 1135 t1 = NULL; 1136 n1 = 0; 1137 ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, 1138 1000, 0); 1139 ok(ret, "CreateTimerQueueTimer\n"); 1140 ok(t1 != NULL, "CreateTimerQueueTimer\n"); 1141 1142 t2 = NULL; 1143 n2 = 0; 1144 ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, 1145 1000, 0); 1146 ok(ret, "CreateTimerQueueTimer\n"); 1147 ok(t2 != NULL, "CreateTimerQueueTimer\n"); 1148 1149 ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000); 1150 ok(ret, "ChangeTimerQueueTimer\n"); 1151 1152 ret = pChangeTimerQueueTimer(q, t2, 2000, 2000); 1153 ok(ret, "ChangeTimerQueueTimer\n"); 1154 1155 ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); 1156 ok(ret, "DeleteTimerQueueTimer\n"); 1157 1158 ret = pDeleteTimerQueueTimer(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 = pDeleteTimerQueueEx(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 = pDeleteTimerQueueEx(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 2648 pChangeTimerQueueTimer = (void*)GetProcAddress(hdll, "ChangeTimerQueueTimer"); 2649 pCreateTimerQueue = (void*)GetProcAddress(hdll, "CreateTimerQueue"); 2650 pCreateTimerQueueTimer = (void*)GetProcAddress(hdll, "CreateTimerQueueTimer"); 2651 pCreateWaitableTimerA = (void*)GetProcAddress(hdll, "CreateWaitableTimerA"); 2652 pDeleteTimerQueueEx = (void*)GetProcAddress(hdll, "DeleteTimerQueueEx"); 2653 pDeleteTimerQueueTimer = (void*)GetProcAddress(hdll, "DeleteTimerQueueTimer"); 2654 pOpenWaitableTimerA = (void*)GetProcAddress(hdll, "OpenWaitableTimerA"); 2655 pCreateMemoryResourceNotification = (void *)GetProcAddress(hdll, "CreateMemoryResourceNotification"); 2656 pQueryMemoryResourceNotification = (void *)GetProcAddress(hdll, "QueryMemoryResourceNotification"); 2657 pInitOnceInitialize = (void *)GetProcAddress(hdll, "InitOnceInitialize"); 2658 pInitOnceExecuteOnce = (void *)GetProcAddress(hdll, "InitOnceExecuteOnce"); 2659 pInitOnceBeginInitialize = (void *)GetProcAddress(hdll, "InitOnceBeginInitialize"); 2660 pInitOnceComplete = (void *)GetProcAddress(hdll, "InitOnceComplete"); 2661 pInitializeConditionVariable = (void *)GetProcAddress(hdll, "InitializeConditionVariable"); 2662 pSleepConditionVariableCS = (void *)GetProcAddress(hdll, "SleepConditionVariableCS"); 2663 pSleepConditionVariableSRW = (void *)GetProcAddress(hdll, "SleepConditionVariableSRW"); 2664 pWakeAllConditionVariable = (void *)GetProcAddress(hdll, "WakeAllConditionVariable"); 2665 pWakeConditionVariable = (void *)GetProcAddress(hdll, "WakeConditionVariable"); 2666 pInitializeSRWLock = (void *)GetProcAddress(hdll, "InitializeSRWLock"); 2667 pAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "AcquireSRWLockExclusive"); 2668 pAcquireSRWLockShared = (void *)GetProcAddress(hdll, "AcquireSRWLockShared"); 2669 pReleaseSRWLockExclusive = (void *)GetProcAddress(hdll, "ReleaseSRWLockExclusive"); 2670 pReleaseSRWLockShared = (void *)GetProcAddress(hdll, "ReleaseSRWLockShared"); 2671 pTryAcquireSRWLockExclusive = (void *)GetProcAddress(hdll, "TryAcquireSRWLockExclusive"); 2672 pTryAcquireSRWLockShared = (void *)GetProcAddress(hdll, "TryAcquireSRWLockShared"); 2673 pNtAllocateVirtualMemory = (void *)GetProcAddress(hntdll, "NtAllocateVirtualMemory"); 2674 pNtFreeVirtualMemory = (void *)GetProcAddress(hntdll, "NtFreeVirtualMemory"); 2675 pNtWaitForSingleObject = (void *)GetProcAddress(hntdll, "NtWaitForSingleObject"); 2676 pNtWaitForMultipleObjects = (void *)GetProcAddress(hntdll, "NtWaitForMultipleObjects"); 2677 pRtlInterlockedPushListSList = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSList"); 2678 pRtlInterlockedPushListSListEx = (void *)GetProcAddress(hntdll, "RtlInterlockedPushListSListEx"); 2679 2680 argc = winetest_get_mainargs( &argv ); 2681 if (argc >= 3) 2682 { 2683 if (!strcmp(argv[2], "apc_deadlock")) 2684 { 2685 for (;;) SleepEx(INFINITE, TRUE); 2686 } 2687 return; 2688 } 2689 2690 init_fastcall_thunk(); 2691 test_signalandwait(); 2692 test_mutex(); 2693 test_slist(); 2694 test_event(); 2695 test_semaphore(); 2696 test_waitable_timer(); 2697 test_iocp_callback(); 2698 test_timer_queue(); 2699 test_WaitForSingleObject(); 2700 test_WaitForMultipleObjects(); 2701 test_initonce(); 2702 test_condvars_base(); 2703 test_condvars_consumer_producer(); 2704 test_srwlock_base(); 2705 test_srwlock_example(); 2706 test_alertable_wait(); 2707 test_apc_deadlock(); 2708 } 2709