PipeConnection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / PipeConnection.cs / 2 / PipeConnection.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.ServiceModel; 
    using System.Globalization;
    using System.Text; 
    using System.Threading;
    using System.Runtime.InteropServices;
    using System.Runtime.CompilerServices;
    using Microsoft.Win32.SafeHandles; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Security; 
    using System.Security.Cryptography; 
    using System.Security.AccessControl;
    using System.Security.Principal; 
    using System.Diagnostics;
    using System.ComponentModel;
    using System.IO;
    using System.ServiceModel.Activation; 
    using System.Net;
 
    using SafeCloseHandle = System.IdentityModel.SafeCloseHandle; 

    sealed class PipeConnection : IConnection 
    {
        // common state
        PipeHandle pipe;
        CloseState closeState; 
        bool aborted;
        bool isBoundToCompletionPort; 
        bool autoBindToCompletionPort; 
        TraceEventType exceptionEventType;
        static byte[] zeroBuffer; 

        // read state
        object readLock = new object();
        bool inReadingState;     // This keeps track of the state machine (IConnection interface). 
        bool isReadOutstanding;  // This tracks whether an actual I/O is pending.
        OverlappedContext readOverlapped; 
        byte[] asyncReadBuffer; 
        int readBufferSize;
        ManualResetEvent atEOFEvent; 
        bool isAtEOF;
        OverlappedIOCompleteCallback onAsyncReadComplete;
        Exception asyncReadException;
        WaitCallback asyncReadCallback; 
        object asyncReadCallbackState;
        int asyncBytesRead; 
 
        // write state
        object writeLock = new object(); 
        bool inWritingState;      // This keeps track of the state machine (IConnection interface).
        bool isWriteOutstanding;  // This tracks whether an actual I/O is pending.
        WriteAsyncResult writeAsyncResult;
        OverlappedContext writeOverlapped; 
        bool isShutdownWritten;
        int syncWriteSize; 
        byte[] pendingWriteBuffer; 
        BufferManager pendingWriteBufferManager;
        OverlappedIOCompleteCallback onAsyncWriteComplete; 
        int writeBufferSize;

        // timeout support
        TimeSpan readTimeout; 
        IOThreadTimer readTimer;
        static WaitCallback onReadTimeout; 
        string timeoutErrorString; 
        TransferOperation timeoutErrorTransferOperation;
        TimeSpan writeTimeout; 
        IOThreadTimer writeTimer;
        static WaitCallback onWriteTimeout;

        public PipeConnection(PipeHandle pipe, int connectionBufferSize, bool isBoundToCompletionPort, bool autoBindToCompletionPort) 
        {
            if (pipe == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("pipe"); 
            if (pipe.IsInvalid)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("pipe"); 

            this.closeState = CloseState.Open;
            this.exceptionEventType = TraceEventType.Error;
            this.isBoundToCompletionPort = isBoundToCompletionPort; 
            this.autoBindToCompletionPort = autoBindToCompletionPort;
            this.pipe = pipe; 
            this.readBufferSize = connectionBufferSize; 
            this.writeBufferSize = connectionBufferSize;
            this.readOverlapped = new OverlappedContext(); 
            this.writeOverlapped = new OverlappedContext();
            this.atEOFEvent = new ManualResetEvent(false);
            this.onAsyncReadComplete = new OverlappedIOCompleteCallback(OnAsyncReadComplete);
            this.onAsyncWriteComplete = new OverlappedIOCompleteCallback(OnAsyncWriteComplete); 
        }
 
        public int AsyncReadBufferSize 
        {
            get 
            {
                return this.readBufferSize;
            }
        } 

        public byte[] AsyncReadBuffer 
        { 
            get
            { 
                if (this.asyncReadBuffer == null)
                {
                    Interlocked.CompareExchange(ref this.asyncReadBuffer,
                        DiagnosticUtility.Utility.AllocateByteArray(AsyncReadBufferSize), null); 
                }
                return this.asyncReadBuffer; 
            } 
        }
 
        static byte[] ZeroBuffer
        {
            get
            { 
                if (PipeConnection.zeroBuffer == null)
                { 
                    PipeConnection.zeroBuffer = new byte[1]; 
                }
                return PipeConnection.zeroBuffer; 
            }
        }

        public TraceEventType ExceptionEventType 
        {
            get { return this.exceptionEventType; } 
            set { this.exceptionEventType = value; } 
        }
 
        public IPEndPoint RemoteIPEndPoint
        {
            get { return null; }
        } 

        IOThreadTimer ReadTimer 
        { 
            get
            { 
                if (this.readTimer == null)
                {
                    if (onReadTimeout == null)
                    { 
                        onReadTimeout = new WaitCallback(OnReadTimeout);
                    } 
 
                    this.readTimer = new IOThreadTimer(onReadTimeout, this, false);
                } 

                return this.readTimer;
            }
        } 
        IOThreadTimer WriteTimer
        { 
            get 
            {
                if (this.writeTimer == null) 
                {
                    if (onWriteTimeout == null)
                    {
                        onWriteTimeout = new WaitCallback(OnWriteTimeout); 
                    }
 
                    this.writeTimer = new IOThreadTimer(onWriteTimeout, this, false); 
                }
 
                return this.writeTimer;
            }
        }
 
        static void OnReadTimeout(object state)
        { 
            PipeConnection thisPtr = (PipeConnection)state; 
            thisPtr.Abort(SR.GetString(SR.PipeConnectionAbortedReadTimedOut, thisPtr.readTimeout), TransferOperation.Read);
        } 

        static void OnWriteTimeout(object state)
        {
            PipeConnection thisPtr = (PipeConnection)state; 
            thisPtr.Abort(SR.GetString(SR.PipeConnectionAbortedWriteTimedOut, thisPtr.writeTimeout), TransferOperation.Write);
        } 
 
        public void Abort()
        { 
            Abort(null, TransferOperation.Undefined);
        }

        void Abort(string timeoutErrorString, TransferOperation transferOperation) 
        {
            CloseHandle(true, timeoutErrorString, transferOperation); 
        } 

        Exception ConvertPipeException(PipeException pipeException, TransferOperation transferOperation) 
        {
            return ConvertPipeException(pipeException.Message, pipeException, transferOperation);
        }
 
        Exception ConvertPipeException(string exceptionMessage, PipeException pipeException, TransferOperation transferOperation)
        { 
            if (this.timeoutErrorString != null) 
            {
                if (transferOperation == this.timeoutErrorTransferOperation) 
                {
                    return new TimeoutException(this.timeoutErrorString, pipeException);
                }
                else 
                {
                    return new CommunicationException(this.timeoutErrorString, pipeException); 
                } 
            }
            else if (this.aborted) 
            {
                return new CommunicationObjectAbortedException(exceptionMessage, pipeException);
            }
            else 
            {
                return new CommunicationException(exceptionMessage, pipeException); 
            } 
        }
 
        public unsafe AsyncReadResult BeginRead(int offset, int size, TimeSpan timeout,
            WaitCallback callback, object state)
        {
            ConnectionUtilities.ValidateBufferBounds(AsyncReadBuffer, offset, size); 

            lock (readLock) 
            { 
                try
                { 
                    ValidateEnterReadingState(true);

                    if (isAtEOF)
                    { 
                        asyncBytesRead = 0;
                        asyncReadException = null; 
                        return AsyncReadResult.Completed; 
                    }
 
                    if (autoBindToCompletionPort)
                    {
                        if (!isBoundToCompletionPort)
                        { 
                            lock (writeLock)
                            { 
                                // readLock, writeLock acquired in order to prevent deadlock 
                                EnsureBoundToCompletionPort();
                            } 
                        }
                    }

                    if (this.isReadOutstanding) 
                    {
                        DiagnosticUtility.DebugAssert("Read I/O already pending when BeginRead called."); 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                    }
                    try 
                    {
                        this.readTimeout = timeout;

                        if (this.readTimeout != TimeSpan.MaxValue) 
                        {
                            this.ReadTimer.Set(this.readTimeout); 
                        } 

                        this.asyncReadCallback = callback; 
                        this.asyncReadCallbackState = state;

                        this.isReadOutstanding = true;
                        this.readOverlapped.StartAsyncOperation(AsyncReadBuffer, this.onAsyncReadComplete, this.isBoundToCompletionPort); 
                        if (UnsafeNativeMethods.ReadFile(this.pipe.DangerousGetHandle(), this.readOverlapped.BufferPtr + offset, size, IntPtr.Zero, this.readOverlapped.NativeOverlapped) == 0)
                        { 
                            int error = Marshal.GetLastWin32Error(); 
                            if (error != UnsafeNativeMethods.ERROR_IO_PENDING && error != UnsafeNativeMethods.ERROR_MORE_DATA)
                            { 
                                this.isReadOutstanding = false;
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateReadException(error));
                            }
                        } 
                    }
                    finally 
                    { 
                        if (!this.isReadOutstanding)
                        { 
                            // Unbind the buffer.
                            this.readOverlapped.CancelAsyncOperation();

                            this.asyncReadCallback = null; 
                            this.asyncReadCallbackState = null;
                            this.ReadTimer.Cancel(); 
                        } 
                    }
 
                    if (!this.isReadOutstanding)
                    {
                        int bytesRead;
                        Exception readException = Exceptions.GetOverlappedReadException(this.pipe, this.readOverlapped.NativeOverlapped, out bytesRead); 
                        if (readException != null)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(readException); 
                        }
                        asyncBytesRead = bytesRead; 
                        HandleReadComplete(asyncBytesRead);
                    }
                    else
                    { 
                        EnterReadingState();
                    } 
 
                    return this.isReadOutstanding ? AsyncReadResult.Queued : AsyncReadResult.Completed;
                } 
                catch (PipeException e)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Read), ExceptionEventType);
                } 
            }
        } 
 
        public unsafe IAsyncResult BeginWrite(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout,
            AsyncCallback callback, object state) 
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            FinishPendingWrite(timeout);
 
            ConnectionUtilities.ValidateBufferBounds(buffer, offset, size);
 
            if (autoBindToCompletionPort && !isBoundToCompletionPort) 
            {
                // Locks must be both taken, and in this order. 
                lock (readLock)
                {
                    lock (writeLock)
                    { 
                        ValidateEnterWritingState(true);
 
                        EnsureBoundToCompletionPort(); 
                    }
                } 
            }

            lock (writeLock)
            { 
                try
                { 
                    ValidateEnterWritingState(true); 

                    if (this.isWriteOutstanding) 
                    {
                        DiagnosticUtility.DebugAssert("Write I/O already pending when BeginWrite called.");
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                    } 
                    WriteAsyncResult result = new WriteAsyncResult(callback, state, size);
                    try 
                    { 
                        this.writeTimeout = timeout;
                        this.WriteTimer.Set(timeoutHelper.RemainingTime()); 
                        this.writeAsyncResult = result;

                        this.isWriteOutstanding = true;
                        this.writeOverlapped.StartAsyncOperation(buffer, this.onAsyncWriteComplete, this.isBoundToCompletionPort); 
                        if (UnsafeNativeMethods.WriteFile(this.pipe.DangerousGetHandle(), this.writeOverlapped.BufferPtr + offset, size, IntPtr.Zero, this.writeOverlapped.NativeOverlapped) == 0)
                        { 
                            int error = Marshal.GetLastWin32Error(); 
                            if (error != UnsafeNativeMethods.ERROR_IO_PENDING)
                            { 
                                this.isWriteOutstanding = false;
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateWriteException(error));
                            }
                        } 
                    }
                    finally 
                    { 
                        if (!this.isWriteOutstanding)
                        { 
                            // Unbind the buffer.
                            this.writeOverlapped.CancelAsyncOperation();

                            this.writeAsyncResult = null; 
                            this.WriteTimer.Cancel();
                        } 
                    } 

                    if (!this.isWriteOutstanding) 
                    {
                        int bytesWritten;
                        Exception writeException = Exceptions.GetOverlappedWriteException(this.pipe, this.writeOverlapped.NativeOverlapped, out bytesWritten);
                        if (writeException == null && bytesWritten != size) 
                        {
                            writeException = new PipeException(SR.GetString(SR.PipeWriteIncomplete)); 
                        } 
                        if (writeException != null)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(writeException);
                        }

                        result.Complete(true); 
                    }
                    else 
                    { 
                        EnterWritingState();
                    } 

                    return result;
                }
                catch (PipeException e) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Write), ExceptionEventType); 
                } 
            }
        } 

        public void Close(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            FinishPendingWrite(timeout);
 
            bool shouldCloseHandle = false; 
            try
            { 
                bool existingReadIsPending = false;
                bool shouldReadEOF = false;
                bool shouldWriteEOF = false;
 
                lock (readLock)
                { 
                    lock (writeLock) 
                    {
                        if (!isShutdownWritten && inWritingState) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                                new PipeException(SR.GetString(SR.PipeCantCloseWithPendingWrite)), ExceptionEventType);
                        } 

                        if (closeState == CloseState.Closing || closeState == CloseState.HandleClosed) 
                        { 
                            // already closing or closed, so just return
                            return; 
                        }

                        closeState = CloseState.Closing;
 
                        shouldCloseHandle = true;
 
                        if (!isAtEOF) 
                        {
                            if (inReadingState) 
                            {
                                existingReadIsPending = true;
                            }
                            else 
                            {
                                shouldReadEOF = true; 
                            } 
                        }
 
                        if (!isShutdownWritten)
                        {
                            shouldWriteEOF = true;
                            isShutdownWritten = true; 
                        }
                    } 
                } 

                if (shouldWriteEOF) 
                {
                    StartWriteZero(timeoutHelper.RemainingTime());
                }
 
                if (shouldReadEOF)
                { 
                    StartReadZero(); 
                }
 
                // wait for shutdown write to complete
                try
                {
                    WaitForWriteZero(timeoutHelper.RemainingTime(), true); 
                }
                catch (TimeoutException e) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                        new TimeoutException(SR.GetString(SR.PipeShutdownWriteError), e), ExceptionEventType); 
                }

                // ensure we have received EOF signal
                if (shouldReadEOF) 
                {
                    try 
                    { 
                        WaitForReadZero(timeoutHelper.RemainingTime(), true);
                    } 
                    catch (TimeoutException e)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                            new TimeoutException(SR.GetString(SR.PipeShutdownReadError), e), ExceptionEventType); 
                    }
                } 
                else if (existingReadIsPending) 
                {
                    if (!TimeoutHelper.WaitOne(atEOFEvent, timeoutHelper.RemainingTime(), false)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                            new TimeoutException(SR.GetString(SR.PipeShutdownReadError)), ExceptionEventType);
                    } 
                }
                // else we had already seen EOF. 
 
                // at this point, we may get exceptions if the other side closes the handle first
                try 
                {
                    // write an ack for eof
                    StartWriteZero(timeoutHelper.RemainingTime());
 
                    // read an ack for eof
                    StartReadZero(); 
 
                    // wait for write to complete/fail
                    WaitForWriteZero(timeoutHelper.RemainingTime(), false); 

                    // wait for read to complete/fail
                    WaitForReadZero(timeoutHelper.RemainingTime(), false);
                } 
                catch (PipeException e)
                { 
                    if (!IsBrokenPipeError(e.ErrorCode)) 
                    {
                        throw; 
                    }
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    }
                } 
                catch (CommunicationException e) 
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    }
                } 
                catch (TimeoutException e)
                { 
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    }
                }
            }
            catch (TimeoutException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper( 
                    new TimeoutException(SR.GetString(SR.PipeCloseFailed), e), ExceptionEventType); 
            }
            catch (PipeException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                    ConvertPipeException(SR.GetString(SR.PipeCloseFailed), e, TransferOperation.Undefined), ExceptionEventType);
            } 
            finally
            { 
                if (shouldCloseHandle) 
                {
                    CloseHandle(false, null, TransferOperation.Undefined); 
                }
            }
        }
 
        void CloseHandle(bool abort, string timeoutErrorString, TransferOperation transferOperation)
        { 
            lock (readLock) 
            {
                lock (writeLock) 
                {
                    if (this.closeState == CloseState.HandleClosed)
                    {
                        return; 
                    }
 
                    this.timeoutErrorString = timeoutErrorString; 
                    this.timeoutErrorTransferOperation = transferOperation;
                    this.aborted = abort; 
                    this.closeState = CloseState.HandleClosed;
                    this.pipe.Close();
                    this.readOverlapped.FreeOrDefer();
                    this.writeOverlapped.FreeOrDefer(); 

                    if (this.atEOFEvent != null) 
                    { 
                        this.atEOFEvent.Close();
                    } 

                    // This should only do anything in the abort case.
                    try
                    { 
                        FinishPendingWrite(TimeSpan.Zero);
                    } 
                    catch (TimeoutException exception) 
                    {
                        if (DiagnosticUtility.ShouldTraceInformation) 
                        {
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                        }
                    } 
                    catch (CommunicationException exception)
                    { 
                        if (DiagnosticUtility.ShouldTraceInformation) 
                        {
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); 
                        }
                    }
                }
            } 

            if (abort) 
            { 
                TraceEventType traceEventType = TraceEventType.Warning;
 
                // we could be timing out a cached connection
                if (this.ExceptionEventType == TraceEventType.Information)
                {
                    traceEventType = this.ExceptionEventType; 
                }
 
                if (DiagnosticUtility.ShouldTrace(traceEventType)) 
                {
                    TraceUtility.TraceEvent(traceEventType, TraceCode.PipeConnectionAbort, this); 
                }
            }
        }
 
        CommunicationException CreatePipeDuplicationFailedException(int win32Error)
        { 
            Exception innerException = new PipeException(SR.GetString(SR.PipeDuplicationFailed), win32Error); 
            return new CommunicationException(innerException.Message, innerException);
        } 

        public object DuplicateAndClose(int targetProcessId)
        {
            SafeCloseHandle targetProcessHandle = ListenerUnsafeNativeMethods.OpenProcess(ListenerUnsafeNativeMethods.PROCESS_DUP_HANDLE, false, targetProcessId); 
            if (targetProcessHandle.IsInvalid)
            { 
                targetProcessHandle.SetHandleAsInvalid(); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                    CreatePipeDuplicationFailedException(Marshal.GetLastWin32Error()), ExceptionEventType); 
            }
            try
            {
                // no need to close this handle, it's a pseudo handle. expected value is -1. 
                IntPtr sourceProcessHandle = ListenerUnsafeNativeMethods.GetCurrentProcess();
                if (sourceProcessHandle == IntPtr.Zero) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(
                        CreatePipeDuplicationFailedException(Marshal.GetLastWin32Error()), ExceptionEventType); 
                }
                IntPtr duplicatedHandle;
                bool success = UnsafeNativeMethods.DuplicateHandle(sourceProcessHandle, this.pipe, targetProcessHandle, out duplicatedHandle, 0, false, UnsafeNativeMethods.DUPLICATE_SAME_ACCESS);
                if (!success) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper( 
                        CreatePipeDuplicationFailedException(Marshal.GetLastWin32Error()), ExceptionEventType); 
                }
                this.Abort(); 
                return duplicatedHandle;
            }
            finally
            { 
                targetProcessHandle.Close();
            } 
        } 

        public object GetCoreTransport() 
        {
            return pipe;
        }
 
        void EnsureBoundToCompletionPort()
        { 
            // Both read and write locks must be acquired before doing this 
            if (!isBoundToCompletionPort)
            { 
                ThreadPool.BindHandle(this.pipe);
                isBoundToCompletionPort = true;
            }
        } 

        public int EndRead() 
        { 
            if (asyncReadException != null)
            { 
                Exception exceptionToThrow = asyncReadException;
                asyncReadException = null;
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(exceptionToThrow, ExceptionEventType);
            } 
            return asyncBytesRead;
        } 
 
        public void EndWrite(IAsyncResult result)
        { 
            WriteAsyncResult.End(result);
        }

        void EnterReadingState() 
        {
            inReadingState = true; 
        } 

        void EnterWritingState() 
        {
            inWritingState = true;
        }
 
        void ExitReadingState()
        { 
            inReadingState = false; 
        }
 
        void ExitWritingState()
        {
            inWritingState = false;
        } 

        void ReadIOCompleted() 
        { 
            this.readOverlapped.FreeIfDeferred();
        } 

        void WriteIOCompleted()
        {
            this.writeOverlapped.FreeIfDeferred(); 
        }
 
        void FinishPendingWrite(TimeSpan timeout) 
        {
            if (this.pendingWriteBuffer == null) 
            {
                return;
            }
 
            byte[] buffer;
            BufferManager bufferManager; 
            lock (this.writeLock) 
            {
                if (this.pendingWriteBuffer == null) 
                {
                    return;
                }
 
                buffer = this.pendingWriteBuffer;
                this.pendingWriteBuffer = null; 
 
                bufferManager = this.pendingWriteBufferManager;
                this.pendingWriteBufferManager = null; 
            }

            try
            { 
                bool success = false;
                try 
                { 
                    WaitForSyncWrite(timeout, true);
                    success = true; 
                }
                finally
                {
                    lock (this.writeLock) 
                    {
                        try 
                        { 
                            if (success)
                            { 
                                FinishSyncWrite(true);
                            }
                        }
                        finally 
                        {
                            ExitWritingState(); 
                            if (!this.isWriteOutstanding) 
                            {
                                bufferManager.ReturnBuffer(buffer); 
                                WriteIOCompleted();
                            }
                        }
                    } 
                }
            } 
            catch (PipeException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Write), ExceptionEventType); 
            }
        }

