From: Marc-Aurel Zent mzent@codeweavers.com
--- dlls/kernel32/tests/sync.c | 167 +++++++++++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 34 deletions(-)
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index f2fc0196626..8787d720010 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -1291,6 +1291,22 @@ static void test_WaitForSingleObject(void) LARGE_INTEGER timeout; NTSTATUS status; DWORD ret; + int i; + HANDLE waitable_pseudohandles[] = { + NtCurrentProcess(), + NtCurrentThread() + }; + HANDLE non_waitable_pseudohandles[] = { + NtCurrentSession(), + NtCurrentProcessToken(), + NtCurrentThreadToken(), + NtCurrentEffectiveToken() + }; + HANDLE std_handles[] = { + (HANDLE)STD_INPUT_HANDLE, + (HANDLE)STD_OUTPUT_HANDLE, + (HANDLE)STD_ERROR_HANDLE + };
signaled = CreateEventW(NULL, TRUE, TRUE, NULL); nonsignaled = CreateEventW(NULL, TRUE, FALSE, NULL); @@ -1359,20 +1375,43 @@ static void test_WaitForSingleObject(void) ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %ld\n", ret); ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %ld\n", GetLastError());
- /* pseudo handles are allowed in WaitForSingleObject and NtWaitForSingleObject */ - ret = WaitForSingleObject(GetCurrentProcess(), 100); - ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret); + /* waitable pseudo-handles are allowed in WaitForSingleObject and NtWaitForSingleObject, + * but not in NtWaitForMultipleObjects, see test_WaitForMultipleObjects */ + for (i = 0; i < ARRAY_SIZE(waitable_pseudohandles); i++) + { + ret = WaitForSingleObject(waitable_pseudohandles[i], 100); + ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret);
- ret = WaitForSingleObject(GetCurrentThread(), 100); - ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %lu\n", ret); + timeout.QuadPart = -1000000; + status = pNtWaitForSingleObject(waitable_pseudohandles[i], FALSE, &timeout); + ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status); + }
- timeout.QuadPart = -1000000; - status = pNtWaitForSingleObject(GetCurrentProcess(), FALSE, &timeout); - ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status); + /* non-waitable pseudo-handles return STATUS_INVALID_HANDLE */ + for (i = 0; i < ARRAY_SIZE(non_waitable_pseudohandles); i++) + { + SetLastError(0xdeadbeef); + ret = WaitForSingleObject(non_waitable_pseudohandles[i], 100); + ok(ret == WAIT_FAILED, "expected WAIT_FAILED, got %ld\n", ret); + ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError()); + + timeout.QuadPart = -1000000; + status = pNtWaitForSingleObject(non_waitable_pseudohandles[i], FALSE, &timeout); + todo_wine_if(non_waitable_pseudohandles[i] == NtCurrentProcessToken() || + non_waitable_pseudohandles[i] == NtCurrentEffectiveToken()) + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + }
- timeout.QuadPart = -1000000; - status = pNtWaitForSingleObject(GetCurrentThread(), FALSE, &timeout); - ok(status == STATUS_TIMEOUT, "expected STATUS_TIMEOUT, got %08lx\n", status); + /* std handles are only allowed in WaitForSingleObject and not NtWaitForSingleObject */ + for (i = 0; i < ARRAY_SIZE(std_handles); i++) + { + ret = WaitForSingleObject(std_handles[i], 100); + ok(ret != WAIT_FAILED, "expected non-fail result, got %lu (GetLastError()=%lu)\n", ret, GetLastError()); + + timeout.QuadPart = -1000000; + status = pNtWaitForSingleObject(std_handles[i], FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + }
CloseHandle(signaled); CloseHandle(nonsignaled); @@ -1385,6 +1424,19 @@ static void test_WaitForMultipleObjects(void) DWORD r; int i; HANDLE maxevents[MAXIMUM_WAIT_OBJECTS]; + HANDLE pseudohandles[] = { + NtCurrentProcess(), + NtCurrentThread(), + NtCurrentSession(), + NtCurrentProcessToken(), + NtCurrentThreadToken(), + NtCurrentEffectiveToken() + }; + HANDLE std_handles[] = { + (HANDLE)STD_INPUT_HANDLE, + (HANDLE)STD_OUTPUT_HANDLE, + (HANDLE)STD_ERROR_HANDLE + };
/* create the maximum number of events and make sure * we can wait on that many */ @@ -1424,34 +1476,81 @@ static void test_WaitForMultipleObjects(void) ok(status == STATUS_WAIT_0 + i, "should signal handle #%d first, got %08lx\n", i, status); }
- for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++) - if (maxevents[i]) CloseHandle(maxevents[i]); + CloseHandle(maxevents[0]);
- /* in contrast to WaitForSingleObject, pseudo handles are not allowed in + /* in contrast to WaitForSingleObject, all pseudo-handles are not allowed in * WaitForMultipleObjects and NtWaitForMultipleObjects */ - maxevents[0] = GetCurrentProcess(); - SetLastError(0xdeadbeef); - r = WaitForMultipleObjects(1, maxevents, FALSE, 100); - ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); - ok(GetLastError() == ERROR_INVALID_HANDLE, - "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + for (i = 0; i < ARRAY_SIZE(pseudohandles); i++) + { + maxevents[0] = pseudohandles[i]; + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(1, maxevents, FALSE, 100); + ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError());
- maxevents[0] = GetCurrentThread(); - SetLastError(0xdeadbeef); - r = WaitForMultipleObjects(1, maxevents, FALSE, 100); - ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); - ok(GetLastError() == ERROR_INVALID_HANDLE, - "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status);
- timeout.QuadPart = -1000000; - maxevents[0] = GetCurrentProcess(); - status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); - ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + /* also not allowed with a wait count greater than 1 with both WaitAny and WaitAll */ + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 100); + ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, 100); + ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAny, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAll, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + + /* irrespective of the index that contains the pseudo handle for both wait types */ + maxevents[0] = maxevents[MAXIMUM_WAIT_OBJECTS - 1]; + maxevents[MAXIMUM_WAIT_OBJECTS - 1] = pseudohandles[i]; + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, FALSE, 100); + ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, TRUE, 100); + ok(r == WAIT_FAILED, "expected WAIT_FAILED, got %lu\n", r); + ok(GetLastError() == ERROR_INVALID_HANDLE, + "expected ERROR_INVALID_HANDLE, got %lu\n", GetLastError()); + + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAny, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, WaitAll, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + maxevents[MAXIMUM_WAIT_OBJECTS - 1] = maxevents[0]; + } + + /* Similar to WaitForSingleObject std handles are only allowed in WaitForMultipleObjects and + * not NtWaitForMultipleObjects (for brevity we only test single count WaitAny here) */ + for (i = 0; i < ARRAY_SIZE(std_handles); i++) + { + maxevents[0] = std_handles[i]; + SetLastError(0xdeadbeef); + r = WaitForMultipleObjects(1, maxevents, FALSE, 100); + ok(r != WAIT_FAILED, "expected non-fail result, got %lu (GetLastError()=%lu)\n", r, GetLastError());
- timeout.QuadPart = -1000000; - maxevents[0] = GetCurrentThread(); - status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); - ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + timeout.QuadPart = -1000000; + status = pNtWaitForMultipleObjects(1, maxevents, WaitAny, FALSE, &timeout); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %08lx\n", status); + } + + for (i=1; i<MAXIMUM_WAIT_OBJECTS; i++) + if (maxevents[i]) CloseHandle(maxevents[i]); }
static BOOL g_initcallback_ret, g_initcallback_called;