Remove StringBuilder in System.IO.Pipes marshaling (#30509)

* Remove StringBuilder in System.IO.Pipes marshaling

To get the impersonated user name, we can just stackalloc space for the Win32 call and then create a string from that, instead of allocating a StringBuilder and its underlying char[], paying the associated StringBuilder marshaling costs, and then creating the string from that.

* Fix existing typo in comment
This commit is contained in:
Stephen Toub 2018-06-19 16:53:41 -04:00 коммит произвёл GitHub
Родитель 8c0487bfef
Коммит c09a2a5296
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 8 добавлений и 9 удалений

Просмотреть файл

@ -5,7 +5,6 @@
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
using System.Text;
internal partial class Interop
{
@ -24,13 +23,13 @@ internal partial class Interop
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "GetNamedPipeHandleStateW")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetNamedPipeHandleState(
internal static extern unsafe bool GetNamedPipeHandleState(
SafePipeHandle hNamedPipe,
IntPtr lpState,
IntPtr lpCurInstances,
IntPtr lpMaxCollectionCount,
IntPtr lpCollectDataTimeout,
[Out] StringBuilder lpUserName,
char* lpUserName,
int nMaxUserNameSize);
[DllImport(Libraries.Kernel32, SetLastError = true, EntryPoint="GetNamedPipeHandleStateW")]
@ -43,6 +42,5 @@ internal partial class Interop
IntPtr lpCollectDataTimeout,
IntPtr lpUserName,
int nMaxUserNameSize);
}
}

Просмотреть файл

@ -166,22 +166,23 @@ namespace System.IO.Pipes
State = PipeState.Disconnected;
}
// Gets the username of the connected client. Not that we will not have access to the client's
// Gets the username of the connected client. Note that we will not have access to the client's
// username until it has written at least once to the pipe (and has set its impersonationLevel
// argument appropriately).
public String GetImpersonationUserName()
public unsafe string GetImpersonationUserName()
{
CheckWriteOperations();
StringBuilder userName = new StringBuilder(Interop.Kernel32.CREDUI_MAX_USERNAME_LENGTH + 1);
const int UserNameMaxLength = Interop.Kernel32.CREDUI_MAX_USERNAME_LENGTH + 1;
char* userName = stackalloc char[UserNameMaxLength]; // ~1K
if (!Interop.Kernel32.GetNamedPipeHandleState(InternalHandle, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero, userName, userName.Capacity))
IntPtr.Zero, IntPtr.Zero, userName, UserNameMaxLength))
{
throw WinIOError(Marshal.GetLastWin32Error());
}
return userName.ToString();
return new string(userName);
}
// -----------------------------