Files
PowerShell-PowerShell/src/System.Management.Automation/engine/Interop/Windows/WNetGetConnection.cs
T
Jordan Borean 22beba4a47 Fix up buffer management getting network roots (#24600)
Fixes the logic used when getting the PSDrive DisplayRoot for network PSDrive paths to exclude null terminators.
2024-11-26 11:59:34 +05:00

87 lines
2.9 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#nullable enable
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Management.Automation.Internal;
internal static partial class Interop
{
internal static unsafe partial class Windows
{
private static bool s_WNetApiNotAvailable;
[LibraryImport("mpr.dll", EntryPoint = "WNetGetConnectionW", StringMarshalling = StringMarshalling.Utf16)]
internal static partial int WNetGetConnection(ReadOnlySpan<char> localName, Span<char> remoteName, ref int remoteNameLength);
internal static int GetUNCForNetworkDrive(char drive, out string? uncPath)
{
uncPath = null;
if (s_WNetApiNotAvailable)
{
return ERROR_NOT_SUPPORTED;
}
ReadOnlySpan<char> driveName = stackalloc char[] { drive, ':', '\0' };
int bufferSize = MAX_PATH;
Span<char> uncBuffer = stackalloc char[MAX_PATH];
if (InternalTestHooks.WNetGetConnectionBufferSize > 0 && InternalTestHooks.WNetGetConnectionBufferSize <= MAX_PATH)
{
bufferSize = InternalTestHooks.WNetGetConnectionBufferSize;
uncBuffer = uncBuffer.Slice(0, bufferSize);
}
char[]? rentedArray = null;
while (true)
{
int errorCode;
try
{
try
{
errorCode = WNetGetConnection(driveName, uncBuffer, ref bufferSize);
}
catch (DllNotFoundException)
{
s_WNetApiNotAvailable = true;
return ERROR_NOT_SUPPORTED;
}
if (errorCode == ERROR_SUCCESS)
{
// Cannot rely on bufferSize as it's only set if
// the first call ended with ERROR_MORE_DATA,
// instead slice at the null terminator.
unsafe
{
fixed (char* uncBufferPtr = uncBuffer)
{
uncPath = new string(uncBufferPtr);
}
}
}
}
finally
{
if (rentedArray is not null)
{
ArrayPool<char>.Shared.Return(rentedArray);
}
}
if (errorCode == ERROR_MORE_DATA)
{
uncBuffer = rentedArray = ArrayPool<char>.Shared.Rent(bufferSize);
}
else
{
return errorCode;
}
}
}
}
}