コード例 #1
0
ファイル: NativeMethods.cs プロジェクト: osortega/vs-pty.net
 internal static int ResizePseudoConsole(SafePseudoConsoleHandle consoleHandle, Coord coord)
 {
     if (Environment.Is64BitOperatingSystem)
     {
         return(ResizePseudoConsole64(consoleHandle, coord));
     }
     else
     {
         return(ResizePseudoConsole86(consoleHandle, coord));
     }
 }
コード例 #2
0
ファイル: NativeMethods.cs プロジェクト: osortega/vs-pty.net
            /// <summary>
            /// Initializes the specified startup info struct with the required properties and
            /// updates its thread attribute list with the specified ConPTY handle.
            /// </summary>
            /// <param name="handle">Pseudo console handle.</param>
            internal void InitAttributeListAttachedToConPTY(SafePseudoConsoleHandle handle)
            {
                this.StartupInfo.cb      = Marshal.SizeOf <STARTUPINFOEX>();
                this.StartupInfo.dwFlags = STARTF_USESTDHANDLES;

                const int AttributeCount = 1;
                var       size           = IntPtr.Zero;

                // Create the appropriately sized thread attribute list
                bool wasInitialized = InitializeProcThreadAttributeList(IntPtr.Zero, AttributeCount, 0, ref size);

                if (wasInitialized || size == IntPtr.Zero)
                {
                    throw new InvalidOperationException(
                              $"Couldn't get the size of the process attribute list for {AttributeCount} attributes",
                              new Win32Exception());
                }

                this.lpAttributeList = Marshal.AllocHGlobal(size);
                if (this.lpAttributeList == IntPtr.Zero)
                {
                    throw new OutOfMemoryException("Couldn't reserve space for a new process attribute list");
                }

                // Set startup info's attribute list & initialize it
                wasInitialized = InitializeProcThreadAttributeList(this.lpAttributeList, AttributeCount, 0, ref size);
                if (!wasInitialized)
                {
                    throw new InvalidOperationException("Couldn't create new process attribute list", new Win32Exception());
                }

                // Set thread attribute list's Pseudo Console to the specified ConPTY
                wasInitialized = UpdateProcThreadAttribute(
                    this.lpAttributeList,
                    0,
                    PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
                    handle.Handle,
                    (IntPtr)Marshal.SizeOf <IntPtr>(),
                    IntPtr.Zero,
                    IntPtr.Zero);

                if (!wasInitialized)
                {
                    throw new InvalidOperationException("Couldn't update process attribute list", new Win32Exception());
                }
            }
コード例 #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PseudoConsoleConnectionHandles"/> class.
 /// </summary>
 /// <param name="inPipePseudoConsoleSide">the input pipe on the pseudoconsole side.</param>
 /// <param name="outPipePseudoConsoleSide">the output pipe on the pseudoconsole side.</param>
 /// <param name="inPipeOurSide"> the input pipe on the local side.</param>
 /// <param name="outPipeOurSide"> the output pipe on the local side.</param>
 /// <param name="pseudoConsoleHandle">the handle to the pseudoconsole.</param>
 /// <param name="processHandle">the handle to the spawned process.</param>
 /// <param name="pid">the process ID.</param>
 /// <param name="mainThreadHandle">the handle to the main thread.</param>
 public PseudoConsoleConnectionHandles(
     SafePipeHandle inPipePseudoConsoleSide,
     SafePipeHandle outPipePseudoConsoleSide,
     SafePipeHandle inPipeOurSide,
     SafePipeHandle outPipeOurSide,
     SafePseudoConsoleHandle pseudoConsoleHandle,
     SafeProcessHandle processHandle,
     int pid,
     SafeThreadHandle mainThreadHandle)
 {
     this.InPipePseudoConsoleSide  = inPipePseudoConsoleSide;
     this.OutPipePseudoConsoleSide = outPipePseudoConsoleSide;
     this.InPipeOurSide            = inPipeOurSide;
     this.OutPipeOurSide           = outPipeOurSide;
     this.PseudoConsoleHandle      = pseudoConsoleHandle;
     this.ProcessHandle            = processHandle;
     this.Pid = pid;
     this.MainThreadHandle = mainThreadHandle;
 }