#if FUTURE 
        ulong GetServerPid()
        { 
            ulong id; 
#pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
            if (!UnsafeNativeMethods.GetNamedPipeServerProcessId(pipe, out id)) 
            {
                Win32Exception e = new Win32Exception();
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(e.Message, e));
            } 
            return id;
        } 
 
        ulong GetClientPid()
        { 
            ulong id;
#pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
            if (!UnsafeNativeMethods.GetNamedPipeServerProcessId(pipe, out id))
            { 
                Win32Exception e = new Win32Exception();
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(e.Message, e)); 
            } 
            return id;
        } 
#endif

        void HandleReadComplete(int bytesRead)
        { 
            if (bytesRead == 0)
            { 
                isAtEOF = true; 
                atEOFEvent.Set();
            } 
        }

        bool IsBrokenPipeError(int error)
        { 
            return error == UnsafeNativeMethods.ERROR_NO_DATA ||
                error == UnsafeNativeMethods.ERROR_BROKEN_PIPE; 
        } 

        Exception CreatePipeClosedException(TransferOperation transferOperation) 
        {
            return ConvertPipeException(new PipeException(SR.GetString(SR.PipeClosed)), transferOperation);
        }
 
        unsafe void OnAsyncReadComplete(bool haveResult, int error, int numBytes)
        { 
            WaitCallback callback; 
            object state;
 
            lock (readLock)
            {
                try
                { 
                    try
                    { 
                        if (this.readTimeout != TimeSpan.MaxValue && !this.ReadTimer.Cancel()) 
                        {
                            this.Abort(SR.GetString(SR.PipeConnectionAbortedReadTimedOut, this.readTimeout), TransferOperation.Read); 
                        }

                        if (this.closeState == CloseState.HandleClosed)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeClosedException(TransferOperation.Read));
                        } 
                        if (!haveResult) 
                        {
                            if (UnsafeNativeMethods.GetOverlappedResult(this.pipe.DangerousGetHandle(), this.readOverlapped.NativeOverlapped, out numBytes, 0) == 0) 
                            {
                                error = Marshal.GetLastWin32Error();
                            }
                            else 
                            {
                                error = 0; 
                            } 
                        }
 
                        if (error != 0 && error != UnsafeNativeMethods.ERROR_MORE_DATA)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateReadException((int) error));
                        } 
                        this.asyncBytesRead = numBytes;
                        HandleReadComplete(this.asyncBytesRead); 
                    } 
                    catch (PipeException e)
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ConvertPipeException(e, TransferOperation.Read));
                    }
                }
