示例#1
0
        // This overload is used in Mono to implement public constructors.
        private void Create(string pipeName, PipeDirection direction, int maxNumberOfServerInstances,
                            PipeTransmissionMode transmissionMode, PipeOptions options, int inBufferSize, int outBufferSize,
                            PipeSecurity pipeSecurity, HandleInheritability inheritability, PipeAccessRights additionalAccessRights)
        {
            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);
            }

            if (IsCurrentUserOnly)
            {
                Debug.Assert(pipeSecurity == null);

                using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent())
                {
                    SecurityIdentifier identifier = currentIdentity.Owner;

                    // Grant full control to the owner so multiple servers can be opened.
                    // Full control is the default per MSDN docs for CreateNamedPipe.
                    PipeAccessRule rule = new PipeAccessRule(identifier, PipeAccessRights.FullControl, 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 |
                           (int)additionalAccessRights;

            // 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();
                }
            }
        }
示例#2
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);
        }
示例#3
0
 public void Disconnect()
 {
     Win32Marshal.DisconnectNamedPipe(Handle);
 }
示例#4
0
        unsafe private PipeStreamAsyncResult BeginReadCore(byte[] buffer, int offset, int count,
                                                           AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanRead, "can't read");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

            // Create and store async stream class library specific data in the async result
            PipeStreamAsyncResult asyncResult = new PipeStreamAsyncResult();

            asyncResult._handle          = _handle;
            asyncResult._userCallback    = callback;
            asyncResult._userStateObject = state;
            asyncResult._isWrite         = false;

            // handle zero-length buffers separately; fixed keyword ReadFileNative doesn't like
            // 0-length buffers. Call user callback and we're done
            if (buffer.Length == 0)
            {
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback and using
                // the managed Monitor class, or I could create a handle and wait on it.
                ManualResetEvent waitHandle = new ManualResetEvent(false);
                asyncResult._waitHandle = waitHandle;

                // Create a managed overlapped class; set the file offsets later
                Overlapped overlapped = new Overlapped();
                overlapped.OffsetLow   = 0;
                overlapped.OffsetHigh  = 0;
                overlapped.AsyncResult = asyncResult;

                // Pack the Overlapped class, and store it in the async result
                NativeOverlapped *intOverlapped;
                intOverlapped = overlapped.Pack(s_IOCallback, buffer);


                asyncResult._overlapped = intOverlapped;

                // Queue an async ReadFile operation and pass in a packed overlapped
                int errorCode = 0;
                int r         = ReadFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper
                // returns -1. This will return the following:
                // - On error, r==-1.
                // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
                // - On async requests that completed sequentially, r==0
                //
                // You will NEVER RELIABLY be able to get the number of buffer read back from this call
                // when using overlapped structures!  You must not pass in a non-null lpNumBytesRead to
                // ReadFile when using overlapped structures!  This is by design NT behavior.
                if (r == -1)
                {
                    // One side has closed its handle or server disconnected. Set the state to Broken
                    // and do some cleanup work
                    if (errorCode == Interop.ERROR_BROKEN_PIPE ||
                        errorCode == Interop.ERROR_PIPE_NOT_CONNECTED)
                    {
                        State = PipeState.Broken;

                        // Clear the overlapped status bit for this special case. Failure to do so looks
                        // like we are freeing a pending overlapped.
                        intOverlapped->InternalLow = IntPtr.Zero;

                        // EndRead will free the Overlapped struct
                        asyncResult.CallUserCallback();
                    }
                    else if (errorCode != Interop.ERROR_IO_PENDING)
                    {
                        throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                    }
                }
                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }
            return(asyncResult);
        }
