diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index e2a6c7ef26925f69ae16eadb675887d77ea39d70..dd87f3e32ff6e22b328c6b6fa2a05cfb4ad1e994 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());
+    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());
-    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_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 31a529aa3fa7f1dce567cbfc427048fc5c9c801d..faedcf39d4dbb3721f8703a1df1e8ae53243aafa 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;