コード例 #4
0
ファイル: PtyProvider.cs プロジェクト: osortega/vs-pty.net
        private Task <IPtyConnection> StartPseudoConsoleAsync(
            PtyOptions options,
            TraceSource trace,
            CancellationToken cancellationToken)
        {
            // Create the in/out pipes
            if (!CreatePipe(out SafePipeHandle inPipePseudoConsoleSide, out SafePipeHandle inPipeOurSide, null, 0))
            {
                throw new InvalidOperationException("Could not create an anonymous pipe", new Win32Exception());
            }

            if (!CreatePipe(out SafePipeHandle outPipeOurSide, out SafePipeHandle outPipePseudoConsoleSide, null, 0))
            {
                throw new InvalidOperationException("Could not create an anonymous pipe", new Win32Exception());
            }

            var coord = new Coord(options.Cols, options.Rows);
            var pseudoConsoleHandle = new SafePseudoConsoleHandle();
            int hr;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                // Run CreatePseudoConsole* in a CER to make sure we don't leak handles.
                // MSDN suggest to put all CER code in a finally block
                // See http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions(v=vs.110).aspx
            }
            finally
            {
                // Create the Pseudo Console, using the pipes
                hr = CreatePseudoConsole(coord, inPipePseudoConsoleSide.Handle, outPipePseudoConsoleSide.Handle, 0, out IntPtr hPC);

                // Remember the handle inside the CER to prevent leakage
                if (hPC != IntPtr.Zero && hPC != INVALID_HANDLE_VALUE)
                {
                    pseudoConsoleHandle.InitialSetHandle(hPC);
                }
            }

            if (hr != S_OK)
            {
                Marshal.ThrowExceptionForHR(hr);
            }

            // Prepare the StartupInfoEx structure attached to the ConPTY.
            var startupInfo = default(STARTUPINFOEX);

            startupInfo.InitAttributeListAttachedToConPTY(pseudoConsoleHandle);
            IntPtr lpEnvironment = Marshal.StringToHGlobalUni(GetEnvironmentString(options.Environment));

            try
            {
                string app       = GetAppOnPath(options.App, options.Cwd, options.Environment);
                string arguments = options.VerbatimCommandLine ?
                                   WindowsArguments.FormatVerbatim(options.CommandLine) :
                                   WindowsArguments.Format(options.CommandLine);

                var  commandLine = new StringBuilder(app.Length + arguments.Length + 4);
                bool quoteApp    = app.Contains(" ") && !app.StartsWith("\"") && !app.EndsWith("\"");
                if (quoteApp)
                {
                    commandLine.Append('"').Append(app).Append('"');
                }
                else
                {
                    commandLine.Append(app);
                }

                if (!string.IsNullOrWhiteSpace(arguments))
                {
                    commandLine.Append(' ');
                    commandLine.Append(arguments);
                }

                bool success;
                int  errorCode        = 0;
                var  processInfo      = default(PROCESS_INFORMATION);
                var  processHandle    = new SafeProcessHandle();
                var  mainThreadHandle = new SafeThreadHandle();

                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    // Run CreateProcess* in a CER to make sure we don't leak handles.
                }
                finally
                {
                    success = CreateProcess(
                        null,                                                      // lpApplicationName
                        commandLine.ToString(),
                        null,                                                      // lpProcessAttributes
                        null,                                                      // lpThreadAttributes
                        false,                                                     // bInheritHandles VERY IMPORTANT that this is false
                        EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
                        lpEnvironment,
                        options.Cwd,
                        ref startupInfo,
                        out processInfo);

                    if (!success)
                    {
                        errorCode = Marshal.GetLastWin32Error();
                    }

                    // Remember the handles inside the CER to prevent leakage
                    if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != INVALID_HANDLE_VALUE)
                    {
                        processHandle.InitialSetHandle(processInfo.hProcess);
                    }

                    if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != INVALID_HANDLE_VALUE)
                    {
                        mainThreadHandle.InitialSetHandle(processInfo.hThread);
                    }
                }

                if (!success)
                {
                    var exception = new Win32Exception(errorCode);
                    throw new InvalidOperationException($"Could not start terminal process {commandLine.ToString()}: {exception.Message}", exception);
                }

                var connectionOptions = new PseudoConsoleConnection.PseudoConsoleConnectionHandles(
                    inPipePseudoConsoleSide,
                    outPipePseudoConsoleSide,
                    inPipeOurSide,
                    outPipeOurSide,
                    pseudoConsoleHandle,
                    processHandle,
                    processInfo.dwProcessId,
                    mainThreadHandle);

                var result = new PseudoConsoleConnection(connectionOptions);
                return(Task.FromResult <IPtyConnection>(result));
            }
            finally
            {
                startupInfo.FreeAttributeList();
                if (lpEnvironment != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(lpEnvironment);
                }
            }
        }
コード例 #5
0
ファイル: NativeMethods.cs プロジェクト: osortega/vs-pty.net
 private static extern int ResizePseudoConsole86(SafePseudoConsoleHandle consoleHandle, Coord coord);