diff --git a/src/libraries/System.Threading/tests/MutexTests.cs b/src/libraries/System.Threading/tests/MutexTests.cs index 6d769c4297fae5..9377f7f09e9796 100644 --- a/src/libraries/System.Threading/tests/MutexTests.cs +++ b/src/libraries/System.Threading/tests/MutexTests.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.DotNet.RemoteExecutor; +using Microsoft.Win32.SafeHandles; using Xunit; namespace System.Threading.Tests @@ -758,6 +759,30 @@ public void NamedMutex_DisposeWhenLockedRaceTest() } } + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void CheckWhichWindowsVersionsDistinguishLocalAndGlobalNamespaces() + { + const int MAXIMUM_ALLOWED = 0x02000000; + const int SYNCHRONIZE = 0x00100000; + const int MUTEX_MODIFY_STATE = 0x00000001; + const int MutexAccessRights = MAXIMUM_ALLOWED | SYNCHRONIZE | MUTEX_MODIFY_STATE; + + const int ERROR_ALREADY_EXISTS = 0xB7; + + string name = Guid.NewGuid().ToString("N"); + + using SafeWaitHandle m = CreateMutexEx(lpMutexAttributes: 0, @"Local\" + name, flags: 0, MutexAccessRights); + int errorCode = Marshal.GetLastPInvokeError(); + Assert.False(m.IsInvalid); + Assert.NotEqual(ERROR_ALREADY_EXISTS, errorCode); + + using SafeWaitHandle m2 = CreateMutexEx(lpMutexAttributes: 0, @"Global\" + name, flags: 0, MutexAccessRights); + errorCode = Marshal.GetLastPInvokeError(); + Assert.False(m2.IsInvalid); + Assert.NotEqual(ERROR_ALREADY_EXISTS, errorCode); + } + public static TheoryData GetValidNames() { var names = new TheoryData() { Guid.NewGuid().ToString("N") }; @@ -768,6 +793,9 @@ public static TheoryData GetValidNames() return names; } + [DllImport("kernel32.dll", EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern SafeWaitHandle CreateMutexEx(nint lpMutexAttributes, string? name, uint flags, uint desiredAccess); + [DllImport("kernel32.dll")] private static extern IntPtr GetCurrentThread();