示例#5
0
        unsafe private static void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
        {
            // Unpack overlapped
            Overlapped overlapped = Overlapped.Unpack(pOverlapped);
            // Free the overlapped struct in EndRead/EndWrite.

            // Extract async result from overlapped
            PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)overlapped.AsyncResult;

            asyncResult._numBytes = (int)numBytes;

            // Allow async read to finish
            if (!asyncResult._isWrite)
            {
                if (errorCode == Interop.ERROR_BROKEN_PIPE ||
                    errorCode == Interop.ERROR_PIPE_NOT_CONNECTED ||
                    errorCode == Interop.ERROR_NO_DATA)
                {
                    errorCode = 0;
                    numBytes  = 0;
                }
            }

            // For message type buffer.
            if (errorCode == Interop.ERROR_MORE_DATA)
            {
                errorCode = 0;
                asyncResult._isMessageComplete = false;
            }
            else
            {
                asyncResult._isMessageComplete = true;
            }

            asyncResult._errorCode = (int)errorCode;

            // Call the user-provided callback.  It can and often should
            // call EndRead or EndWrite.  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.GetSafeWaitHandle().IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set();
                Debug.Assert(r, "ManualResetEvent::Set failed!");
                if (!r)
                {
                    throw Win32Marshal.GetExceptionForLastWin32Error();
                }
            }

            AsyncCallback callback = asyncResult._userCallback;

            if (callback != null)
            {
                callback(asyncResult);
            }
        }
        private unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state)
        {
            CheckConnectOperationsServerWithHandle();

            if (!IsAsync)
            {
                throw new InvalidOperationException(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;

            IOCancellationHelper cancellationHelper = state as IOCancellationHelper;

            // 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();

            overlapped.OffsetLow   = 0;
            overlapped.OffsetHigh  = 0;
            overlapped.AsyncResult = asyncResult;

            // Pack the Overlapped class, and store it in the async result
            NativeOverlapped *intOverlapped = overlapped.Pack(s_WaitForConnectionCallback, null);

            asyncResult._overlapped = intOverlapped;
            if (!Interop.mincore.ConnectNamedPipe(InternalHandle, intOverlapped))
            {
                int errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Interop.ERROR_IO_PENDING)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
                    }
                    return(asyncResult);
                }

                // WaitForConnectionCallback will not be called because we completed synchronously.
                // Either the pipe is already connected, or there was an error. Unpin and free the overlapped again.
                Overlapped.Free(intOverlapped);
                asyncResult._overlapped = null;

                // Did the client already connect to us?
                if (errorCode == Interop.ERROR_PIPE_CONNECTED)
                {
                    if (State == PipeState.Connected)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected);
                    }
                    asyncResult.CallUserCallback();
                    return(asyncResult);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }
            // will set state to Connected when EndWait is called
            if (cancellationHelper != null)
            {
                cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
            }

            return(asyncResult);
        }
        private unsafe void EndWaitForConnection(IAsyncResult asyncResult)
        {
            CheckConnectOperationsServerWithHandle();

            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }
            if (!IsAsync)
            {
                throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
            }

            PipeAsyncResult afsar = asyncResult as PipeAsyncResult;

            if (afsar == null)
            {
                throw __Error.GetWrongAsyncResult();
            }

            // Ensure we can't get into any races 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))
            {
                throw __Error.GetEndWaitForConnectionCalledTwice();
            }

            IOCancellationHelper cancellationHelper = afsar.AsyncState as IOCancellationHelper;

            if (cancellationHelper != null)
            {
                cancellationHelper.SetOperationCompleted();
            }

            // 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.
                using (wh)
                {
                    wh.WaitOne();
                    Debug.Assert(afsar._isComplete == true, "NamedPipeServerStream::EndWaitForConnection - AsyncFSCallback didn't set _isComplete to true!");
                }
            }

            // We should have freed the overlapped and set it to null either in the Begin
            // method (if ConnectNamedPipe completed synchronously) or in AsyncWaitForConnectionCallback.
            // If it is not nulled out, we should not be past the above wait:
            Debug.Assert(afsar._overlapped == null);

            // Now check for any error during the read.
            if (afsar._errorCode != 0)
            {
                if (afsar._errorCode == Interop.ERROR_OPERATION_ABORTED)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.ThrowIOOperationAborted();
                    }
                }
                throw Win32Marshal.GetExceptionForWin32Error(afsar._errorCode);
            }

            // Success
            State = PipeState.Connected;
        }
