internal partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateProcessWithLogonW")]
- internal static extern bool CreateProcessWithLogonW(
+ internal static extern unsafe bool CreateProcessWithLogonW(
string userName,
string domain,
IntPtr password,
LogonFlags logonFlags,
string? appName,
-#pragma warning disable CA1838 // reasonable use of StringBuilder to build up a command line
- [In] StringBuilder cmdLine,
-#pragma warning restore CA1838
+ char* cmdLine,
int creationFlags,
IntPtr environmentBlock,
- string lpCurrentDirectory,
+ string? lpCurrentDirectory,
ref Interop.Kernel32.STARTUPINFO lpStartupInfo,
ref Interop.Kernel32.PROCESS_INFORMATION lpProcessInformation);
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Win32.SafeHandles;
+using System;
using System.Runtime.InteropServices;
internal partial class Interop
internal partial class Advapi32
{
[DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
- internal static extern bool OpenProcessToken(SafeProcessHandle ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle);
+ internal static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle);
}
}
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateProcessW")]
- internal static extern bool CreateProcess(
+ internal static extern unsafe bool CreateProcess(
string? lpApplicationName,
-#pragma warning disable CA1838 // reasonable use of StringBuilder to build up a command line
- [In] StringBuilder lpCommandLine,
-#pragma warning restore CA1838
+ char* lpCommandLine,
ref SECURITY_ATTRIBUTES procSecAttrs,
ref SECURITY_ATTRIBUTES threadSecAttrs,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
- string lpCurrentDirectory,
+ string? lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation
);
{
internal static partial class Kernel32
{
- [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+ [DllImport(Libraries.Kernel32, SetLastError = true)]
internal static extern bool DuplicateHandle(
IntPtr hSourceProcessHandle,
IntPtr hSourceHandle,
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool DuplicateHandle(
+ IntPtr hSourceProcessHandle,
+ SafeHandle hSourceHandle,
+ IntPtr hTargetProcess,
+ out SafeFileHandle targetHandle,
+ int dwDesiredAccess,
+ bool bInheritHandle,
+ int dwOptions
+ );
+ }
+}
using System;
using System.Runtime.InteropServices;
-internal partial class Interop
+internal static partial class Interop
{
- internal partial class Kernel32
+ internal static partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool DuplicateHandle(
IntPtr hSourceProcessHandle,
- SafePipeHandle hSourceHandle,
+ SafeHandle hSourceHandle,
IntPtr hTargetProcessHandle,
out SafePipeHandle lpTargetHandle,
uint dwDesiredAccess,
- [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
+ bool bInheritHandle,
uint dwOptions);
-
}
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Runtime.InteropServices;
-
-internal partial class Interop
-{
- internal partial class Kernel32
- {
- [DllImport(Libraries.Kernel32, SetLastError = true, BestFitMapping = false)]
- internal static extern bool DuplicateHandle(
- SafeProcessHandle hSourceProcessHandle,
- SafeHandle hSourceHandle,
- SafeProcessHandle hTargetProcess,
- out SafeFileHandle targetHandle,
- int dwDesiredAccess,
- bool bInheritHandle,
- int dwOptions
- );
-
- [DllImport(Libraries.Kernel32, SetLastError = true, BestFitMapping = false)]
- internal static extern bool DuplicateHandle(
- SafeProcessHandle hSourceProcessHandle,
- SafeHandle hSourceHandle,
- SafeProcessHandle hTargetProcess,
- out SafeWaitHandle targetHandle,
- int dwDesiredAccess,
- bool bInheritHandle,
- int dwOptions
- );
-
- }
-}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool DuplicateHandle(
+ IntPtr hSourceProcessHandle,
+ SafeHandle hSourceHandle,
+ IntPtr hTargetProcess,
+ out SafeWaitHandle targetHandle,
+ int dwDesiredAccess,
+ bool bInheritHandle,
+ int dwOptions
+ );
+ }
+}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Microsoft.Win32.SafeHandles;
-using System.Runtime.InteropServices;
-
-internal partial class Interop
-{
- internal partial class Kernel32
- {
- [DllImport(Libraries.Kernel32, SetLastError = true)]
- internal static extern SafeProcessHandle GetCurrentProcess();
- }
-}
#nullable enable
using Microsoft.Win32.SafeHandles;
+using System;
using System.Runtime.InteropServices;
using System.Threading;
{
internal ProcessWaitHandle(SafeProcessHandle processHandle)
{
- SafeWaitHandle? waitHandle;
- SafeProcessHandle currentProcHandle = Interop.Kernel32.GetCurrentProcess();
- bool succeeded = Interop.Kernel32.DuplicateHandle(
+ IntPtr currentProcHandle = GetCurrentProcess();
+ bool succeeded = DuplicateHandle(
currentProcHandle,
processHandle,
currentProcHandle,
- out waitHandle,
+ out SafeWaitHandle waitHandle,
0,
false,
- Interop.Kernel32.HandleOptions.DUPLICATE_SAME_ACCESS);
+ HandleOptions.DUPLICATE_SAME_ACCESS);
if (!succeeded)
{
- Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+ int error = Marshal.GetHRForLastWin32Error();
+ waitHandle.Dispose();
+ Marshal.ThrowExceptionForHR(error);
}
this.SetSafeWaitHandle(waitHandle);
return(userId == 0);
}
- IntPtr processHandle = Interop.Kernel32.GetCurrentProcess();
SafeAccessTokenHandle token;
- if (!Interop.Advapi32.OpenProcessToken(processHandle, TokenAccessLevels.Read, out token))
+ if (!Interop.Advapi32.OpenProcessToken(Interop.Kernel32.GetCurrentProcess(), TokenAccessLevels.Read, out token))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "Open process token failed");
}
</ItemGroup>
<!-- Windows imports -->
<ItemGroup>
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs"
- Link="Common\Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
+ Link="Common\Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\NtDll\Interop.RtlGetVersion.cs"
Link="Common\Interop\Windows\NtDll\Interop.RtlGetVersion.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Advapi32\Interop.OpenProcessToken_SafeAccessTokenHandle.cs"
Link="Common\Interop\Windows\Kernel32\Interop.Constants.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.CreateFileMapping.cs"
Link="Common\Interop\Windows\Kernel32\Interop.CreateFileMapping.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeProcessHandle.cs"
- Link="Common\Interop\Windows\kernel32\Interop.DuplicateHandle.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeWaitHandle.cs"
+ Link="Common\Interop\Windows\kernel32\Interop.DuplicateHandle_SafeWaitHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.FreeLibrary.cs"
Link="Common\Interop\Windows\Kernel32\Interop.FreeLibrary.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetComputerName.cs"
Link="Common\Interop\Windows\Kernel32\Interop.GetComputerName.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_SafeProcessHandle.cs"
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
Link="Common\Interop\Windows\kernel32\Interop.GetCurrentProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs"
Link="Common\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs" />
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime.CompilerServices.Unsafe\src\System.Runtime.CompilerServices.Unsafe.ilproj" />
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DefineConstants>$(DefineConstants);FEATURE_REGISTRY</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskCompletionSourceWithCancellation.cs"
Link="Common\System\Threading\Tasks\TaskCompletionSourceWithCancellation.cs" />
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskTimeoutExtensions.cs"
- Link="Common\System\Threading\Tasks\TaskTimeoutExtensions.cs" />
+ Link="Common\System\Threading\Tasks\TaskTimeoutExtensions.cs" />
+ <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs"
+ Link="Common\System\Text\ValueStringBuilder.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetsWindows)' == 'true'">
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.EnumProcessModules.cs"
Link="Common\Interop\Windows\Kernel32\Interop.CreateProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.TerminateProcess.cs"
Link="Common\Interop\Windows\Kernel32\Interop.TerminateProcess.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_SafeProcessHandle.cs"
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
Link="Common\Interop\Windows\kernel32\Interop.GetCurrentProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.OpenProcess.cs"
Link="Common\Interop\Windows\Kernel32\Interop.OpenProcess.cs" />
Link="Common\Interop\Windows\Kernel32\Interop.GetPriorityClass.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.SetPriorityClass.cs"
Link="Common\Interop\Windows\Kernel32\Interop.SetPriorityClass.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeProcessHandle.cs"
- Link="Common\Interop\Windows\kernel32\Interop.DuplicateHandle.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeFileHandle.cs"
+ Link="Common\Interop\Windows\kernel32\Interop.DuplicateHandle_SafeFileHandle.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeWaitHandle.cs"
+ Link="Common\Interop\Windows\kernel32\Interop.DuplicateHandle_SafeWaitHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.ProcessWaitHandle.cs"
Link="Common\Interop\Windows\Kernel32\Interop.ProcessWaitHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Advapi32\Interop.OpenProcessToken.cs"
<Compile Include="System\Diagnostics\ProcessStartInfo.Unix.cs" />
<Compile Include="System\Diagnostics\ProcessWaitHandle.Unix.cs" />
<Compile Include="System\Diagnostics\ProcessWaitState.Unix.cs" />
- <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs"
- Link="Common\System\Text\ValueStringBuilder.cs" />
<Compile Include="$(CommonPath)System\IO\StringParser.cs"
Link="Common\System\IO\StringParser.cs" />
<Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
private static string[] ParseArgv(ProcessStartInfo psi, string? resolvedExe = null, bool ignoreArguments = false)
{
if (string.IsNullOrEmpty(resolvedExe) &&
- (ignoreArguments || (string.IsNullOrEmpty(psi.Arguments) && psi.ArgumentList.Count == 0)))
+ (ignoreArguments || (string.IsNullOrEmpty(psi.Arguments) && !psi.HasArgumentList)))
{
return new string[] { psi.FileName };
}
{
ParseArgumentsIntoList(psi.Arguments, argvList);
}
- else
+ else if (psi.HasArgumentList)
{
argvList.AddRange(psi.ArgumentList);
}
// * CreateProcess allows you to redirect all or none of the standard IO handles, so we use
// GetStdHandle for the handles that are not being redirected
- StringBuilder commandLine = BuildCommandLine(startInfo);
+ var commandLine = new ValueStringBuilder(stackalloc char[256]);
+ BuildCommandLine(startInfo, ref commandLine);
Interop.Kernel32.STARTUPINFO startupInfo = default;
Interop.Kernel32.PROCESS_INFORMATION processInfo = default;
Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = default;
SafeProcessHandle procSH = new SafeProcessHandle();
- SafeThreadHandle threadSH = new SafeThreadHandle();
// handles used in parent process
SafeFileHandle? parentInputPipeHandle = null;
creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables!);
}
- string workingDirectory = startInfo.WorkingDirectory;
+
+ string? workingDirectory = startInfo.WorkingDirectory;
if (workingDirectory.Length == 0)
- workingDirectory = Directory.GetCurrentDirectory();
+ {
+ workingDirectory = null;
+ }
bool retVal;
int errorCode = 0;
fixed (char* passwordInClearTextPtr = startInfo.PasswordInClearText ?? string.Empty)
fixed (char* environmentBlockPtr = environmentBlock)
+ fixed (char* commandLinePtr = &commandLine.GetPinnableReference(terminate: true))
{
IntPtr passwordPtr = (startInfo.Password != null) ?
Marshal.SecureStringToGlobalAllocUnicode(startInfo.Password) : IntPtr.Zero;
(passwordPtr != IntPtr.Zero) ? passwordPtr : (IntPtr)passwordInClearTextPtr,
logonFlags,
null, // we don't need this since all the info is in commandLine
- commandLine,
+ commandLinePtr,
creationFlags,
(IntPtr)environmentBlockPtr,
workingDirectory,
else
{
fixed (char* environmentBlockPtr = environmentBlock)
+ fixed (char* commandLinePtr = &commandLine.GetPinnableReference(terminate: true))
{
retVal = Interop.Kernel32.CreateProcess(
null, // we don't need this since all the info is in commandLine
- commandLine, // pointer to the command line string
+ commandLinePtr, // pointer to the command line string
ref unused_SecAttrs, // address to process security attributes, we don't need to inherit the handle
ref unused_SecAttrs, // address to thread security attributes.
true, // handle inheritance flag
if (processInfo.hProcess != IntPtr.Zero && processInfo.hProcess != new IntPtr(-1))
procSH.InitialSetHandle(processInfo.hProcess);
if (processInfo.hThread != IntPtr.Zero && processInfo.hThread != new IntPtr(-1))
- threadSH.InitialSetHandle(processInfo.hThread);
+ Interop.Kernel32.CloseHandle(processInfo.hThread);
if (!retVal)
{
childInputPipeHandle?.Dispose();
childOutputPipeHandle?.Dispose();
childErrorPipeHandle?.Dispose();
-
- threadSH?.Dispose();
}
}
_standardError = new StreamReader(new FileStream(parentErrorPipeHandle!, FileAccess.Read, 4096, false), enc, true, 4096);
}
+ commandLine.Dispose();
+
if (procSH.IsInvalid)
return false;
private bool _signaled;
- private static StringBuilder BuildCommandLine(ProcessStartInfo startInfo)
+ private static void BuildCommandLine(ProcessStartInfo startInfo, ref ValueStringBuilder commandLine)
{
// Construct a StringBuilder with the appropriate command line
// to pass to CreateProcess. If the filename isn't already
// in quotes, we quote it here. This prevents some security
// problems (it specifies exactly which part of the string
// is the file to execute).
- StringBuilder commandLine = new StringBuilder();
ReadOnlySpan<char> fileName = startInfo.FileName.AsSpan().Trim();
bool fileNameIsQuoted = fileName.Length > 0 && fileName[0] == '\"' && fileName[fileName.Length - 1] == '\"';
if (!fileNameIsQuoted)
commandLine.Append('"');
}
- startInfo.AppendArgumentsTo(commandLine);
-
- return commandLine;
+ startInfo.AppendArgumentsTo(ref commandLine);
}
/// <summary>Gets timing information for the current process.</summary>
private static unsafe void SetPrivilege(string privilegeName, int attrib)
{
// this is only a "pseudo handle" to the current process - no need to close it later
- SafeProcessHandle processHandle = Interop.Kernel32.GetCurrentProcess();
-
SafeTokenHandle? hToken = null;
try
{
// get the process token so we can adjust the privilege on it. We DO need to
// close the token when we're done with it.
- if (!Interop.Advapi32.OpenProcessToken(processHandle, Interop.Kernel32.HandleOptions.TOKEN_ADJUST_PRIVILEGES, out hToken))
+ if (!Interop.Advapi32.OpenProcessToken(Interop.Kernel32.GetCurrentProcess(), Interop.Kernel32.HandleOptions.TOKEN_ADJUST_PRIVILEGES, out hToken))
{
throw new Win32Exception();
}
/// Note that the handle we stored in current process object will have all access we need.
/// </devdoc>
/// <internalonly/>
- private SafeProcessHandle GetProcessHandle(int access, bool throwIfExited)
+ private SafeProcessHandle GetProcessHandle(int access, bool throwIfExited = true)
{
if (_haveProcessHandle)
{
{
if (waitHandle.WaitOne(0))
{
- if (_haveProcessId)
- throw new InvalidOperationException(SR.Format(SR.ProcessHasExited, _processId.ToString()));
- else
- throw new InvalidOperationException(SR.ProcessHasExitedNoId);
+ throw new InvalidOperationException(_haveProcessId ?
+ SR.Format(SR.ProcessHasExited, _processId.ToString()) :
+ SR.ProcessHasExitedNoId);
}
}
}
else
{
EnsureState(State.HaveId | State.IsLocal);
- SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
- handle = ProcessManager.OpenProcess(_processId, access, throwIfExited);
+ SafeProcessHandle handle = ProcessManager.OpenProcess(_processId, access, throwIfExited);
if (throwIfExited && (access & Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION) != 0)
{
if (Interop.Kernel32.GetExitCodeProcess(handle, out _exitCode) && _exitCode != Interop.Kernel32.HandleOptions.STILL_ACTIVE)
}
}
- /// <devdoc>
- /// Gets a short-term handle to the process, with the given access. If a handle exists,
- /// then it is reused. If the process has exited, it throws an exception.
- /// </devdoc>
- /// <internalonly/>
- private SafeProcessHandle GetProcessHandle(int access)
- {
- return GetProcessHandle(access, true);
- }
-
private static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref Interop.Kernel32.SECURITY_ATTRIBUTES lpPipeAttributes, int nSize)
{
bool ret = Interop.Kernel32.CreatePipe(out hReadPipe, out hWritePipe, ref lpPipeAttributes, nSize);
// One potential theory is that child process can do something brain dead like
// closing the parent end of the pipe and there by getting into a blocking situation
// as parent will not be draining the pipe at the other end anymore.
- SafeProcessHandle currentProcHandle = Interop.Kernel32.GetCurrentProcess();
+ IntPtr currentProcHandle = Interop.Kernel32.GetCurrentProcess();
if (!Interop.Kernel32.DuplicateHandle(currentProcHandle,
hTmp,
currentProcHandle,
{
throw new InvalidOperationException(SR.StandardErrorEncodingNotAllowed);
}
- if (!string.IsNullOrEmpty(startInfo.Arguments) && startInfo.ArgumentList.Count > 0)
+ if (!string.IsNullOrEmpty(startInfo.Arguments) && startInfo.HasArgumentList)
{
throw new InvalidOperationException(SR.ArgumentAndArgumentListInitialized);
}
set => _arguments = value;
}
- public Collection<string> ArgumentList
- {
- get
- {
- if (_argumentList == null)
- {
- _argumentList = new Collection<string>();
- }
- return _argumentList;
- }
- }
+ public Collection<string> ArgumentList => _argumentList ??= new Collection<string>();
+
+ internal bool HasArgumentList => _argumentList is not null && _argumentList.Count != 0;
public bool CreateNoWindow { get; set; }
internal string BuildArguments()
{
- if (_argumentList == null || _argumentList.Count == 0)
+ if (HasArgumentList)
{
- return Arguments;
- }
- else
- {
- var stringBuilder = new StringBuilder();
- AppendArgumentsTo(stringBuilder);
- return stringBuilder.ToString();
+ var arguments = new ValueStringBuilder(stackalloc char[256]);
+ AppendArgumentsTo(ref arguments);
+ return arguments.ToString();
}
+
+ return Arguments;
}
- internal void AppendArgumentsTo(StringBuilder stringBuilder)
+ internal void AppendArgumentsTo(ref ValueStringBuilder stringBuilder)
{
if (_argumentList != null && _argumentList.Count > 0)
{
foreach (string argument in _argumentList)
{
- PasteArguments.AppendArgument(stringBuilder, argument);
+ PasteArguments.AppendArgument(ref stringBuilder, argument);
}
}
else if (!string.IsNullOrEmpty(Arguments))
Link="Common\System\ShouldNotBeInvokedException.cs" />
<Compile Include="$(CommonTestPath)Microsoft\Win32\TempRegistryKey.cs"
Link="Common\Microsoft\Win32\TempRegistryKey.cs" />
+ <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs"
+ Link="Common\System\Text\ValueStringBuilder.cs" />
<Compile Include="DelegateSynchronizeInvoke.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="Interop.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.FileOperations.cs"
Link="Common\Interop\Windows\Interop.FileOperations.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.FileTypes.cs"
- Link="Common\CoreLib\Interop\Windows\Interop.FileTypes.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs"
+ Link="Common\Interop\Windows\Interop.FileTypes.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
Link="Common\Interop\Windows\Interop.GetCurrentProcess.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_IntPtr.cs"
- Link="Common\Interop\Windows\Interop.DuplicateHandle_IntPtr.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafePipeHandle.cs"
+ Link="Common\Interop\Windows\Interop.DuplicateHandle_SafePipeHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetFileType_SafeHandle.cs"
- Link="Common\CoreLib\Interop\Windows\Interop.GetFileType.cs" />
+ Link="Common\Interop\Windows\Interop.GetFileType.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.CreatePipe_SafePipeHandle.cs"
Link="Common\Interop\Windows\Interop.CreatePipe_SafePipeHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.ConnectNamedPipe.cs"
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentDirectory.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.GetCurrentDirectory.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs">
- <Link>Common\Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs</Link>
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs">
+ <Link>Common\Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs</Link>
/// </summary>
internal static string Paste(IEnumerable<string> arguments, bool pasteFirstArgumentUsingArgV0Rules)
{
- var stringBuilder = new StringBuilder();
+ var stringBuilder = new ValueStringBuilder(stackalloc char[256]);
foreach (string argument in arguments)
{
- AppendArgument(stringBuilder, argument);
+ AppendArgument(ref stringBuilder, argument);
}
return stringBuilder.ToString();
}
/// </summary>
internal static string Paste(IEnumerable<string> arguments, bool pasteFirstArgumentUsingArgV0Rules)
{
- var stringBuilder = new StringBuilder();
+ var stringBuilder = new ValueStringBuilder(stackalloc char[256]);
foreach (string argument in arguments)
{
}
else
{
- AppendArgument(stringBuilder, argument);
+ AppendArgument(ref stringBuilder, argument);
}
}
{
internal static partial class PasteArguments
{
- internal static void AppendArgument(StringBuilder stringBuilder, string argument)
+ internal static void AppendArgument(ref ValueStringBuilder stringBuilder, string argument)
{
if (stringBuilder.Length != 0)
{
Link="Common\Interop\Interop.OpenThreadToken_SafeTokenHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Advapi32\Interop.OpenProcessToken_IntPtr.cs"
Link="Common\Interop\Interop.OpenProcessToken_IntPtrs.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs"
- Link="Common\Interop\Interop.GetCurrentProcess_IntPtr.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
+ Link="Common\Interop\Interop.GetCurrentProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Advapi32\Interop.SetThreadToken.cs"
Link="Common\Interop\Interop.SetThreadToken.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentThread.cs"
Link="Common\Interop\Interop.LSAStructs.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SspiCli\Interop.SECURITY_LOGON_SESSION_DATA.cs"
Link="Common\Interop\Interop.SECURITY_LOGON_SESSION_DATA.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs"
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcess.cs"
Link="Common\Interop\Interop.GetCurrentProcess.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentThread.cs"
Link="Common\Interop\Interop.GetCurrentThread.cs" />
Link="Common\Interop\Interop.GetTokenInformation.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Advapi32\Interop.DuplicateTokenEx.cs"
Link="Common\Interop\Interop.DuplicateTokenEx.cs" />
- <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle.cs"
- Link="Common\Interop\Interop.DuplicateHandle.cs" />
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.DuplicateHandle_SafeAccessTokenHandle.cs"
+ Link="Common\Interop\Interop.DuplicateHandle_SafeAccessTokenHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.CloseHandle.cs"
Link="Common\Interop\Interop.CloseHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\SspiCli\Interop.LsaGetLogonSessionData.cs"
<Reference Include="System.Security.Principal" />
<Reference Include="System.Threading" />
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>