Merge pull request #3144 from Unity-Technologies/fix-recursive-property-call
[mono.git] / mcs / class / referencesource / System.Web / Util / StopListeningWaitHandle.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="StopListeningWaitHandle.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 namespace System.Web.Util {
8     using Microsoft.Win32.SafeHandles;
9     using System;
10     using System.Diagnostics.CodeAnalysis;
11     using System.Runtime.ConstrainedExecution;
12     using System.Runtime.InteropServices;
13     using System.Security;
14     using System.Threading;
15     using System.Web.Hosting;
16
17     // This is a ManualResetEvent that corresponds to the OnGlobalStopListening event.
18     internal sealed class StopListeningWaitHandle : WaitHandle {
19         [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Justification = @"This is a pseudohandle so shouldn't be closed.")]
20         private static IntPtr _processHandle = GetCurrentProcess();
21
22         public StopListeningWaitHandle() {
23             // This handle is process-wide and not ref counted, so no need to wrap inside a SafeHandle
24             IntPtr eventHandle = UnsafeIISMethods.MgdGetStopListeningEventHandle();
25
26             // Per documentation for RegisterWaitForSingleObject, we need to duplicate handles
27             // before asynchronously waiting on them.
28             SafeWaitHandle safeWaitHandle;
29             bool succeeded = DuplicateHandle(
30                 hSourceProcessHandle: _processHandle,
31                 hSourceHandle: eventHandle,
32                 hTargetProcessHandle: _processHandle,
33                 lpTargetHandle: out safeWaitHandle,
34                 dwDesiredAccess: 0,
35                 bInheritHandle: false,
36                 dwOptions: 2 /* DUPLICATE_SAME_ACCESS */);
37
38             if (!succeeded) {
39                 int hr = Marshal.GetHRForLastWin32Error();
40                 Marshal.ThrowExceptionForHR(hr);
41             }
42
43             this.SafeWaitHandle = safeWaitHandle;
44         }
45
46         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
47         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
48         [SuppressUnmanagedCodeSecurity]
49         [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "We carefully control this method's callers.")]
50         private static extern IntPtr GetCurrentProcess();
51
52         [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
53         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
54         [SuppressUnmanagedCodeSecurity]
55         [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "We carefully control this method's callers.")]
56         private static extern bool DuplicateHandle([In] IntPtr hSourceProcessHandle, [In] IntPtr hSourceHandle, [In] IntPtr hTargetProcessHandle, [Out] out SafeWaitHandle lpTargetHandle, [In] uint dwDesiredAccess, [In] bool bInheritHandle, [In] uint dwOptions);
57     }
58 }