示例#8
0
        private Task <int> ReadAsyncCorePrivate(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanRead, "can't read");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "ReadAsyncCorePrivate doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

            if (buffer.Length == 0)
            {
                UpdateMessageCompletion(false);
                return(s_zeroTask);
            }
            else
            {
                var completionSource = new ReadWriteCompletionSource(this, buffer, cancellationToken, isWrite: false);

                // Queue an async ReadFile operation and pass in a packed overlapped
                int errorCode = 0;
                int r;
                unsafe
                {
                    r = ReadFileNative(_handle, buffer, offset, count, completionSource.Overlapped, out errorCode);
                }

                // ReadFile, the OS version, will return 0 on failure, but this ReadFileNative wrapper
                // returns -1. This will return the following:
                // - On error, r==-1.
                // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
                // - On async requests that completed sequentially, r==0
                //
                // You will NEVER RELIABLY be able to get the number of buffer read back from this call
                // when using overlapped structures!  You must not pass in a non-null lpNumBytesRead to
                // ReadFile when using overlapped structures!  This is by design NT behavior.
                if (r == -1)
                {
                    switch (errorCode)
                    {
                    // One side has closed its handle or server disconnected.
                    // Set the state to Broken and do some cleanup work
                    case Interop.mincore.Errors.ERROR_BROKEN_PIPE:
                    case Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED:
                        State = PipeState.Broken;

                        unsafe
                        {
                            // Clear the overlapped status bit for this special case. Failure to do so looks
                            // like we are freeing a pending overlapped.
                            completionSource.Overlapped->InternalLow = IntPtr.Zero;
                        }

                        completionSource.ReleaseResources();
                        UpdateMessageCompletion(true);
                        return(s_zeroTask);

                    case Interop.mincore.Errors.ERROR_IO_PENDING:
                        break;

                    default:
                        throw Win32Marshal.GetExceptionForWin32Error(errorCode);
                    }
                }

                completionSource.RegisterForCancellation();
                return(completionSource.Task);
            }
        }
        // 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();

                handle.Dispose();

                // 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();

                    handle.Dispose();

                    // 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);
        private bool TryConnect(int timeout, CancellationToken cancellationToken)
        {
            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);
            }

            if (!Interop.mincore.WaitNamedPipe(_normalizedPipePath, timeout))
            {
                int errorCode = Marshal.GetLastWin32Error();

                // Server is not yet created
                if (errorCode == Interop.ERROR_FILE_NOT_FOUND)
                {
                    return(false);
                }

                // The timeout has expired.
                if (errorCode == Interop.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.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)
                {
                    return(false);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }

            // Success!
            InitializeHandle(handle, false, (_pipeOptions & PipeOptions.Asynchronous) != 0);
            State = PipeState.Connected;

            return(true);
        }
示例#11
0
 public void WaitForConnection()
 {
     if (!Win32Marshal.ConnectNamedPipe(Handle, IntPtr.Zero))
         throw Win32PipeError.GetException(); }
示例#12
0
 protected override void HandleError(int errorCode) =>
 TrySetException(ExceptionDispatchInfo.SetCurrentStackTrace(Win32Marshal.GetExceptionForWin32Error(errorCode)));
示例#13
0
 protected override void HandleError(int errorCode)
 {
     TrySetException(Win32Marshal.GetExceptionForWin32Error(errorCode));
 }
示例#14
0
        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, clientHandle;
            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)
            {
                Exception e = Win32Marshal.GetExceptionForLastWin32Error();

                serverHandle.Dispose();
                clientHandle.Dispose();

                throw e;
            }

            // 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)
            {
                Exception e = Win32Marshal.GetExceptionForLastWin32Error();

                serverHandle.Dispose();
                newServerHandle.Dispose();
                clientHandle.Dispose();

                throw e;
            }

            // Close the inheritable server handle.
            serverHandle.Dispose();

            _clientHandle = clientHandle;
            InitializeHandle(newServerHandle, false, false);

            State = PipeState.Connected;
        }