#pragma warning suppress 56500 // [....], transferring exception to caller 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e)) 
                    {
                        throw; 
                    }

                    this.asyncReadException = e;
                } 
                finally
                { 
                    this.isReadOutstanding = false; 
                    ReadIOCompleted();
                    ExitReadingState(); 
                    callback = this.asyncReadCallback;
                    this.asyncReadCallback = null;
                    state = this.asyncReadCallbackState;
                    this.asyncReadCallbackState = null; 
                }
            } 
 
            callback(state);
        } 

        unsafe void OnAsyncWriteComplete(bool haveResult, int error, int numBytes)
        {
            WriteAsyncResult result = this.writeAsyncResult; 
            this.writeAsyncResult = null;
            if (result == null) 
            { 
                DiagnosticUtility.DebugAssert("Write completed with no WriteAsyncResult available.");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            }

            Exception writeException = null;
 
            this.WriteTimer.Cancel();
            lock (writeLock) 
            { 
                try
                { 
                    try
                    {
                        if (this.closeState == CloseState.HandleClosed)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeClosedException(TransferOperation.Write));
                        } 
                        if (!haveResult) 
                        {
                            if (UnsafeNativeMethods.GetOverlappedResult(this.pipe.DangerousGetHandle(), this.writeOverlapped.NativeOverlapped, out numBytes, 0) == 0) 
                            {
                                error = Marshal.GetLastWin32Error();
                            }
                            else 
                            {
                                error = 0; 
                            } 
                        }
 
                        if (error != 0)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateWriteException(error));
                        } 
                        else if (numBytes != result.WriteSize)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new PipeException(SR.GetString(SR.PipeWriteIncomplete))); 
                        }
                    } 
                    catch (PipeException e)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Write), ExceptionEventType);
                    } 
                }
