mscorlib(4.0.0.0) API with additions
Mutex.cs
1 using Microsoft.Win32;
2 using Microsoft.Win32.SafeHandles;
3 using System.IO;
7 using System.Security;
10 
11 namespace System.Threading
12 {
14  [ComVisible(true)]
15  [__DynamicallyInvokable]
16  [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
17  public sealed class Mutex : WaitHandle
18  {
19  internal class MutexTryCodeHelper
20  {
21  private bool m_initiallyOwned;
22 
23  private MutexCleanupInfo m_cleanupInfo;
24 
25  internal bool m_newMutex;
26 
27  private string m_name;
28 
29  [SecurityCritical]
30  private Win32Native.SECURITY_ATTRIBUTES m_secAttrs;
31 
32  private Mutex m_mutex;
33 
34  [SecurityCritical]
35  [PrePrepareMethod]
36  internal MutexTryCodeHelper(bool initiallyOwned, MutexCleanupInfo cleanupInfo, string name, Win32Native.SECURITY_ATTRIBUTES secAttrs, Mutex mutex)
37  {
38  m_initiallyOwned = initiallyOwned;
39  m_cleanupInfo = cleanupInfo;
40  m_name = name;
41  m_secAttrs = secAttrs;
42  m_mutex = mutex;
43  }
44 
45  [SecurityCritical]
46  [PrePrepareMethod]
47  internal void MutexTryCode(object userData)
48  {
49  SafeWaitHandle mutexHandle = null;
51  try
52  {
53  }
54  finally
55  {
56  if (m_initiallyOwned)
57  {
58  m_cleanupInfo.inCriticalRegion = true;
61  }
62  }
63  int num = 0;
65  try
66  {
67  }
68  finally
69  {
70  num = CreateMutexHandle(m_initiallyOwned, m_name, m_secAttrs, out mutexHandle);
71  }
72  if (mutexHandle.IsInvalid)
73  {
74  mutexHandle.SetHandleAsInvalid();
75  if (m_name != null && m_name.Length != 0 && 6 == num)
76  {
77  throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", m_name));
78  }
79  __Error.WinIOError(num, m_name);
80  }
81  m_newMutex = (num != 183);
82  m_mutex.SetHandleInternal(mutexHandle);
83  m_mutex.hasThreadAffinity = true;
84  }
85  }
86 
87  internal class MutexCleanupInfo
88  {
89  [SecurityCritical]
90  internal SafeWaitHandle mutexHandle;
91 
92  internal bool inCriticalRegion;
93 
94  [SecurityCritical]
95  internal MutexCleanupInfo(SafeWaitHandle mutexHandle, bool inCriticalRegion)
96  {
97  this.mutexHandle = mutexHandle;
98  this.inCriticalRegion = inCriticalRegion;
99  }
100  }
101 
102  private static bool dummyBool;
103 
114  [SecurityCritical]
115  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
116  [__DynamicallyInvokable]
117  public Mutex(bool initiallyOwned, string name, out bool createdNew)
118  : this(initiallyOwned, name, out createdNew, (MutexSecurity)null)
119  {
120  }
121 
133  [SecurityCritical]
134  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
135  public unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity)
136  {
137  if (name != null && 260 < name.Length)
138  {
139  throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", name));
140  }
141  Win32Native.SECURITY_ATTRIBUTES sECURITY_ATTRIBUTES = null;
142  if (mutexSecurity != null)
143  {
144  sECURITY_ATTRIBUTES = new Win32Native.SECURITY_ATTRIBUTES();
145  sECURITY_ATTRIBUTES.nLength = Marshal.SizeOf(sECURITY_ATTRIBUTES);
146  byte[] securityDescriptorBinaryForm = mutexSecurity.GetSecurityDescriptorBinaryForm();
147  byte* ptr = stackalloc byte[(int)checked(unchecked((ulong)(uint)securityDescriptorBinaryForm.Length) * 1uL)];
148  Buffer.Memcpy(ptr, 0, securityDescriptorBinaryForm, 0, securityDescriptorBinaryForm.Length);
149  sECURITY_ATTRIBUTES.pSecurityDescriptor = ptr;
150  }
151  CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, sECURITY_ATTRIBUTES);
152  }
153 
154  [SecurityCritical]
155  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
156  internal Mutex(bool initiallyOwned, string name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs)
157  {
158  if (name != null && 260 < name.Length)
159  {
160  throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", name));
161  }
162  CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, secAttrs);
163  }
164 
165  [SecurityCritical]
166  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
167  internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, string name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs)
168  {
169  RuntimeHelpers.CleanupCode backoutCode = MutexCleanupCode;
170  MutexCleanupInfo mutexCleanupInfo = new MutexCleanupInfo(null, inCriticalRegion: false);
171  MutexTryCodeHelper mutexTryCodeHelper = new MutexTryCodeHelper(initiallyOwned, mutexCleanupInfo, name, secAttrs, this);
172  RuntimeHelpers.TryCode code = mutexTryCodeHelper.MutexTryCode;
173  RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(code, backoutCode, mutexCleanupInfo);
174  createdNew = mutexTryCodeHelper.m_newMutex;
175  }
176 
177  [SecurityCritical]
178  [PrePrepareMethod]
179  private void MutexCleanupCode(object userData, bool exceptionThrown)
180  {
181  MutexCleanupInfo mutexCleanupInfo = (MutexCleanupInfo)userData;
182  if (hasThreadAffinity)
183  {
184  return;
185  }
186  if (mutexCleanupInfo.mutexHandle != null && !mutexCleanupInfo.mutexHandle.IsInvalid)
187  {
188  if (mutexCleanupInfo.inCriticalRegion)
189  {
190  Win32Native.ReleaseMutex(mutexCleanupInfo.mutexHandle);
191  }
192  mutexCleanupInfo.mutexHandle.Dispose();
193  }
194  if (mutexCleanupInfo.inCriticalRegion)
195  {
196  Thread.EndCriticalRegion();
197  Thread.EndThreadAffinity();
198  }
199  }
200 
210  [SecurityCritical]
211  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
212  [__DynamicallyInvokable]
213  public Mutex(bool initiallyOwned, string name)
214  : this(initiallyOwned, name, out dummyBool)
215  {
216  }
217 
221  [SecuritySafeCritical]
222  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
223  [__DynamicallyInvokable]
224  public Mutex(bool initiallyOwned)
225  : this(initiallyOwned, null, out dummyBool)
226  {
227  }
228 
230  [SecuritySafeCritical]
231  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
232  [__DynamicallyInvokable]
233  public Mutex()
234  : this(initiallyOwned: false, null, out dummyBool)
235  {
236  }
237 
238  [SecurityCritical]
239  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
240  private Mutex(SafeWaitHandle handle)
241  {
242  SetHandleInternal(handle);
243  hasThreadAffinity = true;
244  }
245 
257  [SecurityCritical]
258  [__DynamicallyInvokable]
259  public static Mutex OpenExisting(string name)
260  {
261  return OpenExisting(name, MutexRights.Modify | MutexRights.Synchronize);
262  }
263 
276  [SecurityCritical]
277  public static Mutex OpenExisting(string name, MutexRights rights)
278  {
279  Mutex result;
280  switch (OpenExistingWorker(name, rights, out result))
281  {
282  case OpenExistingResult.NameNotFound:
284  case OpenExistingResult.NameInvalid:
285  throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
286  case OpenExistingResult.PathNotFound:
287  __Error.WinIOError(3, name);
288  return result;
289  default:
290  return result;
291  }
292  }
293 
306  [SecurityCritical]
307  [__DynamicallyInvokable]
308  public static bool TryOpenExisting(string name, out Mutex result)
309  {
310  return OpenExistingWorker(name, MutexRights.Modify | MutexRights.Synchronize, out result) == OpenExistingResult.Success;
311  }
312 
326  [SecurityCritical]
327  public static bool TryOpenExisting(string name, MutexRights rights, out Mutex result)
328  {
329  return OpenExistingWorker(name, rights, out result) == OpenExistingResult.Success;
330  }
331 
332  [SecurityCritical]
333  private static OpenExistingResult OpenExistingWorker(string name, MutexRights rights, out Mutex result)
334  {
335  if (name == null)
336  {
337  throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName"));
338  }
339  if (name.Length == 0)
340  {
341  throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
342  }
343  if (260 < name.Length)
344  {
345  throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", name));
346  }
347  result = null;
348  SafeWaitHandle safeWaitHandle = Win32Native.OpenMutex((int)rights, inheritHandle: false, name);
349  int num = 0;
350  if (safeWaitHandle.IsInvalid)
351  {
352  num = Marshal.GetLastWin32Error();
353  if (2 == num || 123 == num)
354  {
355  return OpenExistingResult.NameNotFound;
356  }
357  if (3 == num)
358  {
359  return OpenExistingResult.PathNotFound;
360  }
361  if (name != null && name.Length != 0 && 6 == num)
362  {
363  return OpenExistingResult.NameInvalid;
364  }
365  __Error.WinIOError(num, name);
366  }
367  result = new Mutex(safeWaitHandle);
368  return OpenExistingResult.Success;
369  }
370 
374  [SecuritySafeCritical]
375  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
376  [__DynamicallyInvokable]
377  public void ReleaseMutex()
378  {
379  if (Win32Native.ReleaseMutex(safeWaitHandle))
380  {
383  return;
384  }
385  throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException"));
386  }
387 
388  [SecurityCritical]
389  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
390  private static int CreateMutexHandle(bool initiallyOwned, string name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle)
391  {
392  bool flag = false;
393  int num;
394  while (true)
395  {
396  mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name);
397  num = Marshal.GetLastWin32Error();
398  if (!mutexHandle.IsInvalid || num != 5)
399  {
400  break;
401  }
403  try
404  {
405  try
406  {
407  }
408  finally
409  {
410  Thread.BeginThreadAffinity();
411  flag = true;
412  }
413  mutexHandle = Win32Native.OpenMutex(1048577, inheritHandle: false, name);
414  num = (mutexHandle.IsInvalid ? Marshal.GetLastWin32Error() : 183);
415  }
416  finally
417  {
418  if (flag)
419  {
420  Thread.EndThreadAffinity();
421  }
422  }
423  if (num != 2)
424  {
425  if (num == 0)
426  {
427  num = 183;
428  }
429  break;
430  }
431  }
432  return num;
433  }
434 
439  [SecuritySafeCritical]
441  {
442  return new MutexSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
443  }
444 
451  [SecuritySafeCritical]
452  public void SetAccessControl(MutexSecurity mutexSecurity)
453  {
454  if (mutexSecurity == null)
455  {
456  throw new ArgumentNullException("mutexSecurity");
457  }
458  mutexSecurity.Persist(safeWaitHandle);
459  }
460  }
461 }
delegate void TryCode(object userData)
Represents a delegate to code that should be run in a try block..
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
Encapsulates operating system–specific objects that wait for exclusive access to shared resources.
Definition: WaitHandle.cs:15
The exception that is thrown when an attempt is made to open a system mutex, semaphore,...
SafeWaitHandle SafeWaitHandle
Gets or sets the native operating system handle.
Definition: WaitHandle.cs:86
Mutex(bool initiallyOwned, string name, out bool createdNew)
Initializes a new instance of the T:System.Threading.Mutex class with a Boolean value that indicates ...
Definition: Mutex.cs:117
static void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object userData)
Executes code using a T:System.Delegate while using another T:System.Delegate to execute additional c...
static Mutex OpenExisting(string name)
Opens the specified named mutex, if it already exists.
Definition: Mutex.cs:259
void ReleaseMutex()
Releases the T:System.Threading.Mutex once.
Definition: Mutex.cs:377
Definition: __Canon.cs:3
static int SizeOf(object structure)
Returns the unmanaged size of an object in bytes.
Definition: Marshal.cs:159
Mutex(bool initiallyOwned, string name)
Initializes a new instance of the T:System.Threading.Mutex class with a Boolean value that indicates ...
Definition: Mutex.cs:213
void SetAccessControl(MutexSecurity mutexSecurity)
Sets the access control security for a named system mutex.
Definition: Mutex.cs:452
Serves as the base class for application-defined exceptions.
A synchronization primitive that can also be used for interprocess synchronization.
Definition: Mutex.cs:17
static bool TryOpenExisting(string name, out Mutex result)
Opens the specified named mutex, if it already exists, and returns a value that indicates whether the...
Definition: Mutex.cs:308
static bool TryOpenExisting(string name, MutexRights rights, out Mutex result)
Opens the specified named mutex, if it already exists, with the desired security access,...
Definition: Mutex.cs:327
Mutex(bool initiallyOwned)
Initializes a new instance of the T:System.Threading.Mutex class with a Boolean value that indicates ...
Definition: Mutex.cs:224
Cer
Specifies a method's behavior when called within a constrained execution region.
Definition: Cer.cs:5
SecurityAction
Specifies the security actions that can be performed using declarative security.
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
Mutex()
Initializes a new instance of the T:System.Threading.Mutex class with default properties.
Definition: Mutex.cs:233
static void BeginCriticalRegion()
Notifies a host that execution is about to enter a region of code in which the effects of a thread ab...
unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity)
Initializes a new instance of the T:System.Threading.Mutex class with a Boolean value that indicates ...
Definition: Mutex.cs:135
MutexSecurity GetAccessControl()
Gets a T:System.Security.AccessControl.MutexSecurity object that represents the access control securi...
Definition: Mutex.cs:440
static void PrepareConstrainedRegions()
Designates a body of code as a constrained execution region (CER).
Provides a collection of methods for allocating unmanaged memory, copying unmanaged memory blocks,...
Definition: Marshal.cs:15
Represents the Windows access control security for a named mutex. This class cannot be inherited.
Definition: MutexSecurity.cs:9
static void BeginThreadAffinity()
Notifies a host that managed code is about to execute instructions that depend on the identity of the...
static void EndCriticalRegion()
Notifies a host that execution is about to enter a region of code in which the effects of a thread ab...
MutexRights
Specifies the access control rights that can be applied to named system mutex objects.
Definition: MutexRights.cs:5
The exception that is thrown when one of the arguments provided to a method is not valid.
delegate void CleanupCode(object userData, bool exceptionThrown)
Represents a method to run when an exception occurs.
static void EndThreadAffinity()
Notifies a host that managed code has finished executing instructions that depend on the identity of ...
Manipulates arrays of primitive types.
Definition: Buffer.cs:11
Consistency
Specifies a reliability contract.
Definition: Consistency.cs:5
static Mutex OpenExisting(string name, MutexRights rights)
Opens the specified named mutex, if it already exists, with the desired security access.
Definition: Mutex.cs:277
static int GetLastWin32Error()
Returns the error code returned by the last unmanaged function that was called using platform invoke ...
AccessControlSections
Specifies which sections of a security descriptor to save or load.
Provides a set of static methods and properties that provide support for compilers....
Creates and controls a thread, sets its priority, and gets its status.
Definition: Thread.cs:18