/// <summary>
        /// Helper method to create a PowerShell transport named pipe via native API, along
        /// with a returned .Net NamedPipeServerStream object wrapping the named pipe.
        /// </summary>
        /// <param name="serverName">Named pipe server name.</param>
        /// <param name="namespaceName">Named pipe namespace name.</param>
        /// <param name="coreName">Named pipe core name.</param>
        /// <param name="securityDesc"></param>
        /// <returns>NamedPipeServerStream</returns>
        private NamedPipeServerStream CreateNamedPipe(
            string serverName,
            string namespaceName,
            string coreName,
            CommonSecurityDescriptor securityDesc)
        {
            if (serverName == null)
            {
                throw new PSArgumentNullException("serverName");
            }
            if (namespaceName == null)
            {
                throw new PSArgumentNullException("namespaceName");
            }
            if (coreName == null)
            {
                throw new PSArgumentNullException("coreName");
            }

            string fullPipeName = @"\\" + serverName + @"\" + namespaceName + @"\" + coreName;

            // Create optional security attributes based on provided PipeSecurity.
            NamedPipeNative.SECURITY_ATTRIBUTES securityAttributes = null;
            GCHandle?securityDescHandle = null;

            if (securityDesc != null)
            {
                byte[] securityDescBuffer = new byte[securityDesc.BinaryLength];
                securityDesc.GetBinaryForm(securityDescBuffer, 0);
                securityDescHandle = GCHandle.Alloc(securityDescBuffer, GCHandleType.Pinned);
                securityAttributes = NamedPipeNative.GetSecurityAttributes(securityDescHandle.Value);
            }

            // Create named pipe.
            SafePipeHandle pipeHandle = NamedPipeNative.CreateNamedPipe(
                fullPipeName,
                NamedPipeNative.PIPE_ACCESS_DUPLEX | NamedPipeNative.FILE_FLAG_FIRST_PIPE_INSTANCE | NamedPipeNative.FILE_FLAG_OVERLAPPED,
                NamedPipeNative.PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_READMODE_MESSAGE,
                1,
                _namedPipeBufferSizeForRemoting,
                _namedPipeBufferSizeForRemoting,
                0,
                securityAttributes);

            int lastError = Marshal.GetLastWin32Error();

            if (securityDescHandle != null)
            {
                securityDescHandle.Value.Free();
            }

            if (pipeHandle.IsInvalid)
            {
                throw new PSInvalidOperationException(
                          StringUtil.Format(RemotingErrorIdStrings.CannotCreateNamedPipe, lastError));
            }

            // Create the .Net NamedPipeServerStream wrapper.
            try
            {
                return(new NamedPipeServerStream(
                           PipeDirection.InOut,
                           true,                // IsAsync
                           false,               // IsConnected
                           pipeHandle));
            }
            catch (Exception)
            {
                pipeHandle.Dispose();
                throw;
            }
        }
예제 #2
0
        /// <summary>
        /// Helper method to open a named pipe via native APIs and return in
        /// .Net NamedPipeClientStream wrapper object.
        /// </summary>
        protected override NamedPipeClientStream DoConnect(int timeout)
        {
            // Create pipe flags.
            uint pipeFlags = NamedPipeNative.FILE_FLAG_OVERLAPPED;

            //
            // WaitNamedPipe API is not supported by Windows Server container now, so we need to repeatedly
            // attempt connection to pipe server until timeout expires.
            //
            int            startTime   = Environment.TickCount;
            int            elapsedTime = 0;
            SafePipeHandle pipeHandle  = null;

            do
            {
                // Get handle to pipe.
                pipeHandle = NamedPipeNative.CreateFile(
                    _pipeName,
                    NamedPipeNative.GENERIC_READ | NamedPipeNative.GENERIC_WRITE,
                    0,
                    IntPtr.Zero,
                    NamedPipeNative.OPEN_EXISTING,
                    pipeFlags,
                    IntPtr.Zero);

                int lastError = Marshal.GetLastWin32Error();
                if (pipeHandle.IsInvalid)
                {
                    if (lastError == NamedPipeNative.ERROR_FILE_NOT_FOUND)
                    {
                        elapsedTime = unchecked (Environment.TickCount - startTime);
                        Thread.Sleep(100);
                        continue;
                    }
                    else
                    {
                        throw new PSInvalidOperationException(
                                  StringUtil.Format(RemotingErrorIdStrings.CannotConnectContainerNamedPipe, lastError));
                    }
                }
                else
                {
                    break;
                }
            } while (elapsedTime < timeout);

            try
            {
                return(new NamedPipeClientStream(
                           PipeDirection.InOut,
                           true,
                           true,
                           pipeHandle));
            }
            catch (Exception e)
            {
                CommandProcessorBase.CheckForSevereException(e);
                pipeHandle.Dispose();
                throw;
            }
        }