#pragma warning suppress 56500 // [....], transferring exception to another thread 
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                    {
                        throw;
                    }
 
                    writeException = e;
                } 
                finally 
                {
                    this.isWriteOutstanding = false; 
                    WriteIOCompleted();
                    ExitWritingState();
                }
            } 

            result.Complete(false, writeException); 
        } 

        unsafe public int Read(byte[] buffer, int offset, int size, TimeSpan timeout) 
        {
            ConnectionUtilities.ValidateBufferBounds(buffer, offset, size);

            try 
            {
                lock (readLock) 
                { 
                    ValidateEnterReadingState(true);
                    if (isAtEOF) 
                    {
                        return 0;
                    }
 
                    StartSyncRead(buffer, offset, size);
                    EnterReadingState(); 
                } 

                int bytesRead = -1; 
                bool success = false;
                try
                {
                    WaitForSyncRead(timeout, true); 
                    success = true;
                } 
                finally 
                {
                    lock (this.readLock) 
                    {
                        try
                        {
                            if (success) 
                            {
                                bytesRead = FinishSyncRead(true); 
                                HandleReadComplete(bytesRead); 
                            }
                        } 
                        finally
                        {
                            ExitReadingState();
                            if (!this.isReadOutstanding) 
                            {
                                ReadIOCompleted(); 
                            } 
                        }
                    } 
                }

                DiagnosticUtility.DebugAssert(bytesRead >= 0, "Logic error in Read - bytesRead not set.");
                return bytesRead; 
            }
            catch (PipeException e) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Read), ExceptionEventType);
            } 
        }

        public void Shutdown(TimeSpan timeout)
        { 
            try
            { 
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
                FinishPendingWrite(timeoutHelper.RemainingTime());
 
                lock (writeLock)
                {
                    ValidateEnterWritingState(true);
                    StartWriteZero(timeoutHelper.RemainingTime()); 
                    isShutdownWritten = true;
                } 
            } 
            catch (PipeException e)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Undefined), ExceptionEventType);
            }
        }
 
        unsafe void StartReadZero()
        { 
            lock (this.readLock) 
            {
                ValidateEnterReadingState(false); 
                StartSyncRead(ZeroBuffer, 0, 1);
                EnterReadingState();
            }
        } 

        unsafe void StartWriteZero(TimeSpan timeout) 
        { 
            FinishPendingWrite(timeout);
 
            lock (this.writeLock)
            {
                ValidateEnterWritingState(false);
                StartSyncWrite(ZeroBuffer, 0, 0); 
                EnterWritingState();
            } 
        } 

        public bool Validate(Uri uri) 
        {
            return true;
        }
 
        void WaitForReadZero(TimeSpan timeout, bool traceExceptionsAsErrors)
        { 
            bool success = false; 
            try
            { 
                WaitForSyncRead(timeout, traceExceptionsAsErrors);
                success = true;
            }
            finally 
            {
                lock (this.readLock) 
                { 
                    try
                    { 
                        if (success)
                        {
                            if (FinishSyncRead(traceExceptionsAsErrors) != 0)
                            { 
                                Exception exception = ConvertPipeException(new PipeException(SR.GetString(SR.PipeSignalExpected)), TransferOperation.Read);
                                TraceEventType traceEventType = TraceEventType.Information; 
                                if (traceExceptionsAsErrors) 
                                {
                                    traceEventType = TraceEventType.Error; 
                                }
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(exception, traceEventType);
                            }
                        } 
                    }
                    finally 
                    { 
                        ExitReadingState();
                        if (!this.isReadOutstanding) 
                        {
                            ReadIOCompleted();
                        }
                    } 
                }
            } 
        } 

        void WaitForWriteZero(TimeSpan timeout, bool traceExceptionsAsErrors) 
        {
            bool success = false;
            try
            { 
                WaitForSyncWrite(timeout, traceExceptionsAsErrors);
                success = true; 
            } 
            finally
            { 
                lock (this.writeLock)
                {
                    try
                    { 
                        if (success)
                        { 
                            FinishSyncWrite(traceExceptionsAsErrors); 
                        }
                    } 
                    finally
                    {
                        ExitWritingState();
                        if (!this.isWriteOutstanding) 
                        {
                            WriteIOCompleted(); 
                        } 
                    }
                } 
            }
        }

        public void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout) 
        {
            WriteHelper(buffer, offset, size, immediate, timeout, ref this.writeOverlapped.Holder[0]); 
        } 

        // The holder is a perf optimization that lets us avoid repeatedly indexing into the array. 
        unsafe void WriteHelper(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout, ref object holder)
        {
            try
            { 
                FinishPendingWrite(timeout);
 
                ConnectionUtilities.ValidateBufferBounds(buffer, offset, size); 

                int bytesToWrite = size; 
                if (size > this.writeBufferSize)
                {
                    size = this.writeBufferSize;
                } 

                while (bytesToWrite > 0) 
                { 
                    lock (this.writeLock)
                    { 
                        ValidateEnterWritingState(true);

                        StartSyncWrite(buffer, offset, size, ref holder);
                        EnterWritingState(); 
                    }
 
                    bool success = false; 
                    try
                    { 
                        WaitForSyncWrite(timeout, true, ref holder);
                        success = true;
                    }
                    finally 
                    {
                        lock (this.writeLock) 
                        { 
                            try
                            { 
                                if (success)
                                {
                                    FinishSyncWrite(true);
                                } 
                            }
                            finally 
                            { 
                                ExitWritingState();
                                if (!this.isWriteOutstanding) 
                                {
                                    WriteIOCompleted();
                                }
                            } 
                        }
                    } 
 
                    bytesToWrite -= size;
                    offset += size; 
                    if (size > bytesToWrite)
                    {
                        size = bytesToWrite;
                    } 
                }
            } 
            catch (PipeException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Write), ExceptionEventType); 
            }
        }

        public unsafe void Write(byte[] buffer, int offset, int size, bool immediate, TimeSpan timeout, BufferManager bufferManager) 
        {
            bool shouldReturnBuffer = true; 
 
            try
            { 
                if (size > this.writeBufferSize)
                {
                    WriteHelper(buffer, offset, size, immediate, timeout, ref this.writeOverlapped.Holder[0]);
                    return; 
                }
 
                FinishPendingWrite(timeout); 

                ConnectionUtilities.ValidateBufferBounds(buffer, offset, size); 

                lock (this.writeLock)
                {
                    ValidateEnterWritingState(true); 

                    // This method avoids the call to GetOverlappedResult for synchronous completions.  Perf? 
                    bool success = false; 
                    try
                    { 
                        shouldReturnBuffer = false;
                        StartSyncWrite(buffer, offset, size);
                        success = true;
                    } 
                    finally
                    { 
                        if (!this.isWriteOutstanding) 
                        {
                            shouldReturnBuffer = true; 
                        }
                        else
                        {
                            if (success) 
                            {
                                EnterWritingState(); 
 
                                DiagnosticUtility.DebugAssert(this.pendingWriteBuffer == null, "Need to pend a write but one's already pending.");
                                this.pendingWriteBuffer = buffer; 
                                this.pendingWriteBufferManager = bufferManager;
                            }
                        }
                    } 
                }
            } 
            catch (PipeException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(ConvertPipeException(e, TransferOperation.Write), ExceptionEventType); 
            }
            finally
            {
                if (shouldReturnBuffer) 
                {
                    bufferManager.ReturnBuffer(buffer); 
                } 
            }
        } 

        void ValidateEnterReadingState(bool checkEOF)
        {
            if (checkEOF) 
            {
                if (closeState == CloseState.Closing) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeAlreadyClosing)), ExceptionEventType);
                } 
            }

            if (inReadingState)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeReadPending)), ExceptionEventType);
            } 
 
            if (closeState == CloseState.HandleClosed)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeClosed)), ExceptionEventType);
            }
        }
 
        void ValidateEnterWritingState(bool checkShutdown)
        { 
            if (checkShutdown) 
            {
                if (isShutdownWritten) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeAlreadyShuttingDown)), ExceptionEventType);
                }
 
                if (closeState == CloseState.Closing)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeAlreadyClosing)), ExceptionEventType); 
                }
            } 

            if (inWritingState)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeWritePending)), ExceptionEventType); 
            }
 
            if (closeState == CloseState.HandleClosed) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new PipeException(SR.GetString(SR.PipeClosed)), ExceptionEventType); 
            }
        }

        void StartSyncRead(byte[] buffer, int offset, int size) 
        {
            StartSyncRead(buffer, offset, size, ref this.readOverlapped.Holder[0]); 
        } 

        unsafe void StartSyncRead(byte[] buffer, int offset, int size, ref object holder) 
        {
            if (this.isReadOutstanding)
            {
                DiagnosticUtility.DebugAssert("StartSyncRead called when read I/O was already pending."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            } 
 
            try
            { 
                this.isReadOutstanding = true;
                this.readOverlapped.StartSyncOperation(buffer, ref holder);
                if (UnsafeNativeMethods.ReadFile(this.pipe.DangerousGetHandle(), this.readOverlapped.BufferPtr + offset, size, IntPtr.Zero, this.readOverlapped.NativeOverlapped) == 0)
                { 
                    int error = Marshal.GetLastWin32Error();
                    if (error != UnsafeNativeMethods.ERROR_IO_PENDING) 
                    { 
                        this.isReadOutstanding = false;
                        if (error != UnsafeNativeMethods.ERROR_MORE_DATA) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateReadException(error));
                        }
                    } 
                }
                else 
                { 
                    this.isReadOutstanding = false;
                } 
            }
            finally
            {
                if (!this.isReadOutstanding) 
                {
                    this.readOverlapped.CancelSyncOperation(ref holder); 
                } 
            }
        } 

        unsafe void WaitForSyncRead(TimeSpan timeout, bool traceExceptionsAsErrors)
        {
            if (this.isReadOutstanding) 
            {
                if (!this.readOverlapped.WaitForSyncOperation(timeout)) 
                { 
                    Abort(SR.GetString(SR.PipeConnectionAbortedReadTimedOut, this.readTimeout), TransferOperation.Read);
 
                    Exception timeoutException = new TimeoutException(SR.GetString(SR.PipeReadTimedOut, timeout));
                    TraceEventType traceEventType = TraceEventType.Information;
                    if (traceExceptionsAsErrors)
                    { 
                        traceEventType = TraceEventType.Error;
                    } 
 
                    // This intentionally doesn't reset isReadOutstanding, because technically it still is, and we need to not free the buffer.
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(timeoutException, traceEventType); 
                }
                else
                {
                    this.isReadOutstanding = false; 
                }
            } 
        } 

        // Must be called in a lock. 
        unsafe int FinishSyncRead(bool traceExceptionsAsErrors)
        {
            int bytesRead = -1;
            Exception readException; 

            if (this.closeState == CloseState.HandleClosed) 
            { 
                readException = CreatePipeClosedException(TransferOperation.Read);
            } 
            else
            {
                readException = Exceptions.GetOverlappedReadException(this.pipe, this.readOverlapped.NativeOverlapped, out bytesRead);
            } 
            if (readException != null)
            { 
                TraceEventType traceEventType = TraceEventType.Information; 
                if (traceExceptionsAsErrors)
                { 
                    traceEventType = TraceEventType.Error;
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(readException, traceEventType);
            } 

            return bytesRead; 
        } 

        void StartSyncWrite(byte[] buffer, int offset, int size) 
        {
            StartSyncWrite(buffer, offset, size, ref this.writeOverlapped.Holder[0]);
        }
 
        unsafe void StartSyncWrite(byte[] buffer, int offset, int size, ref object holder)
        { 
            if (this.isWriteOutstanding) 
            {
                DiagnosticUtility.DebugAssert("StartSyncWrite called when write I/O was already pending."); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }

            try 
            {
                this.syncWriteSize = size; 
                this.isWriteOutstanding = true; 
                this.writeOverlapped.StartSyncOperation(buffer, ref holder);
                if (UnsafeNativeMethods.WriteFile(this.pipe.DangerousGetHandle(), this.writeOverlapped.BufferPtr + offset, size, IntPtr.Zero, this.writeOverlapped.NativeOverlapped) == 0) 
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error != UnsafeNativeMethods.ERROR_IO_PENDING)
                    { 
                        this.isWriteOutstanding = false;
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Exceptions.CreateWriteException(error)); 
                    } 
                }
                else 
                {
                    this.isWriteOutstanding = false;
                }
            } 
            finally
            { 
                if (!this.isWriteOutstanding) 
                {
                    this.writeOverlapped.CancelSyncOperation(ref holder); 
                }
            }
        }
 
        void WaitForSyncWrite(TimeSpan timeout, bool traceExceptionsAsErrors)
        { 
            WaitForSyncWrite(timeout, traceExceptionsAsErrors, ref this.writeOverlapped.Holder[0]); 
        }
 
        unsafe void WaitForSyncWrite(TimeSpan timeout, bool traceExceptionsAsErrors, ref object holder)
        {
            if (this.isWriteOutstanding)
            { 
                if (!this.writeOverlapped.WaitForSyncOperation(timeout, ref holder))
                { 
                    Abort(SR.GetString(SR.PipeConnectionAbortedWriteTimedOut, this.writeTimeout), TransferOperation.Write); 

                    Exception timeoutException = new TimeoutException(SR.GetString(SR.PipeWriteTimedOut, timeout)); 
                    TraceEventType traceEventType = TraceEventType.Information;
                    if (traceExceptionsAsErrors)
                    {
                        traceEventType = TraceEventType.Error; 
                    }
 
                    // This intentionally doesn't reset isWriteOutstanding, because technically it still is, and we need to not free the buffer. 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelper(timeoutException, traceEventType);
                } 
                else
                {
                    this.isWriteOutstanding = false;
                } 
            }
        } 
 
        // Must be called in a lock.
        unsafe void FinishSyncWrite(bool traceExceptionsAsErrors) 
        {
            int bytesWritten;
            Exception writeException;
 
            if (this.closeState == CloseState.HandleClosed)
            { 
                writeException = CreatePipeClosedException(TransferOperation.Write); 
            }
            else 
            {
                writeException = Exceptions.GetOverlappedWriteException(this.pipe, this.writeOverlapped.NativeOverlapped, out bytesWritten);
                if (writeException == null && bytesWritten != this.syncWriteSize)
                { 
                    writeException = new PipeException(SR.GetString(SR.PipeWriteIncomplete));
                } 
            } 

            if (writeException != null) 
            {
                TraceEventType traceEventType = TraceEventType.Information;
                if (traceExceptionsAsErrors)
                { 
                    traceEventType = TraceEventType.Error;
                } 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelper(writeException, traceEventType); 
            }
        } 

        enum CloseState
        {
            Open, 
            Closing,
            HandleClosed, 
        } 

        enum TransferOperation 
        {
            Write,
            Read,
            Undefined, 
        }
 
        static class Exceptions 
        {
            static PipeException CreateException(string resourceString, int error) 
            {
                return new PipeException(SR.GetString(resourceString, PipeError.GetErrorString(error)), error);
            }
 
            public static PipeException CreateReadException(int error)
            { 
                return CreateException(SR.PipeReadError, error); 
            }
 
            public static PipeException CreateWriteException(int error)
            {
                return CreateException(SR.PipeWriteError, error);
            } 

            // Must be called in a lock, after checking for HandleClosed. 
            public static unsafe PipeException GetOverlappedWriteException(PipeHandle pipe, 
                NativeOverlapped* nativeOverlapped, out int bytesWritten)
            { 
                if (UnsafeNativeMethods.GetOverlappedResult(pipe.DangerousGetHandle(), nativeOverlapped, out bytesWritten, 0) == 0)
                {
                    int error = Marshal.GetLastWin32Error();
                    return Exceptions.CreateWriteException(error); 
                }
                else 
                { 
                    return null;
                } 
            }

            // Must be called in a lock, after checking for HandleClosed.
            public static unsafe PipeException GetOverlappedReadException(PipeHandle pipe, 
                NativeOverlapped* nativeOverlapped, out int bytesRead)
            { 
                if (UnsafeNativeMethods.GetOverlappedResult(pipe.DangerousGetHandle(), nativeOverlapped, out bytesRead, 0) == 0) 
                {
                    int error = Marshal.GetLastWin32Error(); 
                    if (error == UnsafeNativeMethods.ERROR_MORE_DATA)
                    {
                        return null;
                    } 

                    else 
                    { 
                        return Exceptions.CreateReadException(error);
                    } 
                }
                else
                {
                    return null; 
                }
            } 
        } 

        class WriteAsyncResult : AsyncResult 
        {
            int writeSize;

            public WriteAsyncResult(AsyncCallback callback, object state, int writeSize) 
                : base(callback, state)
            { 
                this.writeSize = writeSize; 
            }
 
            public new void Complete(bool completedSynchronously, Exception e)
            {
                base.Complete(completedSynchronously, e);
            } 

            public new void Complete(bool completedSynchronously) 
            { 
                base.Complete(completedSynchronously);
            } 

            public static void End(IAsyncResult result)
            {
                AsyncResult.End(result); 
            }
 
            public int WriteSize 
            {
                get 
                {
                    return this.writeSize;
                }
            } 
        }
    } 
 

    class PipeConnectionInitiator : IConnectionInitiator 
    {
        bool includeSecurityIdentity;
        int bufferSize;
 
        public PipeConnectionInitiator(bool includeSecurityIdentity, int bufferSize)
        { 
            this.includeSecurityIdentity = includeSecurityIdentity; 
            this.bufferSize = bufferSize;
        } 

        Exception CreateConnectFailedException(Uri remoteUri, PipeException innerException)
        {
            return new CommunicationException( 
                SR.GetString(SR.PipeConnectFailed, remoteUri.AbsoluteUri), innerException);
        } 
 
        public IConnection Connect(Uri remoteUri, TimeSpan timeout)
        { 
            string resolvedAddress;
            BackoffTimeoutHelper backoffHelper;
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            this.PrepareConnect(remoteUri, timeoutHelper.RemainingTime(), out resolvedAddress, out backoffHelper); 

            IConnection connection = null; 
            while (connection == null) 
            {
                connection = this.TryConnect(remoteUri, resolvedAddress, backoffHelper); 
                if (connection == null)
                {
                    backoffHelper.WaitAndBackoff();
 
                    if (DiagnosticUtility.ShouldTraceInformation)
                    { 
                        DiagnosticUtility.DiagnosticTrace.TraceEvent( 
                            TraceEventType.Information,
                            TraceCode.FailedPipeConnect, 
                            SR.GetString(
                                SR.TraceCodeFailedPipeConnect,
                                timeoutHelper.RemainingTime(),
                                remoteUri)); 
                    }
                } 
            } 
            return connection;
        } 

        internal static string GetPipeName(Uri uri)
        {
            // for wildcard hostName support, we first try and connect to the StrongWildcard, 
            // then the Exact HostName, and lastly the WeakWildcard
            string[] hostChoices = new string[] { "+", uri.Host, "*" }; 
            bool[] globalChoices = new bool[] { true, false }; 
            for (int i = 0; i < hostChoices.Length; i++)
            { 
                for (int iGlobal = 0; iGlobal < globalChoices.Length; iGlobal++)
                {
                    // walk up the path hierarchy, looking for first match
                    string path = PipeUri.GetPath(uri); 

                    while (path.Length > 0) 
                    { 
                        string sharedMemoryName = PipeUri.BuildSharedMemoryName(hostChoices[i], path, globalChoices[iGlobal]);
                        try 
                        {
                            PipeSharedMemory sharedMemory = PipeSharedMemory.Open(sharedMemoryName, uri);
                            if (sharedMemory != null)
                            { 
                                try
                                { 
                                    string pipeName = sharedMemory.PipeName; 
                                    if (pipeName != null)
                                    { 
                                        return pipeName;
                                    }
                                }
                                finally 
                                {
                                    sharedMemory.Dispose(); 
                                } 
                            }
                        } 
                        catch (AddressAccessDeniedException exception)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new EndpointNotFoundException(SR.GetString(
                                SR.EndpointNotFound, uri.AbsoluteUri), exception)); 
                        }
 
                        path = PipeUri.GetParentPath(path); 
                    }
                } 
            }

            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, uri.AbsoluteUri), 
                new PipeException(SR.GetString(SR.PipeEndpointNotFound, uri.AbsoluteUri))));
        } 
 
        public IAsyncResult BeginConnect(Uri uri, TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return new ConnectAsyncResult(this, uri, timeout, callback, state);
        }

        public IConnection EndConnect(IAsyncResult result) 
        {
            return ConnectAsyncResult.End(result); 
        } 

        void PrepareConnect(Uri remoteUri, TimeSpan timeout, out string resolvedAddress, 
            out BackoffTimeoutHelper backoffHelper)
        {
            PipeUri.Validate(remoteUri);
            if (DiagnosticUtility.ShouldTraceInformation) 
            {
                TraceUtility.TraceEvent(System.Diagnostics.TraceEventType.Information, TraceCode.InitiatingNamedPipeConnection, 
                    new StringTraceRecord("Uri", remoteUri.ToString()), this, null); 
            }
            resolvedAddress = GetPipeName(remoteUri); 

            backoffHelper = new BackoffTimeoutHelper(TimeoutHelper.ReserveTimeAtEnd(timeout), TimeSpan.FromMinutes(5));
        }
 
        IConnection TryConnect(Uri remoteUri, string resolvedAddress, BackoffTimeoutHelper backoffHelper)
        { 
            const int access = UnsafeNativeMethods.GENERIC_READ | UnsafeNativeMethods.GENERIC_WRITE; 
            bool lastAttempt = backoffHelper.IsExpired();
 
            int flags = UnsafeNativeMethods.FILE_FLAG_OVERLAPPED;
            if (includeSecurityIdentity)
            {
                flags |= UnsafeNativeMethods.SECURITY_QOS_PRESENT | UnsafeNativeMethods.SECURITY_IDENTIFICATION; 
            }
 
            PipeHandle pipeHandle = UnsafeNativeMethods.CreateFile(resolvedAddress, access, 0, IntPtr.Zero, 
                UnsafeNativeMethods.OPEN_EXISTING, flags, IntPtr.Zero);
            int error = Marshal.GetLastWin32Error(); 
            if (pipeHandle.IsInvalid)
            {
                pipeHandle.SetHandleAsInvalid();
            } 
            else
            { 
                int mode = UnsafeNativeMethods.PIPE_READMODE_MESSAGE; 
                if (UnsafeNativeMethods.SetNamedPipeHandleState(pipeHandle, ref mode, IntPtr.Zero, IntPtr.Zero) == 0)
                { 
                    error = Marshal.GetLastWin32Error();
                    pipeHandle.Close();
                    PipeException innerException = new PipeException(SR.GetString(SR.PipeModeChangeFailed,
                        PipeError.GetErrorString(error)), error); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        CreateConnectFailedException(remoteUri, innerException)); 
                } 
                return new PipeConnection(pipeHandle, bufferSize, false, true);
            } 

            if (error == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND || error == UnsafeNativeMethods.ERROR_PIPE_BUSY)
            {
                if (lastAttempt) 
                {
                    Exception innerException = new PipeException(SR.GetString(SR.PipeConnectAddressFailed, 
                        resolvedAddress, PipeError.GetErrorString(error)), error); 

                    TimeoutException timeoutException; 
                    string endpoint = remoteUri.AbsoluteUri;

                    if (error == UnsafeNativeMethods.ERROR_PIPE_BUSY)
                    { 
                        timeoutException = new TimeoutException(SR.GetString(SR.PipeConnectTimedOutServerTooBusy,
                            endpoint, backoffHelper.OriginalTimeout), innerException); 
                    } 
                    else
                    { 
                        timeoutException = new TimeoutException(SR.GetString(SR.PipeConnectTimedOut,
                            endpoint, backoffHelper.OriginalTimeout), innerException);
                    }
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(timeoutException);
                } 
 
                return null;
            } 
            else
            {
                PipeException innerException = new PipeException(SR.GetString(SR.PipeConnectAddressFailed,
                    resolvedAddress, PipeError.GetErrorString(error)), error); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    CreateConnectFailedException(remoteUri, innerException)); 
            } 
        }
 
        class ConnectAsyncResult : AsyncResult
        {
            PipeConnectionInitiator parent;
            Uri remoteUri; 
            string resolvedAddress;
            BackoffTimeoutHelper backoffHelper; 
            TimeoutHelper timeoutHelper; 
            IConnection connection;
            static WaitCallback waitCompleteCallback; 

            public ConnectAsyncResult(PipeConnectionInitiator parent, Uri remoteUri, TimeSpan timeout,
                AsyncCallback callback, object state)
                : base(callback, state) 
            {
                this.parent = parent; 
                this.remoteUri = remoteUri; 
                this.timeoutHelper = new TimeoutHelper(timeout);
                parent.PrepareConnect(remoteUri, this.timeoutHelper.RemainingTime(), out this.resolvedAddress, out this.backoffHelper); 

                if (this.ConnectAndWait())
                {
                    this.Complete(true); 
                }
            } 
 
            bool ConnectAndWait()
            { 
                this.connection = this.parent.TryConnect(this.remoteUri, this.resolvedAddress, this.backoffHelper);
                bool completed = (this.connection != null);
                if (!completed)
                { 
                    if (waitCompleteCallback == null)
                    { 
                        waitCompleteCallback = new WaitCallback(OnWaitComplete); 
                    }
                    this.backoffHelper.WaitAndBackoff(waitCompleteCallback, this); 
                }
                return completed;
            }
 
            public static IConnection End(IAsyncResult result)
            { 
                ConnectAsyncResult thisPtr = AsyncResult.End(result); 
                return thisPtr.connection;
            } 

            static void OnWaitComplete(object state)
            {
                Exception exception = null; 
                ConnectAsyncResult thisPtr = (ConnectAsyncResult)state;
 
                bool completeSelf = true; 
                try
                { 
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        DiagnosticUtility.DiagnosticTrace.TraceEvent(
                            TraceEventType.Information, 
                            TraceCode.FailedPipeConnect,
                            SR.GetString( 
                                SR.TraceCodeFailedPipeConnect, 
                                thisPtr.timeoutHelper.RemainingTime(),
                                thisPtr.remoteUri)); 
                    }

                    completeSelf = thisPtr.ConnectAndWait();
                } 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e)) 
                    {
                        throw; 
                    }
                    exception = e;
                }
 
                if (completeSelf)
                { 
                    thisPtr.Complete(false, exception); 
                }
            } 
        }
    }

    class PipeConnectionListener : IConnectionListener 
    {
        Uri pipeUri; 
        int bufferSize; 
        HostNameComparisonMode hostNameComparisonMode;
        bool isDisposed; 
        bool isListening;
        List pendingAccepts;
        bool anyPipesCreated;
        PipeSharedMemory sharedMemory; 
        List allowedSids;
        bool useCompletionPort; 
        int maxInstances; 

        public PipeConnectionListener(Uri pipeUri, HostNameComparisonMode hostNameComparisonMode, int bufferSize, 
            List allowedSids, bool useCompletionPort, int maxConnections)
        {
            PipeUri.Validate(pipeUri);
            this.pipeUri = pipeUri; 
            this.hostNameComparisonMode = hostNameComparisonMode;
            this.allowedSids = allowedSids; 
            this.bufferSize = bufferSize; 
            pendingAccepts = new List();
            this.useCompletionPort = useCompletionPort; 
            this.maxInstances = Math.Min(maxConnections, UnsafeNativeMethods.PIPE_UNLIMITED_INSTANCES);
        }

        object ThisLock 
        {
            get { return this; } 
        } 

        public string PipeName { get { return sharedMemory.PipeName; } } 

        public IAsyncResult BeginAccept(AsyncCallback callback, object state)
        {
            lock (ThisLock) 
            {
                if (isDisposed) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException("", SR.GetString(SR.PipeListenerDisposed)));
                } 

                if (!isListening)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.PipeListenerNotListening))); 
                }
 
                PipeHandle pipeHandle = CreatePipe(); 
                PendingAccept pendingAccept = new PendingAccept(this, pipeHandle, useCompletionPort, callback, state);
                if (!pendingAccept.CompletedSynchronously) 
                {
                    this.pendingAccepts.Add(pendingAccept);
                }
                return pendingAccept; 
            }
        } 
 
        public IConnection EndAccept(IAsyncResult result)
        { 
            PendingAccept pendingAccept = result as PendingAccept;
            if (pendingAccept == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.InvalidAsyncResult)); 
            }
 
            PipeHandle acceptedPipe = pendingAccept.End(); 

            if (acceptedPipe == null) 
            {
                return null;
            }
            else 
            {
                return new PipeConnection(acceptedPipe, bufferSize, 
                    pendingAccept.IsBoundToCompletionPort, pendingAccept.IsBoundToCompletionPort); 
            }
        } 

        unsafe PipeHandle CreatePipe()
        {
            int openMode = UnsafeNativeMethods.PIPE_ACCESS_DUPLEX | UnsafeNativeMethods.FILE_FLAG_OVERLAPPED; 
            if (!anyPipesCreated)
            { 
                openMode |= UnsafeNativeMethods.FILE_FLAG_FIRST_PIPE_INSTANCE; 
            }
 
            byte[] binarySecurityDescriptor = SecurityDescriptorHelper.FromSecurityIdentifiers(allowedSids, UnsafeNativeMethods.GENERIC_READ | UnsafeNativeMethods.GENERIC_WRITE);
            PipeHandle pipeHandle;
            int error;
            fixed (byte* pinnedSecurityDescriptor = binarySecurityDescriptor) 
            {
                UnsafeNativeMethods.SECURITY_ATTRIBUTES securityAttributes = new UnsafeNativeMethods.SECURITY_ATTRIBUTES(); 
                securityAttributes.lpSecurityDescriptor = (IntPtr)pinnedSecurityDescriptor; 

                pipeHandle = UnsafeNativeMethods.CreateNamedPipe(sharedMemory.PipeName, openMode, 
                    UnsafeNativeMethods.PIPE_TYPE_MESSAGE | UnsafeNativeMethods.PIPE_READMODE_MESSAGE,
                    maxInstances, bufferSize, bufferSize, 0, securityAttributes);
                error = Marshal.GetLastWin32Error();
            } 

            if (pipeHandle.IsInvalid) 
            { 
                pipeHandle.SetHandleAsInvalid();
 
                Exception innerException = new PipeException(SR.GetString(SR.PipeListenFailed,
                    pipeUri.AbsoluteUri, PipeError.GetErrorString(error)), error);

                if (error == UnsafeNativeMethods.ERROR_ACCESS_DENIED) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAccessDeniedException(innerException.Message, innerException)); 
                } 
                else if (error == UnsafeNativeMethods.ERROR_ALREADY_EXISTS)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAlreadyInUseException(innerException.Message, innerException));
                }
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(innerException.Message, innerException));
                } 
            } 

            bool closePipe = true; 
            try
            {
                if (useCompletionPort)
                { 
                    ThreadPool.BindHandle(pipeHandle);
                } 
                anyPipesCreated = true; 
                closePipe = false;
                return pipeHandle; 
            }
            finally
            {
                if (closePipe) 
                {
                    pipeHandle.Close(); 
                } 
            }
        } 

        public void Dispose()
        {
            lock (ThisLock) 
            {
                if (!isDisposed) 
                { 
                    if (sharedMemory != null)
                    { 
                        sharedMemory.Dispose();
                    }
                    for (int i = 0; i < pendingAccepts.Count; i++)
                    { 
                        pendingAccepts[i].Abort();
                    } 
                    isDisposed = true; 
                }
            } 
        }

        public void Listen()
        { 
            lock (ThisLock)
            { 
                if (!isListening) 
                {
                    string sharedMemoryName = PipeUri.BuildSharedMemoryName(pipeUri, hostNameComparisonMode, true); 
                    if (!PipeSharedMemory.TryCreate(allowedSids, pipeUri, sharedMemoryName, out this.sharedMemory))
                    {
                        PipeSharedMemory tempSharedMemory = null;
 
                        // first see if we're in RANU by creating a unique Uri in the global namespace
                        Uri tempUri = new Uri(pipeUri, Guid.NewGuid().ToString()); 
                        string tempSharedMemoryName = PipeUri.BuildSharedMemoryName(tempUri, hostNameComparisonMode, true); 
                        if (PipeSharedMemory.TryCreate(allowedSids, tempUri, tempSharedMemoryName, out tempSharedMemory))
                        { 
                            // we're not RANU, throw PipeNameInUse
                            tempSharedMemory.Dispose();
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                PipeSharedMemory.CreatePipeNameInUseException(UnsafeNativeMethods.ERROR_ACCESS_DENIED, pipeUri)); 
                        }
                        else 
                        { 
                            // try the session namespace since we're RANU
                            sharedMemoryName = PipeUri.BuildSharedMemoryName(pipeUri, hostNameComparisonMode, false); 
                            this.sharedMemory = PipeSharedMemory.Create(allowedSids, pipeUri, sharedMemoryName);
                        }
                    }
 
                    isListening = true;
                } 
            } 
        }
 
        void RemovePendingAccept(PendingAccept pendingAccept)
        {
            lock (ThisLock)
            { 
                DiagnosticUtility.DebugAssert(this.pendingAccepts.Contains(pendingAccept), "An unknown PendingAccept is removing itself.");
                this.pendingAccepts.Remove(pendingAccept); 
            } 
        }
 
        class PendingAccept : AsyncResult
        {
            PipeHandle pipeHandle;
            PipeHandle result; 
            OverlappedIOCompleteCallback onAcceptComplete;
            static WaitCallback onStartAccept; 
            OverlappedContext overlapped; 
            bool isBoundToCompletionPort;
            PipeConnectionListener listener; 

            public unsafe PendingAccept(PipeConnectionListener listener, PipeHandle pipeHandle, bool isBoundToCompletionPort,
                AsyncCallback callback, object state)
                : base(callback, state) 
            {
                this.pipeHandle = pipeHandle; 
                this.result = pipeHandle; 
                this.listener = listener;
                onAcceptComplete = new OverlappedIOCompleteCallback(OnAcceptComplete); 
                overlapped = new OverlappedContext();
                this.isBoundToCompletionPort = isBoundToCompletionPort;
                if (!Thread.CurrentThread.IsThreadPoolThread)
                { 
                    if (onStartAccept == null)
                    { 
                        onStartAccept = new WaitCallback(OnStartAccept); 
                    }
                    IOThreadScheduler.ScheduleCallback(onStartAccept, this); 
                }
                else
                {
                    StartAccept(true); 
                }
            } 
 
            public bool IsBoundToCompletionPort
            { 
                get { return this.isBoundToCompletionPort; }
            }

            static void OnStartAccept(object state) 
            {
                PendingAccept pendingAccept = (PendingAccept)state; 
                pendingAccept.StartAccept(false); 
            }
 
            Exception CreatePipeAcceptFailedException(int errorCode)
            {
                Exception innerException = new PipeException(SR.GetString(SR.PipeAcceptFailed,
                    PipeError.GetErrorString(errorCode)), errorCode); 
                return new CommunicationException(innerException.Message, innerException);
            } 
 
            unsafe void StartAccept(bool synchronous)
            { 
                Exception completionException = null;
                bool completeSelf = false;
                try
                { 
                    try
                    { 
                        this.overlapped.StartAsyncOperation(null, onAcceptComplete, this.isBoundToCompletionPort); 
                        while (true)
                        { 
                            if (UnsafeNativeMethods.ConnectNamedPipe(pipeHandle, overlapped.NativeOverlapped) == 0)
                            {
                                int error = Marshal.GetLastWin32Error();
                                switch (error) 
                                {
                                    case UnsafeNativeMethods.ERROR_NO_DATA: 
                                        if (UnsafeNativeMethods.DisconnectNamedPipe(pipeHandle) != 0) 
                                        {
                                            continue; 
                                        }
                                        else
                                        {
                                            completeSelf = true; 
                                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeAcceptFailedException(error));
                                        } 
                                    case UnsafeNativeMethods.ERROR_PIPE_CONNECTED: 
                                        completeSelf = true;
                                        break; 
                                    case UnsafeNativeMethods.ERROR_IO_PENDING:
                                        break;
                                    default:
                                        completeSelf = true; 
                                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeAcceptFailedException(error));
                                } 
                            } 
                            else
                            { 
                                completeSelf = true;
                            }

                            break; 
                        }
                    } 
                    catch (ObjectDisposedException exception) 
                    {
                        // A race with Abort can cause PipeHandle to throw this. 
                        DiagnosticUtility.DebugAssert(this.result == null, "Got an ObjectDisposedException but not an Abort!");
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information); 
                        }
                        completeSelf = true; 
                    } 
                    finally
                    { 
                        if (completeSelf)
                        {
                            this.overlapped.CancelAsyncOperation();
                            this.overlapped.Free(); 
                        }
                    } 
                } 
