diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index e2a6c7ef269..dd87f3e32ff 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -128,20 +128,51 @@ static void test_mutex(void) BOOL ret; HANDLE hCreated; HANDLE hOpened; + int i; + DWORD failed = 0; hCreated = CreateMutex(NULL, FALSE, "WineTestMutex"); ok(hCreated != NULL, "CreateMutex failed with error %d\n", GetLastError()); - wait_ret = WaitForSingleObject(hCreated, INFINITE); - ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret); - /* yes, opening with just READ_CONTROL access allows us to successfully - * call ReleaseMutex */ - hOpened = OpenMutex(READ_CONTROL, FALSE, "WineTestMutex"); + hOpened = OpenMutex(0, FALSE, "WineTestMutex"); + ok(hOpened == NULL, "OpenMutex succeded\n"); + + hOpened = OpenMutex(GENERIC_EXECUTE, FALSE, "WineTestMutex"); ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); - ret = ReleaseMutex(hOpened); - todo_wine ok(ret, "ReleaseMutex failed with error %d\n", GetLastError()); + wait_ret = WaitForSingleObject(hOpened, INFINITE); + todo_wine ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error %d\n", GetLastError()); + CloseHandle(hOpened); + + for(i=0; i < 31; i++) + { + wait_ret = WaitForSingleObject(hCreated, INFINITE); + ok(wait_ret == WAIT_OBJECT_0, "WaitForSingleObject failed with error 0x%08x\n", wait_ret); + } + + hOpened = OpenMutex(GENERIC_READ | GENERIC_WRITE, FALSE, "WineTestMutex"); + ok(hOpened != NULL, "OpenMutex failed with error %d\n", GetLastError()); + wait_ret = WaitForSingleObject(hOpened, INFINITE); + todo_wine ok(wait_ret == WAIT_FAILED, "WaitForSingleObject succeeded\n"); + CloseHandle(hOpened); + + for (i = 0; i < 32; i++) + { + hOpened = OpenMutex(0x1 << i, FALSE, "WineTestMutex"); + ReleaseMutex(hCreated); + if(hOpened != NULL) + { + CloseHandle(hOpened); + } + else + { + failed |=0x1 << i; + } + } + + ok( failed == 0x0de0fffe, "open succeded when it shouldn't: %x\n", failed); + ret = ReleaseMutex(hCreated); - todo_wine ok(!ret && (GetLastError() == ERROR_NOT_OWNER), + ok(!ret && (GetLastError() == ERROR_NOT_OWNER), "ReleaseMutex should have failed with ERROR_NOT_OWNER instead of %d\n", GetLastError()); /* test case sensitivity */ diff --git a/server/mutex.c b/server/mutex.c index 31a529aa3fa..faedcf39d4d 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -238,6 +238,14 @@ DECL_HANDLER(open_mutex) struct directory *root = NULL; struct mutex *mutex; + if ((req->access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL | + MUTEX_ALL_ACCESS | STANDARD_RIGHTS_ALL | MAXIMUM_ALLOWED)) || + !req->access) + { + set_error(STATUS_INVALID_PARAMETER); + return; + } + get_req_unicode_str( &name ); if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) return;