private GetSecAttrs ( HandleInheritability inheritability ) : Interop.Kernel32.SECURITY_ATTRIBUTES | ||
inheritability | HandleInheritability | |
return | Interop.Kernel32.SECURITY_ATTRIBUTES |
public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) : base(direction, bufferSize) { object obj2; if (direction == PipeDirection.InOut) { throw new NotSupportedException(System.SR.GetString("NotSupported_AnonymousPipeUnidirectional")); } if ((inheritability < HandleInheritability.None) || (inheritability > HandleInheritability.Inheritable)) { throw new ArgumentOutOfRangeException("inheritability", System.SR.GetString("ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable")); } Microsoft.Win32.UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out obj2); try { this.Create(direction, secAttrs, bufferSize); } finally { if (obj2 != null) { ((GCHandle)obj2).Free(); } } }
// Creates the anonymous pipe. This overload is used in Mono to implement public constructors. private void Create(PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) { Debug.Assert(direction != PipeDirection.InOut, "Anonymous pipe direction shouldn't be InOut"); Debug.Assert(bufferSize >= 0, "bufferSize is negative"); bool bSuccess; SafePipeHandle serverHandle; SafePipeHandle newServerHandle; // Create the two pipe handles that make up the anonymous pipe. GCHandle pinningHandle = default; try { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, ref pinningHandle); if (direction == PipeDirection.In) { bSuccess = Interop.Kernel32.CreatePipe(out serverHandle, out _clientHandle, ref secAttrs, bufferSize); } else { bSuccess = Interop.Kernel32.CreatePipe(out _clientHandle, out serverHandle, ref secAttrs, bufferSize); } } finally { if (pinningHandle.IsAllocated) { pinningHandle.Free(); } } if (!bSuccess) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Duplicate the server handle to make it not inheritable. Note: We need to do this so that the child // process doesn't end up getting another copy of the server handle. If it were to get a copy, the // OS wouldn't be able to inform the child that the server has closed its handle because it will see // that there is still one server handle that is open. bSuccess = Interop.Kernel32.DuplicateHandle(Interop.Kernel32.GetCurrentProcess(), serverHandle, Interop.Kernel32.GetCurrentProcess(), out newServerHandle, 0, false, Interop.Kernel32.HandleOptions.DUPLICATE_SAME_ACCESS); if (!bSuccess) { throw Win32Marshal.GetExceptionForLastWin32Error(); } // Close the inheritable server handle. serverHandle.Dispose(); InitializeHandle(newServerHandle, false, false); State = PipeState.Connected; }
public NamedPipeServerStream(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights) : base(direction, transmissionMode, outBufferSize) { if (pipeName == null) { throw new ArgumentNullException("pipeName"); } if (pipeName.Length == 0) { throw new ArgumentException(System.SR.GetString("Argument_NeedNonemptyPipeName")); } if ((options & ~(PipeOptions.Asynchronous | PipeOptions.WriteThrough)) != PipeOptions.None) { throw new ArgumentOutOfRangeException("options", System.SR.GetString("ArgumentOutOfRange_OptionsInvalid")); } if (inBufferSize < 0) { throw new ArgumentOutOfRangeException("inBufferSize", System.SR.GetString("ArgumentOutOfRange_NeedNonNegNum")); } if (((maxNumberOfServerInstances < 1) || (maxNumberOfServerInstances > 0xfe)) && (maxNumberOfServerInstances != -1)) { throw new ArgumentOutOfRangeException("maxNumberOfServerInstances", System.SR.GetString("ArgumentOutOfRange_MaxNumServerInstances")); } if ((inheritability < HandleInheritability.None) || (inheritability > HandleInheritability.Inheritable)) { throw new ArgumentOutOfRangeException("inheritability", System.SR.GetString("ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable")); } if ((additionalAccessRights & ~(PipeAccessRights.AccessSystemSecurity | PipeAccessRights.TakeOwnership | PipeAccessRights.ChangePermissions)) != 0) { throw new ArgumentOutOfRangeException("additionalAccessRights", System.SR.GetString("ArgumentOutOfRange_AdditionalAccessLimited")); } if (Environment.OSVersion.Platform == PlatformID.Win32Windows) { throw new PlatformNotSupportedException(System.SR.GetString("PlatformNotSupported_NamedPipeServers")); } string fullPath = Path.GetFullPath(@"\\.\pipe\" + pipeName); if (string.Compare(fullPath, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase) == 0) { throw new ArgumentOutOfRangeException("pipeName", System.SR.GetString("ArgumentOutOfRange_AnonymousReserved")); } object pinningHandle = null; Microsoft.Win32.UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out pinningHandle); try { this.Create(fullPath, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, additionalAccessRights, secAttrs); } finally { if (pinningHandle != null) { ((GCHandle)pinningHandle).Free(); } } }
public void Connect(int timeout) { this.CheckConnectOperationsClient(); if ((timeout < 0) && (timeout != -1)) { throw new ArgumentOutOfRangeException("timeout", System.SR.GetString("ArgumentOutOfRange_InvalidTimeout")); } Microsoft.Win32.UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(this.m_inheritability); int pipeOptions = (int)this.m_pipeOptions; if (this.m_impersonationLevel != TokenImpersonationLevel.None) { pipeOptions |= 0x100000; pipeOptions |= ((int)(this.m_impersonationLevel - 1)) << 0x10; } int tickCount = Environment.TickCount; int num3 = 0; Label_005C: if (!Microsoft.Win32.UnsafeNativeMethods.WaitNamedPipe(this.m_normalizedPipePath, timeout - num3)) { int errorCode = Marshal.GetLastWin32Error(); switch (errorCode) { case 2: goto Label_00EF; case 0: goto Label_0105; } System.IO.__Error.WinIOError(errorCode, string.Empty); } SafePipeHandle handle = Microsoft.Win32.UnsafeNativeMethods.CreateNamedPipeClient(this.m_normalizedPipePath, this.m_access, FileShare.None, secAttrs, FileMode.Open, pipeOptions, Microsoft.Win32.UnsafeNativeMethods.NULL); if (handle.IsInvalid) { int num5 = Marshal.GetLastWin32Error(); if (num5 == 0xe7) { goto Label_00EF; } System.IO.__Error.WinIOError(num5, string.Empty); } base.InitializeHandle(handle, false, (this.m_pipeOptions & PipeOptions.Asynchronous) != PipeOptions.None); base.State = PipeState.Connected; return; Label_00EF: if ((timeout == -1) || ((num3 = Environment.TickCount - tickCount) < timeout)) { goto Label_005C; } Label_0105: throw new TimeoutException(); }
private void Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability) { Debug.Assert(pipeName != null && pipeName.Length != 0, "fullPipeName is null or empty"); Debug.Assert(direction >= PipeDirection.In && direction <= PipeDirection.InOut, "invalid pipe direction"); Debug.Assert(inBufferSize >= 0, "inBufferSize is negative"); Debug.Assert(outBufferSize >= 0, "outBufferSize is negative"); Debug.Assert((maxNumberOfServerInstances >= 1 && maxNumberOfServerInstances <= 254) || (maxNumberOfServerInstances == MaxAllowedServerInstances), "maxNumberOfServerInstances is invalid"); Debug.Assert(transmissionMode >= PipeTransmissionMode.Byte && transmissionMode <= PipeTransmissionMode.Message, "transmissionMode is out of range"); string fullPipeName = Path.GetFullPath(@"\\.\pipe\" + pipeName); // Make sure the pipe name isn't one of our reserved names for anonymous pipes. if (String.Equals(fullPipeName, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentOutOfRangeException(nameof(pipeName), SR.ArgumentOutOfRange_AnonymousReserved); } int openMode = ((int)direction) | (maxNumberOfServerInstances == 1 ? Interop.mincore.FileOperations.FILE_FLAG_FIRST_PIPE_INSTANCE : 0) | (int)options; // We automatically set the ReadMode to match the TransmissionMode. int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1; // Convert -1 to 255 to match win32 (we asserted that it is between -1 and 254). if (maxNumberOfServerInstances == MaxAllowedServerInstances) { maxNumberOfServerInstances = 255; } Interop.mincore.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability); SafePipeHandle handle = Interop.mincore.CreateNamedPipe(fullPipeName, openMode, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs); if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(); } InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0); }
// Waits for a pipe instance to become available. This method may return before WaitForConnection is called // on the server end, but WaitForConnection will not return until we have returned. Any data written to the // pipe by us after we have connected but before the server has called WaitForConnection will be available // to the server after it calls WaitForConnection. private bool TryConnect(int timeout, CancellationToken cancellationToken) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability); // PipeOptions.CurrentUserOnly is special since it doesn't match directly to a corresponding Win32 valid flag. // Remove it, while keeping others untouched since historically this has been used as a way to pass flags to // CreateNamedPipeClient that were not defined in the enumeration. int _pipeFlags = (int)(_pipeOptions & ~PipeOptions.CurrentUserOnly); if (_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)_impersonationLevel - 1) << 16); } int access = 0; if ((PipeDirection.In & _direction) != 0) { access |= Interop.Kernel32.GenericOperations.GENERIC_READ; } if ((PipeDirection.Out & _direction) != 0) { access |= Interop.Kernel32.GenericOperations.GENERIC_WRITE; } // Let's try to connect first SafePipeHandle handle = Interop.Kernel32.CreateNamedPipeClient(_normalizedPipePath, access, // read and write access 0, // sharing: none ref secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags IntPtr.Zero); // template file: null if (handle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_PIPE_BUSY && errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } if (!Interop.Kernel32.WaitNamedPipe(_normalizedPipePath, timeout)) { errorCode = Marshal.GetLastWin32Error(); // Server is not yet created or a timeout occurred before a pipe instance was available. if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_SEM_TIMEOUT) { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Pipe server should be free. Let's try to connect to it. handle = Interop.Kernel32.CreateNamedPipeClient(_normalizedPipePath, access, // read and write access 0, // sharing: none ref secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags IntPtr.Zero); // template file: null if (handle.IsInvalid) { errorCode = Marshal.GetLastWin32Error(); // Handle the possible race condition of someone else connecting to the server // between our calls to WaitNamedPipe & CreateFile. if (errorCode == Interop.Errors.ERROR_PIPE_BUSY) { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } // Success! InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; ValidateRemotePipeUser(); return(true); }
private void Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, HandleInheritability inheritability) { Debug.Assert(pipeName != null && pipeName.Length != 0, "fullPipeName is null or empty"); Debug.Assert(direction >= PipeDirection.In && direction <= PipeDirection.InOut, "invalid pipe direction"); Debug.Assert(inBufferSize >= 0, "inBufferSize is negative"); Debug.Assert(outBufferSize >= 0, "outBufferSize is negative"); Debug.Assert((maxNumberOfServerInstances >= 1 && maxNumberOfServerInstances <= 254) || (maxNumberOfServerInstances == MaxAllowedServerInstances), "maxNumberOfServerInstances is invalid"); Debug.Assert(transmissionMode >= PipeTransmissionMode.Byte && transmissionMode <= PipeTransmissionMode.Message, "transmissionMode is out of range"); string fullPipeName = Path.GetFullPath(@"\\.\pipe\" + pipeName); // Make sure the pipe name isn't one of our reserved names for anonymous pipes. if (String.Equals(fullPipeName, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentOutOfRangeException(nameof(pipeName), SR.ArgumentOutOfRange_AnonymousReserved); } PipeSecurity pipeSecurity = null; if (IsCurrentUserOnly) { using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent()) { SecurityIdentifier identifier = currentIdentity.Owner; PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.ReadWrite, AccessControlType.Allow); pipeSecurity = new PipeSecurity(); pipeSecurity.AddAccessRule(rule); pipeSecurity.SetOwner(identifier); } // PipeOptions.CurrentUserOnly is special since it doesn't match directly to a corresponding Win32 valid flag. // Remove it, while keeping others untouched since historically this has been used as a way to pass flags to CreateNamedPipe // that were not defined in the enumeration. options &= ~PipeOptions.CurrentUserOnly; } int openMode = ((int)direction) | (maxNumberOfServerInstances == 1 ? Interop.Kernel32.FileOperations.FILE_FLAG_FIRST_PIPE_INSTANCE : 0) | (int)options; // We automatically set the ReadMode to match the TransmissionMode. int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1; // Convert -1 to 255 to match win32 (we asserted that it is between -1 and 254). if (maxNumberOfServerInstances == MaxAllowedServerInstances) { maxNumberOfServerInstances = 255; } var pinningHandle = new GCHandle(); try { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, ref pinningHandle); SafePipeHandle handle = Interop.Kernel32.CreateNamedPipe(fullPipeName, openMode, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref secAttrs); if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(); } InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0); } finally { if (pinningHandle.IsAllocated) { pinningHandle.Free(); } } }
private bool TryConnect(int timeout, CancellationToken cancellationToken) { Interop.mincore.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability); int _pipeFlags = (int)_pipeOptions; if (_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= Interop.mincore.SecurityOptions.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)_impersonationLevel - 1) << 16); } if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, timeout)) { int errorCode = Marshal.GetLastWin32Error(); // Server is not yet created if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { return(false); } // The timeout has expired. if (errorCode == Interop.mincore.Errors.ERROR_SUCCESS) { if (cancellationToken.CanBeCanceled) { // It may not be real timeout. return(false); } throw new TimeoutException(); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Pipe server should be free. Let's try to connect to it. int access = 0; if ((PipeDirection.In & _direction) != 0) { access |= Interop.mincore.GenericOperations.GENERIC_READ; } if ((PipeDirection.Out & _direction) != 0) { access |= Interop.mincore.GenericOperations.GENERIC_WRITE; } SafePipeHandle handle = Interop.mincore.CreateNamedPipeClient(_normalizedPipePath, access, // read and write access 0, // sharing: none ref secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags IntPtr.Zero); // template file: null if (handle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); // Handle the possible race condition of someone else connecting to the server // between our calls to WaitNamedPipe & CreateFile. if (errorCode == Interop.mincore.Errors.ERROR_PIPE_BUSY) { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Success! InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; return(true); }
private void ConnectInternal(int timeout, CancellationToken cancellationToken, int startTime) { Interop.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability); int _pipeFlags = (int)_pipeOptions; if (_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= Interop.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)_impersonationLevel - 1) << 16); } // This is the main connection loop. It will loop until the timeout expires. Most of the // time, we will be waiting in the WaitNamedPipe win32 blocking function; however, there are // cases when we will need to loop: 1) The server is not created (WaitNamedPipe returns // straight away in such cases), and 2) when another client connects to our server in between // our WaitNamedPipe and CreateFile calls. int elapsed = 0; do { // We want any other exception and and success to have priority over cancellation. cancellationToken.ThrowIfCancellationRequested(); // Wait for pipe to become free (this will block unless the pipe does not exist). int timeLeft = timeout - elapsed; int waitTime; if (cancellationToken.CanBeCanceled) { waitTime = Math.Min(CancellationCheckInterval, timeLeft); } else { waitTime = timeLeft; } if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, waitTime)) { int errorCode = Marshal.GetLastWin32Error(); // Server is not yet created so let's keep looping. if (errorCode == Interop.ERROR_FILE_NOT_FOUND) { continue; } // The timeout has expired. if (errorCode == Interop.ERROR_SUCCESS) { if (cancellationToken.CanBeCanceled) { // It may not be real timeout and only checking for cancellation // let the while condition check it and decide continue; } else { break; } } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Pipe server should be free. Let's try to connect to it. int access = 0; if ((PipeDirection.In & _direction) != 0) { access |= Interop.GENERIC_READ; } if ((PipeDirection.Out & _direction) != 0) { access |= Interop.GENERIC_WRITE; } SafePipeHandle handle = Interop.mincore.CreateNamedPipeClient(_normalizedPipePath, access, // read and write access 0, // sharing: none ref secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags Interop.NULL); // template file: null if (handle.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); // Handle the possible race condition of someone else connecting to the server // between our calls to WaitNamedPipe & CreateFile. if (errorCode == Interop.ERROR_PIPE_BUSY) { continue; } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Success! InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; return; }while (timeout == Timeout.Infinite || (elapsed = unchecked (Environment.TickCount - startTime)) < timeout); // BUGBUG: SerialPort does not use unchecked arithmetic when calculating elapsed times. This is needed // because Environment.TickCount can overflow (though only every 49.7 days). throw new TimeoutException(); }
// Waits for a pipe instance to become available. This method may return before WaitForConnection is called // on the server end, but WaitForConnection will not return until we have returned. Any data written to the // pipe by us after we have connected but before the server has called WaitForConnection will be available // to the server after it calls WaitForConnection. private bool TryConnect(int timeout, CancellationToken cancellationToken) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(_inheritability); // PipeOptions.CurrentUserOnly is special since it doesn't match directly to a corresponding Win32 valid flag. // Remove it, while keeping others untouched since historically this has been used as a way to pass flags to // CreateNamedPipeClient that were not defined in the enumeration. int _pipeFlags = (int)(_pipeOptions & ~PipeOptions.CurrentUserOnly); if (_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)_impersonationLevel - 1) << 16); } int access = 0; if ((PipeDirection.In & _direction) != 0) { access |= Interop.Kernel32.GenericOperations.GENERIC_READ; } if ((PipeDirection.Out & _direction) != 0) { access |= Interop.Kernel32.GenericOperations.GENERIC_WRITE; } SafePipeHandle handle = CreateNamedPipeClient(_normalizedPipePath, ref secAttrs, _pipeFlags, access); if (handle.IsInvalid) { int errorCode = Marshal.GetLastPInvokeError(); // CreateFileW: "If the CreateNamedPipe function was not successfully called on the server prior to this operation, // a pipe will not exist and CreateFile will fail with ERROR_FILE_NOT_FOUND" // WaitNamedPipeW: "If no instances of the specified named pipe exist, // the WaitNamedPipe function returns immediately, regardless of the time-out value." // We know that no instances exist, so we just quit without calling WaitNamedPipeW. if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND) { return(false); } if (errorCode != Interop.Errors.ERROR_PIPE_BUSY) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } if (!Interop.Kernel32.WaitNamedPipe(_normalizedPipePath, timeout)) { errorCode = Marshal.GetLastPInvokeError(); if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || // server has been closed errorCode == Interop.Errors.ERROR_SEM_TIMEOUT) { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // Pipe server should be free. Let's try to connect to it. handle = CreateNamedPipeClient(_normalizedPipePath, ref secAttrs, _pipeFlags, access); if (handle.IsInvalid) { errorCode = Marshal.GetLastPInvokeError(); // WaitNamedPipe: "A subsequent CreateFile call to the pipe can fail, // because the instance was closed by the server or opened by another client." if (errorCode == Interop.Errors.ERROR_PIPE_BUSY || // opened by another client errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND) // server has been closed { return(false); } throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } // Success! InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0); State = PipeState.Connected; ValidateRemotePipeUser(); return(true);