Esempio n. 1
0
        protected override async Task WaitAndProcessAsync(
            Func <Stream, CancellationToken, Task> process,
            CancellationToken cancellationToken)
        {
            if (process is null)
            {
                throw new ArgumentNullException(nameof(process));
            }

            // https://github.com/PowerShell/PowerShellEditorServices/blob/f45c6312a859cde4aa25ea347a345e1d35238350/src/PowerShellEditorServices.Protocol/MessageProtocol/Channel/NamedPipeServerListener.cs#L38-L67
            // Unfortunately, .NET Core does not support passing in a PipeSecurity object into the constructor for
            // NamedPipeServerStream so we are creating native Named Pipes and securing them using native APIs.
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                PipeSecurity   pipeSecurity = new PipeSecurity();
                PipeAccessRule psRule       = new PipeAccessRule(@"Everyone", PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow);
                pipeSecurity.AddAccessRule(psRule);
                using (var server = NamedPipeNative.CreateNamedPipe(_options.PipeName, (uint)_options.MaxConcurrentCalls, pipeSecurity))
                {
                    await server.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false);
                    await process(server, cancellationToken).ConfigureAwait(false);
                }
            }

            // Use original logic on other platforms.
            else
            {
                using (var server = new NamedPipeServerStream(_options.PipeName, PipeDirection.InOut, _options.MaxConcurrentCalls,
                                                              PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
                {
                    await server.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false);
                    await process(server, cancellationToken).ConfigureAwait(false);
                }
            }
        }
Esempio n. 2
0
        /// <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="pipeName">Named pipe core name.</param>
        /// <param name="securityDesc"></param>
        /// <returns>NamedPipeServerStream</returns>
        internal static NamedPipeServerStream CreateNamedPipe(
            string pipeName,
            uint maxNumberOfServerInstances,
            PipeSecurity pipeSecurity)

        {
            string fullPipeName = @"\\.\pipe\" + pipeName;

            CommonSecurityDescriptor securityDesc = new CommonSecurityDescriptor(false, false, pipeSecurity.GetSecurityDescriptorBinaryForm(), 0);

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

            uint openMode = NamedPipeNative.PIPE_ACCESS_DUPLEX | NamedPipeNative.FILE_FLAG_OVERLAPPED;

            if (maxNumberOfServerInstances == 1)
            {
                openMode |= NamedPipeNative.FILE_FLAG_FIRST_PIPE_INSTANCE;
            }

            // Create named pipe.
#pragma warning disable CA2000 // Dispose objects before losing scope
            SafePipeHandle pipeHandle = NamedPipeNative.CreateNamedPipe(
                fullPipeName,
                openMode,
                NamedPipeNative.PIPE_TYPE_BYTE | NamedPipeNative.PIPE_READMODE_BYTE,
                maxNumberOfServerInstances,
                1,
                1,
                0,
                securityAttributes);
#pragma warning restore CA2000 // Dispose objects before losing scope

            int lastError = Marshal.GetLastWin32Error();
            if (securityDescHandle != null)
            {
                securityDescHandle.Value.Free();
            }

            if (pipeHandle.IsInvalid)
            {
                throw new InvalidOperationException();
            }

            // Create the .Net NamedPipeServerStream wrapper.
            try
            {
                return(new NamedPipeServerStream(
                           PipeDirection.InOut,
                           true,                // IsAsync
                           false,               // IsConnected
                           pipeHandle));
            }
            catch (Exception)
            {
                pipeHandle.Dispose();
                throw;
            }
        }