#pragma warning suppress 56500 // [....], transferring exception to another thread
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e))
                    {
                        throw; 
                    }
 
                    completeSelf = true; 
                    completionException = e;
                } 
                if (completeSelf)
                {
                    if (!synchronous)
                    { 
                        this.listener.RemovePendingAccept(this);
                    } 
                    base.Complete(synchronous, completionException); 
                }
            } 

            // Must be called in PipeConnectionListener's lock.
            public void Abort()
            { 
                this.result = null; // we need to return null after an abort
                pipeHandle.Close(); 
            } 

            public PipeHandle End() 
            {
                AsyncResult.End(this);
                return this.result;
            } 

            unsafe void OnAcceptComplete(bool haveResult, int error, int numBytes) 
            { 
                this.listener.RemovePendingAccept(this);
 
                if (!haveResult)
                {
                    // No race with Abort here since Abort can't be called once RemovePendingAccept happens.
                    if (this.result != null && UnsafeNativeMethods.GetOverlappedResult(this.pipeHandle, 
                        this.overlapped.NativeOverlapped, out numBytes, 0) == 0)
                    { 
                        error = Marshal.GetLastWin32Error(); 
                    }
                    else 
                    {
                        error = 0;
                    }
                } 

                this.overlapped.Free(); 
 
                if (error != 0)
                { 
                    this.pipeHandle.Close();
                    base.Complete(false, CreatePipeAcceptFailedException(error));
                }
                else 
                {
                    base.Complete(false); 
                } 
            }
        } 
    }

    static class SecurityDescriptorHelper
    { 
        static byte[] worldCreatorOwnerWithReadAndWriteDescriptorDenyNetwork;
        static byte[] worldCreatorOwnerWithReadDescriptorDenyNetwork; 
 
        static SecurityDescriptorHelper()
        { 
            worldCreatorOwnerWithReadAndWriteDescriptorDenyNetwork = FromSecurityIdentifiersFull(null, UnsafeNativeMethods.GENERIC_READ | UnsafeNativeMethods.GENERIC_WRITE);
            worldCreatorOwnerWithReadDescriptorDenyNetwork = FromSecurityIdentifiersFull(null, UnsafeNativeMethods.GENERIC_READ);
        }
 
        internal static byte[] FromSecurityIdentifiers(List allowedSids, int accessRights)
        { 
            if (allowedSids == null) 
            {
                if (accessRights == (UnsafeNativeMethods.GENERIC_READ | UnsafeNativeMethods.GENERIC_WRITE)) 
                {
                    return worldCreatorOwnerWithReadAndWriteDescriptorDenyNetwork;
                }
 
                if (accessRights == UnsafeNativeMethods.GENERIC_READ)
                { 
                    return worldCreatorOwnerWithReadDescriptorDenyNetwork; 
                }
            } 

            return FromSecurityIdentifiersFull(allowedSids, accessRights);
        }
 
        static byte[] FromSecurityIdentifiersFull(List allowedSids, int accessRights)
        { 
            int capacity = allowedSids == null ? 3 : 2 + allowedSids.Count; 
            DiscretionaryAcl dacl = new DiscretionaryAcl(false, false, capacity);
 
            // add deny ACE first so that we don't get short circuited
            dacl.AddAccess(AccessControlType.Deny, new SecurityIdentifier(WellKnownSidType.NetworkSid, null),
                UnsafeNativeMethods.GENERIC_ALL, InheritanceFlags.None, PropagationFlags.None);
 
            if (allowedSids == null)
            { 
                dacl.AddAccess(AccessControlType.Allow, new SecurityIdentifier(WellKnownSidType.WorldSid, null), 
                    accessRights, InheritanceFlags.None, PropagationFlags.None);
            } 
            else
            {
                for (int i = 0; i < allowedSids.Count; i++)
                { 
                    SecurityIdentifier allowedSid = allowedSids[i];
                    dacl.AddAccess(AccessControlType.Allow, allowedSid, 
                        accessRights, InheritanceFlags.None, PropagationFlags.None); 
                }
            } 
            dacl.AddAccess(AccessControlType.Allow, new SecurityIdentifier(WellKnownSidType.CreatorOwnerSid, null),
                accessRights, InheritanceFlags.None, PropagationFlags.None);

            CommonSecurityDescriptor securityDescriptor = 
                new CommonSecurityDescriptor(false, false, ControlFlags.None, null, null, null, dacl);
            byte[] binarySecurityDescriptor = new byte[securityDescriptor.BinaryLength]; 
            securityDescriptor.GetBinaryForm(binarySecurityDescriptor, 0); 
            return binarySecurityDescriptor;
        } 
    }


    unsafe class PipeSharedMemory : IDisposable 
    {
        SafeFileMappingHandle fileMapping; 
        string pipeName; 
        Uri pipeUri;
 
        PipeSharedMemory(SafeFileMappingHandle fileMapping, Uri pipeUri)
            : this(fileMapping, pipeUri, null)
        {
        } 

        PipeSharedMemory(SafeFileMappingHandle fileMapping, Uri pipeUri, string pipeName) 
        { 
            this.pipeName = pipeName;
            this.fileMapping = fileMapping; 
            this.pipeUri = pipeUri;
        }

        public static PipeSharedMemory Create(List allowedSids, Uri pipeUri, string sharedMemoryName) 
        {
            PipeSharedMemory result; 
            if (TryCreate(allowedSids, pipeUri, sharedMemoryName, out result)) 
            {
                return result; 
            }
            else
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeNameInUseException(UnsafeNativeMethods.ERROR_ACCESS_DENIED, pipeUri)); 
            }
        } 
 
        public unsafe static bool TryCreate(List allowedSids, Uri pipeUri, string sharedMemoryName, out PipeSharedMemory result)
        { 
            Guid pipeGuid = Guid.NewGuid();
            string pipeName = BuildPipeName(pipeGuid);
            byte[] binarySecurityDescriptor = SecurityDescriptorHelper.FromSecurityIdentifiers(allowedSids, UnsafeNativeMethods.GENERIC_READ);
            SafeFileMappingHandle fileMapping; 
            int error;
            result = null; 
            fixed (byte* pinnedSecurityDescriptor = binarySecurityDescriptor) 
            {
                UnsafeNativeMethods.SECURITY_ATTRIBUTES securityAttributes = new UnsafeNativeMethods.SECURITY_ATTRIBUTES(); 
                securityAttributes.lpSecurityDescriptor = (IntPtr)pinnedSecurityDescriptor;

                fileMapping = UnsafeNativeMethods.CreateFileMapping((IntPtr)(-1), securityAttributes,
                    UnsafeNativeMethods.PAGE_READWRITE, 0, sizeof(SharedMemoryContents), sharedMemoryName); 
                error = Marshal.GetLastWin32Error();
            } 
 
            if (fileMapping.IsInvalid)
            { 
                fileMapping.SetHandleAsInvalid();
                if (error == UnsafeNativeMethods.ERROR_ACCESS_DENIED)
                {
                    return false; 
                }
                else 
                { 
                    Exception innerException = new PipeException(SR.GetString(SR.PipeNameCantBeReserved,
                        pipeUri.AbsoluteUri, PipeError.GetErrorString(error)), error); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AddressAccessDeniedException(innerException.Message, innerException));
                }
            }
 
            // now we have a valid file mapping handle
            if (error == UnsafeNativeMethods.ERROR_ALREADY_EXISTS) 
            { 
                fileMapping.Close();
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeNameInUseException(error, pipeUri)); 
            }
            PipeSharedMemory pipeSharedMemory = new PipeSharedMemory(fileMapping, pipeUri, pipeName);
            bool disposeSharedMemory = true;
            try 
            {
                pipeSharedMemory.InitializeContents(pipeGuid); 
                disposeSharedMemory = false; 
                result = pipeSharedMemory;
                return true; 
            }
            finally
            {
                if (disposeSharedMemory) 
                {
                    pipeSharedMemory.Dispose(); 
                } 
            }
        } 

        public static PipeSharedMemory Open(string sharedMemoryName, Uri pipeUri)
        {
            SafeFileMappingHandle fileMapping = UnsafeNativeMethods.OpenFileMapping( 
                UnsafeNativeMethods.FILE_MAP_READ, false, sharedMemoryName);
            if (fileMapping.IsInvalid) 
            { 
                int error = Marshal.GetLastWin32Error();
                fileMapping.SetHandleAsInvalid(); 
                if (error == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND)
                {
                    fileMapping = UnsafeNativeMethods.OpenFileMapping(
                        UnsafeNativeMethods.FILE_MAP_READ, false, "Global\\" + sharedMemoryName); 
                    if (fileMapping.IsInvalid)
                    { 
                        error = Marshal.GetLastWin32Error(); 
                        fileMapping.SetHandleAsInvalid();
                        if (error == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) 
                        {
                            return null;
                        }
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeNameCannotBeAccessedException(error, pipeUri)); 
                    }
                    return new PipeSharedMemory(fileMapping, pipeUri); 
                } 

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeNameCannotBeAccessedException(error, pipeUri)); 
            }
            return new PipeSharedMemory(fileMapping, pipeUri);
        }
 
        public void Dispose()
        { 
            if (fileMapping != null) 
            {
                fileMapping.Close(); 
                fileMapping = null;
            }
        }
 
        public string PipeName
        { 
            get 
            {
                if (pipeName == null) 
                {
                    SafeViewOfFileHandle view = GetView(false);
                    try
                    { 
                        SharedMemoryContents* contents = (SharedMemoryContents*) view.DangerousGetHandle();
                        if (contents->isInitialized) 
                        { 
                            Thread.MemoryBarrier();
                            pipeName = BuildPipeName(contents->pipeGuid); 
                        }
                    }
                    finally
                    { 
                        view.Close();
                    } 
                } 
                return pipeName;
            } 
        }

        void InitializeContents(Guid pipeGuid)
        { 
            SafeViewOfFileHandle view = GetView(true);
            try 
            { 
                SharedMemoryContents* contents = (SharedMemoryContents*)view.DangerousGetHandle();
                contents->pipeGuid = pipeGuid; 
                Thread.MemoryBarrier();
                contents->isInitialized = true;
            }
            finally 
            {
                view.Close(); 
            } 
        }
 
        public static Exception CreatePipeNameInUseException(int error, Uri pipeUri)
        {
            Exception innerException = new PipeException(SR.GetString(SR.PipeNameInUse, pipeUri.AbsoluteUri), error);
            return new AddressAlreadyInUseException(innerException.Message, innerException); 
        }
 
        static Exception CreatePipeNameCannotBeAccessedException(int error, Uri pipeUri) 
        {
            Exception innerException = new PipeException(SR.GetString(SR.PipeNameCanNotBeAccessed, 
                PipeError.GetErrorString(error)), error);
            return new AddressAccessDeniedException(SR.GetString(SR.PipeNameCanNotBeAccessed2, pipeUri.AbsoluteUri), innerException);
        }
 
        SafeViewOfFileHandle GetView(bool writable)
        { 
            SafeViewOfFileHandle handle = UnsafeNativeMethods.MapViewOfFile(fileMapping, 
                writable ? UnsafeNativeMethods.FILE_MAP_WRITE : UnsafeNativeMethods.FILE_MAP_READ,
                0, 0, (IntPtr)sizeof(SharedMemoryContents)); 
            if (handle.IsInvalid)
            {
                int error = Marshal.GetLastWin32Error();
                handle.SetHandleAsInvalid(); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreatePipeNameCannotBeAccessedException(error, pipeUri));
            } 
            return handle; 
        }
 
        static string BuildPipeName(Guid guid)
        {
            return "\\\\.\\pipe\\" + guid.ToString();
        } 

        [StructLayout(LayoutKind.Sequential)] 
        struct SharedMemoryContents 
        {
            public bool isInitialized; 
            public Guid pipeGuid;
        }
    }
 
    static class PipeUri
    { 
        public static string BuildSharedMemoryName(Uri uri, HostNameComparisonMode hostNameComparisonMode, bool global) 
        {
            string path = PipeUri.GetPath(uri); 
            string host = null;

            switch (hostNameComparisonMode)
            { 
                case HostNameComparisonMode.StrongWildcard:
                    host = "+"; 
                    break; 
                case HostNameComparisonMode.Exact:
                    host = uri.Host; 
                    break;
                case HostNameComparisonMode.WeakWildcard:
                    host = "*";
                    break; 
            }
 
            return PipeUri.BuildSharedMemoryName(host, path, global); 
        }
 
        public static string BuildSharedMemoryName(string hostName, string path, bool global)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(Uri.UriSchemeNetPipe); 
            builder.Append("://");
            builder.Append(hostName.ToUpperInvariant()); 
            builder.Append(path); 
            string canonicalName = builder.ToString();
 
            byte[] canonicalBytes = Encoding.UTF8.GetBytes(canonicalName);
            byte[] hashedBytes;
            string separator;
 
            if (canonicalBytes.Length >= 128)
            { 
                // we don't need to check fips for our useage, so create a Managed SHA1 directly 
                // avoids IdentityModel faulting into the reference set.
                using (HashAlgorithm hash = new SHA1Managed()) 
                {
                    hashedBytes = hash.ComputeHash(canonicalBytes);
                }
                separator = ":H"; 
            }
            else 
            { 
                hashedBytes = canonicalBytes;
                separator = ":E"; 
            }

            builder = new StringBuilder();
            if (global) 
            {
                // we may need to create the shared memory in the global namespace so we work with terminal services+admin 
                builder.Append("Global\\"); 
            }
            else 
            {
                builder.Append("Local\\");
            }
            builder.Append(Uri.UriSchemeNetPipe); 
            builder.Append(separator);
            builder.Append(Convert.ToBase64String(hashedBytes)); 
            return builder.ToString(); 
        }
 
        public static string GetPath(Uri uri)
        {
            string path = uri.LocalPath.ToUpperInvariant();
            if (!path.EndsWith("/", StringComparison.Ordinal)) 
                path = path + "/";
            return path; 
        } 

        public static string GetParentPath(string path) 
        {
            if (path.EndsWith("/", StringComparison.Ordinal))
                path = path.Substring(0, path.Length - 1);
            if (path.Length == 0) 
                return path;
            return path.Substring(0, path.LastIndexOf('/') + 1); 
        } 

        public static void Validate(Uri uri) 
        {
            if (uri.Scheme != Uri.UriSchemeNetPipe)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("uri", SR.GetString(SR.PipeUriSchemeWrong));
        } 
    }
 
    static class PipeError 
    {
        public static string GetErrorString(int error) 
        {
            StringBuilder stringBuilder = new StringBuilder(512);
            if (UnsafeNativeMethods.FormatMessage(UnsafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS |
                UnsafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM | UnsafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY, 
                IntPtr.Zero, error, CultureInfo.CurrentCulture.LCID, stringBuilder, stringBuilder.Capacity, IntPtr.Zero) != 0)
            { 
                stringBuilder = stringBuilder.Replace("\n", ""); 
                stringBuilder = stringBuilder.Replace("\r", "");
                return SR.GetString( 
                    SR.PipeKnownWin32Error,
                    stringBuilder.ToString(),
                    error.ToString(CultureInfo.InvariantCulture),
                    Convert.ToString(error, 16)); 
            }
            else 
            { 
                return SR.GetString(
                    SR.PipeUnknownWin32Error, 
                    error.ToString(CultureInfo.InvariantCulture),
                    Convert.ToString(error, 16));
            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK