Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / IO / Pipes / Pipe.cs / 1305376 / Pipe.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Classes: AnonymousPipeServerStream ** AnonymousPipeClientStream ** NamedPipeServerStream ** NamedPipeClientStream ** ** Purpose: pipe stream classes. ** ** ===========================================================*/ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; namespace System.IO.Pipes { ////// Anonymous pipe server stream /// [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class AnonymousPipeServerStream : PipeStream { private SafePipeHandle m_clientHandle; private bool m_clientHandleExposed; [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream() : this(PipeDirection.Out, HandleInheritability.None, 0, null) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream(PipeDirection direction) : this(direction, HandleInheritability.None, 0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability) : this(direction, inheritability, 0) { } // bufferSize is used as a suggestion; specify 0 to let OS decide // This constructor instantiates the PipeSecurity using just the inheritability flag //// [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability, int bufferSize) : base(direction, bufferSize) { if (direction == PipeDirection.InOut) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable)); } UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability); Create(direction, secAttrs, bufferSize); } // bufferSize is used as a suggestion; specify 0 to let OS decide // pipeSecurity of null is default security descriptor //// // // [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream(PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) : base(direction, bufferSize) { if (direction == PipeDirection.InOut) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable)); } Object pinningHandle; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out pinningHandle); try { Create(direction, secAttrs, bufferSize); } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } } ~AnonymousPipeServerStream() { Dispose(false); } // Create an AnonymousPipeServerStream from two existing pipe handles. //// // // // [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeServerStream(PipeDirection direction, SafePipeHandle serverSafePipeHandle, SafePipeHandle clientSafePipeHandle) : base(direction, 0) { if (direction == PipeDirection.InOut) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional)); } if (serverSafePipeHandle == null) { throw new ArgumentNullException("serverSafePipeHandle"); } if (clientSafePipeHandle == null) { throw new ArgumentNullException("clientSafePipeHandle"); } if (serverSafePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "serverSafePipeHandle"); } if (clientSafePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "clientSafePipeHandle"); } // Check that these handles are in fact a handles to a pipe. if (UnsafeNativeMethods.GetFileType(serverSafePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) { throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle)); } if (UnsafeNativeMethods.GetFileType(clientSafePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) { throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle)); } InitializeHandle(serverSafePipeHandle, true, false); m_clientHandle = clientSafePipeHandle; m_clientHandleExposed = true; State = PipeState.Connected; } // This method should exist until we add a first class way of passing handles between parent and child // processes. For now, people do it via command line arguments. //// // // [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Reliability","CA2001:AvoidCallingProblematicMethods", MessageId="System.Runtime.InteropServices.SafeHandle.DangerousGetHandle", Justification="By design")] public String GetClientHandleAsString() { m_clientHandleExposed = true; return m_clientHandle.DangerousGetHandle().ToString(); } public SafePipeHandle ClientSafePipeHandle { //// // // [System.Security.SecurityCritical] get { m_clientHandleExposed = true; return m_clientHandle; } } // This method is an annoying one but it has to exist at least until we make passing handles between // processes first class. We need this because once the child handle is inherited, the OS considers // the parent and child's handles to be different. Therefore, if a child closes its handle, our // Read/Write methods won't throw because the OS will think that there is still a child handle around // that can still Write/Read to/from the other end of the pipe. // // Ideally, we would want the Process class to close this handle after it has been inherited. See // the pipe spec future features section for more information. // // Right now, this is the best signal to set the anonymous pipe as connected; if this is called, we // know the client has been passed the handle and so the connection is live. //// // [System.Security.SecurityCritical] public void DisposeLocalCopyOfClientHandle() { if (m_clientHandle != null && !m_clientHandle.IsClosed) { m_clientHandle.Dispose(); } } //// // // // [System.Security.SecurityCritical] protected override void Dispose(bool disposing) { try { // We should dispose of the client handle if it was not exposed. if (!m_clientHandleExposed && m_clientHandle != null && !m_clientHandle.IsClosed) { m_clientHandle.Dispose(); } } finally { base.Dispose(disposing); } } // Creates the anonymous pipe. //// // // // [System.Security.SecurityCritical] private void Create(PipeDirection direction, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs, int bufferSize) { 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. if (direction == PipeDirection.In) { bSuccess = UnsafeNativeMethods.CreatePipe(out serverHandle, out m_clientHandle, secAttrs, bufferSize); } else { bSuccess = UnsafeNativeMethods.CreatePipe(out m_clientHandle, out serverHandle, secAttrs, bufferSize); } if (!bSuccess) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // 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 = UnsafeNativeMethods.DuplicateHandle(UnsafeNativeMethods.GetCurrentProcess(), serverHandle, UnsafeNativeMethods.GetCurrentProcess(), out newServerHandle, 0, false, UnsafeNativeMethods.DUPLICATE_SAME_ACCESS); if (!bSuccess) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // Close the inheritable server handle. serverHandle.Dispose(); InitializeHandle(newServerHandle, false, false); State = PipeState.Connected; } // Anonymous pipes do not support message mode so there is no need to use the base version that P/Invokes here. public override PipeTransmissionMode TransmissionMode { [System.Security.SecurityCritical] get { return PipeTransmissionMode.Byte; } } public override PipeTransmissionMode ReadMode { //// // // // // // // // [System.Security.SecurityCritical] set { CheckPipePropertyOperations(); if (value < PipeTransmissionMode.Byte || value > PipeTransmissionMode.Message) { throw new ArgumentOutOfRangeException("value", SR.GetString(SR.ArgumentOutOfRange_TransmissionModeByteOrMsg)); } if (value == PipeTransmissionMode.Message) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeMessagesNotSupported)); } } } } ///// /// Anonymous pipe client. Use this to open the client end of an anonymous pipes created with AnonymousPipeServerStream. /// [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class AnonymousPipeClientStream : PipeStream { [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] [SuppressMessage("Microsoft.Naming","CA1720:IdentifiersShouldNotContainTypeNames", MessageId="string", Justification="By design")] public AnonymousPipeClientStream(String pipeHandleAsString) : this(PipeDirection.In, pipeHandleAsString) { } //// [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] [SuppressMessage("Microsoft.Naming","CA1720:IdentifiersShouldNotContainTypeNames", MessageId="string", Justification="By design")] public AnonymousPipeClientStream(PipeDirection direction, String pipeHandleAsString) : base(direction, 0) { if (direction == PipeDirection.InOut) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional)); } if (pipeHandleAsString == null) { throw new ArgumentNullException("pipeHandleAsString"); } // Initialize SafePipeHandle from String and check if it's valid. First see if it's parseable long result = 0; bool parseable = long.TryParse(pipeHandleAsString, out result); if (!parseable) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "pipeHandleAsString"); } // next check whether the handle is invalid SafePipeHandle safePipeHandle = new SafePipeHandle((IntPtr)result, true); if (safePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "pipeHandleAsString"); } Init(direction, safePipeHandle); } [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public AnonymousPipeClientStream(PipeDirection direction, SafePipeHandle safePipeHandle) : base(direction, 0) { if (direction == PipeDirection.InOut) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeUnidirectional)); } if (safePipeHandle == null) { throw new ArgumentNullException("safePipeHandle"); } if (safePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "safePipeHandle"); } Init(direction, safePipeHandle); } //// // [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] private void Init(PipeDirection direction, SafePipeHandle safePipeHandle) { Debug.Assert(direction != PipeDirection.InOut, "anonymous pipes are unidirectional, caller should have verified before calling Init"); Debug.Assert(safePipeHandle != null && !safePipeHandle.IsInvalid, "safePipeHandle must be valid"); // Check that this handle is infact a handle to a pipe. if (UnsafeNativeMethods.GetFileType(safePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) { throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle)); } InitializeHandle(safePipeHandle, true, false); State = PipeState.Connected; } ~AnonymousPipeClientStream() { Dispose(false); } // Anonymous pipes do not support message readmode so there is no need to use the base version // which P/Invokes (and sometimes fails). public override PipeTransmissionMode TransmissionMode { [System.Security.SecurityCritical] get { return PipeTransmissionMode.Byte; } } public override PipeTransmissionMode ReadMode { //// // [System.Security.SecurityCritical] set { CheckPipePropertyOperations(); if (value < PipeTransmissionMode.Byte || value > PipeTransmissionMode.Message) { throw new ArgumentOutOfRangeException("value", SR.GetString(SR.ArgumentOutOfRange_TransmissionModeByteOrMsg)); } if (value == PipeTransmissionMode.Message) { throw new NotSupportedException(SR.GetString(SR.NotSupported_AnonymousPipeMessagesNotSupported)); } } } } // Users will use this delegate to specify a method to call while impersonating the client // (see NamedPipeServerStream.RunAsClient). public delegate void PipeStreamImpersonationWorker(); ///// /// Named pipe server /// [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class NamedPipeServerStream : PipeStream { // Use the maximum number of server instances that the system resources allow public const int MaxAllowedServerInstances = -1; // Max username length (in Windows Server 2003) private static int s_maxUsernameLength = 20; private unsafe static readonly IOCompletionCallback WaitForConnectionCallback = new IOCompletionCallback(NamedPipeServerStream.AsyncWaitForConnectionCallback); //// [System.Security.SecurityCritical] static NamedPipeServerStream() { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName) : this(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction) : this(pipeName, direction, 1, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances) : this(pipeName, direction, maxNumberOfServerInstances, PipeTransmissionMode.Byte, PipeOptions.None, 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode) : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, PipeOptions.None, 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options) : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, 0, 0, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize) : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, null, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity) : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity, HandleInheritability.None, (PipeAccessRights)0) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(String pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability) : this(pipeName, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, pipeSecurity, inheritability, (PipeAccessRights)0) { } ///// // // /// Full named pipe server constructor /// /// Pipe name /// Pipe direction: In, Out or InOut (duplex). /// Win32 note: this gets OR'd into dwOpenMode to CreateNamedPipe /// /// Maximum number of server instances. Specify a fixed value between /// 1 and 254, or use NamedPipeServerStream.MaxAllowedServerInstances to use the maximum amount allowed by /// system resources. /// Byte mode or message mode. /// Win32 note: this gets used for dwPipeMode. CreateNamedPipe allows you to specify PIPE_TYPE_BYTE/MESSAGE /// and PIPE_READMODE_BYTE/MESSAGE independently, but this sets type and readmode to match. /// /// PipeOption enum: None, Asynchronous, or Writethrough /// Win32 note: this gets passed in with dwOpenMode to CreateNamedPipe. Asynchronous corresponds to /// FILE_FLAG_OVERLAPPED option. PipeOptions enum doesn't expose FIRST_PIPE_INSTANCE option because /// this sets that automatically based on the number of instances specified. /// /// Incoming buffer size, 0 or higher. /// Note: this size is always advisory; OS uses a suggestion. /// /// Outgoing buffer size, 0 or higher (see above) /// PipeSecurity, or null for default security descriptor /// Whether handle is inheritable /// Combination (logical OR) of PipeAccessRights.TakeOwnership, /// PipeAccessRights.AccessSystemSecurity, and PipeAccessRights.ChangePermissions //// [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 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(SR.GetString(SR.Argument_NeedNonemptyPipeName)); } if ((options & ~(PipeOptions.WriteThrough | PipeOptions.Asynchronous)) != 0) { throw new ArgumentOutOfRangeException("options", SR.GetString(SR.ArgumentOutOfRange_OptionsInvalid)); } if (inBufferSize < 0) { throw new ArgumentOutOfRangeException("inBufferSize", SR.GetString(SR.ArgumentOutOfRange_NeedNonNegNum)); } // win32 allows fixed values of 1-254 or 255 to mean max allowed by system. We expose 255 as -1 (unlimited) // through the MaxAllowedServerInstances constant. This is consistent e.g. with -1 as infinite timeout, etc if ((maxNumberOfServerInstances < 1 || maxNumberOfServerInstances > 254) && (maxNumberOfServerInstances != MaxAllowedServerInstances)) { throw new ArgumentOutOfRangeException("maxNumberOfServerInstances", SR.GetString(SR.ArgumentOutOfRange_MaxNumServerInstances)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable)); } // ChangePermissions, TakeOwnership, and AccessSystemSecurity are only legal values user may provide; // internally this is set to 0 if not provided. This handles both cases. if ((additionalAccessRights & ~(PipeAccessRights.ChangePermissions | PipeAccessRights.TakeOwnership | PipeAccessRights.AccessSystemSecurity)) != 0) { throw new ArgumentOutOfRangeException("additionalAccessRights", SR.GetString(SR.ArgumentOutOfRange_AdditionalAccessLimited)); } // Named Pipe Servers require Windows NT if (Environment.OSVersion.Platform == PlatformID.Win32Windows) { throw new PlatformNotSupportedException(SR.GetString(SR.PlatformNotSupported_NamedPipeServers)); } string normalizedPipePath = Path.GetFullPath(@"\\.\pipe\" + pipeName); // Make sure the pipe name isn't one of our reserved names for anonymous pipes. if (String.Compare(normalizedPipePath, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase) == 0) { throw new ArgumentOutOfRangeException("pipeName", SR.GetString(SR.ArgumentOutOfRange_AnonymousReserved)); } Object pinningHandle = null; UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(inheritability, pipeSecurity, out pinningHandle); try { Create(normalizedPipePath, direction, maxNumberOfServerInstances, transmissionMode, options, inBufferSize, outBufferSize, additionalAccessRights, secAttrs); } finally { if (pinningHandle != null) { GCHandle pinHandle = (GCHandle)pinningHandle; pinHandle.Free(); } } } // Create a NamedPipeServerStream from an existing server pipe handle. //// // // // [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeServerStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) : base(direction, PipeTransmissionMode.Byte, 0) { if (safePipeHandle == null) { throw new ArgumentNullException("safePipeHandle"); } if (safePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "safePipeHandle"); } // Check that this handle is infact a handle to a pipe. if (UnsafeNativeMethods.GetFileType(safePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) { throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle)); } InitializeHandle(safePipeHandle, true, isAsync); if (isConnected) { State = PipeState.Connected; } } ~NamedPipeServerStream() { Dispose(false); } //// // [System.Security.SecurityCritical] private void Create(String fullPipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize, PipeAccessRights rights, UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs) { Debug.Assert(fullPipeName != null && fullPipeName.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"); int openMode = ((int)direction) | (maxNumberOfServerInstances == 1 ? UnsafeNativeMethods.FILE_FLAG_FIRST_PIPE_INSTANCE : 0) | (int)options | (int)rights; // 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; } SafePipeHandle handle = UnsafeNativeMethods.CreateNamedPipe(fullPipeName, openMode, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, secAttrs); if (handle.IsInvalid) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } InitializeHandle(handle, false, (options & PipeOptions.Asynchronous) != 0); } // This will wait until the client calls Connect(). If we return from this method, we guarantee that // the client has returned from its Connect call. The client may have done so before this method // was called (but not before this server is been created, or, if we were servicing another client, // not before we called Disconnect), in which case, there may be some buffer already in the pipe waiting // for us to read. See NamedPipeClientStream.Connect for more information. //// // // // // [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Security model of pipes: demand at creation but no subsequent demands")] public void WaitForConnection() { CheckConnectOperationsServer(); if (IsAsync) { IAsyncResult result = BeginWaitForConnection(null, null); EndWaitForConnection(result); } else { if (!UnsafeNativeMethods.ConnectNamedPipe(InternalHandle, UnsafeNativeMethods.NULL)) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode != UnsafeNativeMethods.ERROR_PIPE_CONNECTED) { __Error.WinIOError(errorCode, String.Empty); } // pipe already connected if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED && State == PipeState.Connected) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected)); } // If we reach here then a connection has been established. This can happen if a client // connects in the interval between the call to CreateNamedPipe and the call to ConnectNamedPipe. // In this situation, there is still a good connection between client and server, even though // ConnectNamedPipe returns zero. } State = PipeState.Connected; } } // Async version of WaitForConnection. See the comments above for more info. //// // // // // // [System.Security.SecurityCritical] [HostProtection(ExternalThreading = true)] public unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state) { CheckConnectOperationsServer(); if (!IsAsync) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotAsync)); } // Create and store async stream class library specific data in the // async result PipeAsyncResult asyncResult = new PipeAsyncResult(); asyncResult._handle = InternalHandle; asyncResult._userCallback = callback; asyncResult._userStateObject = state; // Create wait handle and store in async result ManualResetEvent waitHandle = new ManualResetEvent(false); asyncResult._waitHandle = waitHandle; // Create a managed overlapped class // We will set the file offsets later Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, asyncResult); // Pack the Overlapped class, and store it in the async result NativeOverlapped* intOverlapped = overlapped.Pack(WaitForConnectionCallback, null); asyncResult._overlapped = intOverlapped; if (!UnsafeNativeMethods.ConnectNamedPipe(InternalHandle, intOverlapped)) { int errorCode = Marshal.GetLastWin32Error(); // Did the client already connect to us? if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED) { // If so, our WaitForConnectionCallback will not be called, so we clear the overlapped // status bit (failure to do so looks like we are freeing a pending overlapped // later), and call the user's callback. intOverlapped->InternalLow = IntPtr.Zero; if (State == PipeState.Connected) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected)); } asyncResult.CallUserCallback(); } else if (errorCode != UnsafeNativeMethods.ERROR_IO_PENDING) { __Error.WinIOError(errorCode, String.Empty); } } // will set state to Connected when EndWait is called return asyncResult; } // Async version of WaitForConnection. See comments for WaitForConnection for more info. //// // // // // // // // // // // [System.Security.SecurityCritical] public unsafe void EndWaitForConnection(IAsyncResult asyncResult) { CheckConnectOperationsServer(); if (asyncResult == null) { throw new ArgumentNullException("asyncResult"); } if (!IsAsync) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotAsync)); } PipeAsyncResult afsar = asyncResult as PipeAsyncResult; if (afsar == null) { __Error.WrongAsyncResult(); } // Ensure we can't get into any ----s by doing an interlocked // CompareExchange here. Avoids corrupting memory via freeing the // NativeOverlapped class or GCHandle twice. -- if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0)) { __Error.EndWaitForConnectionCalledTwice(); } // Obtain the WaitHandle, but don't use public property in case we // delay initialize the manual reset event in the future. WaitHandle wh = afsar._waitHandle; if (wh != null) { // We must block to ensure that ConnectionIOCallback has completed, // and we should close the WaitHandle in here. AsyncFSCallback // and the hand-ported imitation version in COMThreadPool.cpp // are the only places that set this event. try { wh.WaitOne(); Debug.Assert(afsar._isComplete == true, "NamedPipeServerStream::EndWaitForConnection - AsyncFSCallback didn't set _isComplete to true!"); } finally { wh.Close(); } } // Free memory & GC handles. NativeOverlapped* overlappedPtr = afsar._overlapped; if (overlappedPtr != null) { Overlapped.Free(overlappedPtr); } // Now check for any error during the read. if (afsar._errorCode != 0) { __Error.WinIOError(afsar._errorCode, String.Empty); } // Success State = PipeState.Connected; } //// // // // // [System.Security.SecurityCritical] public void Disconnect() { CheckDisconnectOperations(); // Disconnect the pipe. if (!UnsafeNativeMethods.DisconnectNamedPipe(InternalHandle)) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } State = PipeState.Disconnected; } // This method calls a delegate while impersonating the client. Note that we will not have // access to the client's security token until it has written at least once to the pipe // (and has set its impersonationLevel argument appropriately). //// // // // // // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)] public void RunAsClient(PipeStreamImpersonationWorker impersonationWorker) { CheckWriteOperations(); ExecuteHelper execHelper = new ExecuteHelper(impersonationWorker, InternalHandle); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, execHelper); // now handle win32 impersonate/revert specific errors by throwing corresponding exceptions if (execHelper.m_impersonateErrorCode != 0) { WinIOError(execHelper.m_impersonateErrorCode); } else if (execHelper.m_revertImpersonateErrorCode != 0) { WinIOError(execHelper.m_revertImpersonateErrorCode); } } // the following are needed for CER private static RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(ImpersonateAndTryCode); private static RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(RevertImpersonationOnBackout); //// // // // // [System.Security.SecurityCritical] private static void ImpersonateAndTryCode(Object helper) { ExecuteHelper execHelper = (ExecuteHelper)helper; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (UnsafeNativeMethods.ImpersonateNamedPipeClient(execHelper.m_handle)) { execHelper.m_mustRevert = true; } else { execHelper.m_impersonateErrorCode = Marshal.GetLastWin32Error(); } } if (execHelper.m_mustRevert) { // impersonate passed so run user code execHelper.m_userCode(); } } //// // // // // [System.Security.SecurityCritical] [PrePrepareMethod] private static void RevertImpersonationOnBackout(Object helper, bool exceptionThrown) { ExecuteHelper execHelper = (ExecuteHelper)helper; if (execHelper.m_mustRevert) { if (!UnsafeNativeMethods.RevertToSelf()) { execHelper.m_revertImpersonateErrorCode = Marshal.GetLastWin32Error(); } } } internal class ExecuteHelper { internal PipeStreamImpersonationWorker m_userCode; internal SafePipeHandle m_handle; internal bool m_mustRevert; internal int m_impersonateErrorCode; internal int m_revertImpersonateErrorCode; //// // // [System.Security.SecurityCritical] internal ExecuteHelper(PipeStreamImpersonationWorker userCode, SafePipeHandle handle) { m_userCode = userCode; m_handle = handle; } } // Gets the username of the connected client. Not that we will not have access to the client's // username until it has written at least once to the pipe (and has set its impersonationLevel // argument appropriately). //// // [System.Security.SecurityCritical] [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPrincipal)] public String GetImpersonationUserName() { CheckWriteOperations(); StringBuilder userName = new StringBuilder(s_maxUsernameLength); if (!UnsafeNativeMethods.GetNamedPipeHandleState(InternalHandle, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, userName, s_maxUsernameLength)) { WinIOError(Marshal.GetLastWin32Error()); } return userName.ToString(); } // Callback to be called by the OS when completing the async WaitForConnection operation. //// // // // // [System.Security.SecurityCritical] unsafe private static void AsyncWaitForConnectionCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) { // Unpack overlapped Overlapped overlapped = Overlapped.Unpack(pOverlapped); // Extract async result from overlapped PipeAsyncResult asyncResult = (PipeAsyncResult)overlapped.AsyncResult; // Special case for when the client has already connected to us. if (errorCode == UnsafeNativeMethods.ERROR_PIPE_CONNECTED) { errorCode = 0; } asyncResult._errorCode = (int)errorCode; // Call the user-provided callback. It can and often should // call EndWaitForCommection. There's no reason to use an async // delegate here - we're already on a threadpool thread. // IAsyncResult's completedSynchronously property must return // false here, saying the user callback was called on another thread. asyncResult._completedSynchronously = false; asyncResult._isComplete = true; // The OS does not signal this event. We must do it ourselves. ManualResetEvent wh = asyncResult._waitHandle; if (wh != null) { Debug.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!"); bool r = wh.Set(); Debug.Assert(r, "ManualResetEvent::Set failed!"); if (!r) { __Error.WinIOError(); } } AsyncCallback userCallback = asyncResult._userCallback; if (userCallback != null) { userCallback(asyncResult); } } // Server can only connect from Disconnected state //// // // // // [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Consistent with security model")] private void CheckConnectOperationsServer() { // we're not checking whether already connected; this allows us to throw IOException // "pipe is being closed" if other side is closing (as does win32) or no-op if // already connected if (InternalHandle == null) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeHandleNotSet)); } // object disposed if (State == PipeState.Closed) { __Error.PipeNotOpen(); } if (InternalHandle.IsClosed) { __Error.PipeNotOpen(); } // IOException if (State == PipeState.Broken) { throw new IOException(SR.GetString(SR.IO_IO_PipeBroken)); } } // Server is allowed to disconnect from connected and broken states //// // // [System.Security.SecurityCritical] private void CheckDisconnectOperations() { // invalid operation if (State== PipeState.WaitingToConnect) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotYetConnected)); } if (State == PipeState.Disconnected) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyDisconnected)); } if (InternalHandle == null) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeHandleNotSet)); } // object disposed if (State == PipeState.Closed) { __Error.PipeNotOpen(); } if (InternalHandle.IsClosed) { __Error.PipeNotOpen(); } } } // Named pipe client. Use this to open the client end of a named pipes created with // NamedPipeServerStream. [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class NamedPipeClientStream : PipeStream { private string m_normalizedPipePath; private TokenImpersonationLevel m_impersonationLevel; private PipeOptions m_pipeOptions; private HandleInheritability m_inheritability; private int m_access; // Creates a named pipe client using default server (same machine, or "."), and PipeDirection.InOut [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String pipeName) : this(".", pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName) : this(serverName, pipeName, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction) : this(serverName, pipeName, direction, PipeOptions.None, TokenImpersonationLevel.None, HandleInheritability.None) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction, PipeOptions options) : this(serverName, pipeName, direction, options, TokenImpersonationLevel.None, HandleInheritability.None) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel) : this(serverName, pipeName, direction, options, impersonationLevel, HandleInheritability.None) { } [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName, PipeDirection direction, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability) : base(direction, 0) { if (pipeName == null) { throw new ArgumentNullException("pipeName"); } if (serverName == null) { throw new ArgumentNullException("serverName", SR.GetString(SR.ArgumentNull_ServerName)); } if (pipeName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_NeedNonemptyPipeName)); } if (serverName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_EmptyServerName)); } if ((options & ~(PipeOptions.WriteThrough | PipeOptions.Asynchronous)) != 0) { throw new ArgumentOutOfRangeException("options", SR.GetString(SR.ArgumentOutOfRange_OptionsInvalid)); } if (impersonationLevel < TokenImpersonationLevel.None || impersonationLevel > TokenImpersonationLevel.Delegation) { throw new ArgumentOutOfRangeException("impersonationLevel", SR.GetString(SR.ArgumentOutOfRange_ImpersonationInvalid)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable)); } m_normalizedPipePath = Path.GetFullPath(@"\\" + serverName + @"\pipe\" + pipeName); if (String.Compare(m_normalizedPipePath, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase) == 0) { throw new ArgumentOutOfRangeException("pipeName", SR.GetString(SR.ArgumentOutOfRange_AnonymousReserved)); } m_inheritability = inheritability; m_impersonationLevel = impersonationLevel; m_pipeOptions = options; if ((PipeDirection.In & direction) != 0) { m_access |= UnsafeNativeMethods.GENERIC_READ; } if ((PipeDirection.Out & direction) != 0) { m_access |= UnsafeNativeMethods.GENERIC_WRITE; } } // This constructor is for advanced users that want to specify their PipeAccessRights explcitly. It can be used // to open pipes with, for example, WritePermissions access in the case that they want to play with the pipe's // ACL. [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(String serverName, String pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, TokenImpersonationLevel impersonationLevel, HandleInheritability inheritability) : base(DirectionFromRights(desiredAccessRights), 0) { if (pipeName == null) { throw new ArgumentNullException("pipeName"); } if (serverName == null) { throw new ArgumentNullException("serverName", SR.GetString(SR.ArgumentNull_ServerName)); } if (pipeName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_NeedNonemptyPipeName)); } if (serverName.Length == 0) { throw new ArgumentException(SR.GetString(SR.Argument_EmptyServerName)); } if ((options & ~(PipeOptions.WriteThrough | PipeOptions.Asynchronous)) != 0) { throw new ArgumentOutOfRangeException("options", SR.GetString(SR.ArgumentOutOfRange_OptionsInvalid)); } if (impersonationLevel < TokenImpersonationLevel.None || impersonationLevel > TokenImpersonationLevel.Delegation) { throw new ArgumentOutOfRangeException("impersonationLevel", SR.GetString(SR.ArgumentOutOfRange_ImpersonationInvalid)); } if (inheritability < HandleInheritability.None || inheritability > HandleInheritability.Inheritable) { throw new ArgumentOutOfRangeException("inheritability", SR.GetString(SR.ArgumentOutOfRange_HandleInheritabilityNoneOrInheritable)); } if ((desiredAccessRights & ~(PipeAccessRights.FullControl | PipeAccessRights.AccessSystemSecurity)) != 0) { throw new ArgumentOutOfRangeException("desiredAccessRights", SR.GetString(SR.ArgumentOutOfRange_InvalidPipeAccessRights)); } m_normalizedPipePath = Path.GetFullPath(@"\\" + serverName + @"\pipe\" + pipeName); if (String.Compare(m_normalizedPipePath, @"\\.\pipe\anonymous", StringComparison.OrdinalIgnoreCase) == 0) { throw new ArgumentOutOfRangeException("pipeName", SR.GetString(SR.ArgumentOutOfRange_AnonymousReserved)); } m_inheritability = inheritability; m_impersonationLevel = impersonationLevel; m_pipeOptions = options; m_access = (int)desiredAccessRights; } // Helper method for the constructor above. The PipeStream protected constructor takes in a PipeDirection so we need // to convert the access rights to a direction. Usually, PipeDirection.In/Out maps to GENERIC_READ/WRITE but in the // other direction, READ/WRITE_DATA is sufficient. private static PipeDirection DirectionFromRights(PipeAccessRights rights) { PipeDirection direction = 0; if ((rights & PipeAccessRights.ReadData) != 0) { direction |= PipeDirection.In; } if ((rights & PipeAccessRights.WriteData) != 0) { direction |= PipeDirection.Out; } return direction; } // Create a NamedPipeClientStream from an existing server pipe handle. //// // // [System.Security.SecurityCritical] [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) : base(direction, 0) { if (safePipeHandle == null) { throw new ArgumentNullException("safePipeHandle"); } if (safePipeHandle.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Argument_InvalidHandle), "safePipeHandle"); } // Check that this handle is infact a handle to a pipe. if (UnsafeNativeMethods.GetFileType(safePipeHandle) != UnsafeNativeMethods.FILE_TYPE_PIPE) { throw new IOException(SR.GetString(SR.IO_IO_InvalidPipeHandle)); } InitializeHandle(safePipeHandle, true, isAsync); if (isConnected) { State = PipeState.Connected; } } ~NamedPipeClientStream() { Dispose(false); } // See below public void Connect() { Connect(Timeout.Infinite); } // 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 writen 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. //// // [System.Security.SecurityCritical] public void Connect(int timeout) { CheckConnectOperationsClient(); if (timeout < 0 && timeout != Timeout.Infinite) { throw new ArgumentOutOfRangeException("timeout", SR.GetString(SR.ArgumentOutOfRange_InvalidTimeout)); } UnsafeNativeMethods.SECURITY_ATTRIBUTES secAttrs = PipeStream.GetSecAttrs(m_inheritability); int _pipeFlags = (int)m_pipeOptions; if (m_impersonationLevel != TokenImpersonationLevel.None) { _pipeFlags |= UnsafeNativeMethods.SECURITY_SQOS_PRESENT; _pipeFlags |= (((int)m_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 startTime = Environment.TickCount; int elapsed = 0; do { // Wait for pipe to become free (this will block unless the pipe does not exist). if (!UnsafeNativeMethods.WaitNamedPipe(m_normalizedPipePath, timeout - elapsed)) { int errorCode = Marshal.GetLastWin32Error(); // Server is not yet created so let's keep looping. if (errorCode == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) { continue; } // The timeout has expired. if (errorCode == UnsafeNativeMethods.ERROR_SUCCESS) { break; } __Error.WinIOError(errorCode, String.Empty); } // Pipe server should be free. Let's try to connect to it. SafePipeHandle handle = UnsafeNativeMethods.CreateNamedPipeClient(m_normalizedPipePath, m_access, // read and write access 0, // sharing: none secAttrs, // security attributes FileMode.Open, // open existing _pipeFlags, // impersonation flags UnsafeNativeMethods.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 == UnsafeNativeMethods.ERROR_PIPE_BUSY) { continue; } __Error.WinIOError(errorCode, String.Empty); } // Success! InitializeHandle(handle, false, (m_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(); } public int NumberOfServerInstances { //// // // // // // // [System.Security.SecurityCritical] [SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Security model of pipes: demand at creation but no subsequent demands")] get { CheckPipePropertyOperations(); // NOTE: MSDN says that GetNamedPipeHandleState requires that the pipe handle has // GENERIC_READ access, but we don't check for that because sometimes it works without // GERERIC_READ access. [Edit: Seems like CreateFile slaps on a READ_ATTRIBUTES // access request before calling NTCreateFile, so all NamedPipeClientStreams can read // this if they are created (on WinXP SP2 at least)] int numInstances; if (!UnsafeNativeMethods.GetNamedPipeHandleState(InternalHandle, UnsafeNativeMethods.NULL, out numInstances, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, UnsafeNativeMethods.NULL, 0)) { WinIOError(Marshal.GetLastWin32Error()); } return numInstances; } } // override because named pipe clients can't get/set properties when waiting to connect // or broken //// // // // // [System.Security.SecurityCritical] protected override internal void CheckPipePropertyOperations() { base.CheckPipePropertyOperations(); // Invalid operation if (State == PipeState.WaitingToConnect) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeNotYetConnected)); } // IOException if (State == PipeState.Broken) { throw new IOException(SR.GetString(SR.IO_IO_PipeBroken)); } } // named client is allowed to connect from broken private void CheckConnectOperationsClient() { if (State == PipeState.Connected) { throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_PipeAlreadyConnected)); } if (State == PipeState.Closed) { __Error.PipeNotOpen(); } } } [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust"), PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")] unsafe internal sealed class PipeAsyncResult : IAsyncResult { internal AsyncCallback _userCallback; // User code callback internal Object _userStateObject; internal ManualResetEvent _waitHandle; internal SafePipeHandle _handle; internal NativeOverlapped* _overlapped; internal int _EndXxxCalled; // Whether we've called EndXxx already. internal int _errorCode; internal bool _isComplete; // Value for IsCompleted property internal bool _completedSynchronously; // Which thread called callback public Object AsyncState { get { return _userStateObject; } } public bool IsCompleted { get { return _isComplete; } } public WaitHandle AsyncWaitHandle { //// // [System.Security.SecurityCritical] get { if (_waitHandle == null) { ManualResetEvent mre = new ManualResetEvent(false); if (_overlapped != null && _overlapped->EventHandle != IntPtr.Zero) { mre.SafeWaitHandle = new SafeWaitHandle(_overlapped->EventHandle, true); } if (_isComplete) { mre.Set(); } _waitHandle = mre; } return _waitHandle; } } public bool CompletedSynchronously { get { return _completedSynchronously; } } private void CallUserCallbackWorker(Object callbackState) { _isComplete = true; if (_waitHandle != null) { _waitHandle.Set(); } _userCallback(this); } internal void CallUserCallback() { if (_userCallback != null) { _completedSynchronously = false; ThreadPool.QueueUserWorkItem(new WaitCallback(CallUserCallbackWorker)); } else { _isComplete = true; if (_waitHandle != null) { _waitHandle.Set(); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.// // //
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- GridViewCellAutomationPeer.cs
- KeyValueSerializer.cs
- AdornedElementPlaceholder.cs
- ImageFormatConverter.cs
- TranslateTransform3D.cs
- Misc.cs
- DesignerHelpers.cs
- DataReaderContainer.cs
- ProxyAttribute.cs
- Queue.cs
- TypeDefinition.cs
- TextEmbeddedObject.cs
- SpoolingTask.cs
- CollectionViewSource.cs
- ItemContainerPattern.cs
- GetPageCompletedEventArgs.cs
- DependsOnAttribute.cs
- XmlSchemaExporter.cs
- SessionEndingEventArgs.cs
- CodeExporter.cs
- ClientSideProviderDescription.cs
- DataSourceCacheDurationConverter.cs
- WebPartCancelEventArgs.cs
- TypeReference.cs
- XmlSerializerAssemblyAttribute.cs
- ChildDocumentBlock.cs
- KeySpline.cs
- ContentControl.cs
- ObjectDataSourceDisposingEventArgs.cs
- DataColumnChangeEvent.cs
- RadioButtonList.cs
- _DigestClient.cs
- MembershipUser.cs
- FontFamily.cs
- EndOfStreamException.cs
- TargetParameterCountException.cs
- X509Certificate2Collection.cs
- basevalidator.cs
- ToolStripSplitButton.cs
- Attribute.cs
- ModifyActivitiesPropertyDescriptor.cs
- SQLSingleStorage.cs
- CodeDOMUtility.cs
- DataGridViewImageColumn.cs
- CrossAppDomainChannel.cs
- HtmlLink.cs
- BitmapFrame.cs
- MsmqIntegrationBindingElement.cs
- LinqDataSourceEditData.cs
- MailWebEventProvider.cs
- QueueProcessor.cs
- ResizeGrip.cs
- SmiRequestExecutor.cs
- ConfigXmlText.cs
- InvalidateEvent.cs
- EqualityArray.cs
- SymLanguageVendor.cs
- Type.cs
- MiniLockedBorderGlyph.cs
- WebBrowserHelper.cs
- OptimizedTemplateContentHelper.cs
- RuntimeConfigLKG.cs
- GridViewRowEventArgs.cs
- SoapHeaderAttribute.cs
- PackWebRequestFactory.cs
- storepermission.cs
- XmlSchemaDocumentation.cs
- Configuration.cs
- NonClientArea.cs
- FunctionQuery.cs
- MatrixAnimationUsingKeyFrames.cs
- SessionStateContainer.cs
- NavigatingCancelEventArgs.cs
- ComProxy.cs
- StringAnimationBase.cs
- Single.cs
- DesignerDataSourceView.cs
- WebServicesInteroperability.cs
- DataTablePropertyDescriptor.cs
- HttpModuleAction.cs
- GeometryCombineModeValidation.cs
- LeafCellTreeNode.cs
- RSAOAEPKeyExchangeFormatter.cs
- LightweightCodeGenerator.cs
- DataExpression.cs
- SessionEndingCancelEventArgs.cs
- CharUnicodeInfo.cs
- Scene3D.cs
- HostingEnvironment.cs
- Int64AnimationUsingKeyFrames.cs
- FontNamesConverter.cs
- MergePropertyDescriptor.cs
- MatrixValueSerializer.cs
- ListViewDeletedEventArgs.cs
- TableLayoutStyle.cs
- MultipleCopiesCollection.cs
- FileDialog_Vista_Interop.cs
- XmlTextEncoder.cs
- WebControl.cs
- StructuralObject.cs