Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Use GetTempPath2W if available. #72452

Merged
merged 7 commits into from
Aug 11, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -1636,9 +1636,6 @@
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetTempFileNameW.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.GetTempFileNameW.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetTempPathW.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.GetTempPathW.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetVolumeInformation.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.GetVolumeInformation.cs</Link>
</Compile>
Expand Down
39 changes: 37 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;

namespace System.IO
{
public static partial class Path
public static unsafe partial class Path
{
private static volatile delegate* unmanaged<int, char*, uint> s_GetTempPathWFunc;

public static char[] GetInvalidFileNameChars() => new char[]
{
'\"', '<', '>', '|', '\0',
Expand Down Expand Up @@ -151,10 +154,22 @@ public static string GetTempPath()
return path;
}

private static unsafe delegate* unmanaged<int, char*, uint> GetGetTempPathWFunc()
{
IntPtr kernel32 = Interop.Kernel32.LoadLibraryEx(Interop.Libraries.Kernel32, 0, Interop.Kernel32.LOAD_LIBRARY_SEARCH_SYSTEM32);

if (!NativeLibrary.TryGetExport(kernel32, "GetTempPath2W", out IntPtr func))
{
func = NativeLibrary.GetExport(kernel32, "GetTempPathW");
}

return (delegate* unmanaged<int, char*, uint>)func;
}

private static void GetTempPath(ref ValueStringBuilder builder)
{
uint result;
while ((result = Interop.Kernel32.GetTempPathW(builder.Capacity, ref builder.GetPinnableReference())) > builder.Capacity)
while ((result = GetTempPathW(builder.Capacity, ref builder.GetPinnableReference())) > builder.Capacity)
{
// Reported size is greater than the buffer size. Increase the capacity.
builder.EnsureCapacity(checked((int)result));
Expand All @@ -164,6 +179,26 @@ private static void GetTempPath(ref ValueStringBuilder builder)
throw Win32Marshal.GetExceptionForLastWin32Error();

builder.Length = (int)result;

static uint GetTempPathW(int bufferLen, ref char buffer)
{
delegate* unmanaged<int, char*, uint> func = s_GetTempPathWFunc;
if (func == null)
{
func = s_GetTempPathWFunc = GetGetTempPathWFunc();
}

int lastError;
uint retVal;
fixed (char* ptr = &buffer)
{
Marshal.SetLastSystemError(0);
retVal = func(bufferLen, ptr);
lastError = Marshal.GetLastSystemError();
}
Marshal.SetLastPInvokeError(lastError);
return retVal;
}
}

// Returns a unique temporary file name, and creates a 0-byte file by that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public static unsafe Architecture OSArchitecture
// If we are running an x64 process on a non-x64 windows machine, we will report x64 as OS architecutre.
//
// IsWow64Process2 is only available on Windows 10+, so we will perform run-time introspection via indirect load
if (NativeLibrary.TryGetExport(NativeLibrary.Load(Interop.Libraries.Kernel32), "IsWow64Process2", out IntPtr isWow64Process2Ptr))
IntPtr kernel32 = Interop.Kernel32.LoadLibraryEx(Interop.Libraries.Kernel32, 0, Interop.Kernel32.LOAD_LIBRARY_SEARCH_SYSTEM32);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change to make load library more secure?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (NativeLibrary.TryGetExport(kernel32, "IsWow64Process2", out IntPtr isWow64Process2Ptr))
{
ushort processMachine, nativeMachine;
var isWow64Process2 = (delegate* unmanaged<IntPtr, ushort*, ushort*, int>)isWow64Process2Ptr;
Expand Down