33
44using System . Diagnostics ;
55using System . Diagnostics . CodeAnalysis ;
6+ using System . Runtime . InteropServices ;
67using System . Text ;
78
89#if MS_IO_REDIST
@@ -14,8 +15,10 @@ namespace Microsoft.IO
1415namespace System . IO
1516#endif
1617{
17- public static partial class Path
18+ public static unsafe partial class Path
1819 {
20+ private static volatile delegate * unmanaged< int , char * , uint > s_GetTempPathWFunc ;
21+
1922 public static char [ ] GetInvalidFileNameChars ( ) => new char [ ]
2023 {
2124 '\" ' , '<' , '>' , '|' , '\0 ' ,
@@ -152,10 +155,22 @@ public static string GetTempPath()
152155 return path ;
153156 }
154157
155- private static void GetTempPath ( ref ValueStringBuilder builder )
158+ private static unsafe delegate * unmanaged< int , char * , uint > GetGetTempPathWFunc ( )
159+ {
160+ IntPtr kernel32 = Interop . Kernel32 . LoadLibraryEx ( Interop . Libraries . Kernel32 , IntPtr . Zero , Interop . Kernel32 . LOAD_LIBRARY_SEARCH_SYSTEM32 ) ;
161+
162+ if ( ! NativeLibrary . TryGetExport ( kernel32 , "GetTempPath2W" , out IntPtr func ) )
163+ {
164+ func = NativeLibrary . GetExport ( kernel32 , "GetTempPathW" ) ;
165+ }
166+
167+ return ( delegate * unmanaged< int , char * , uint > ) func ;
168+ }
169+
170+ internal static void GetTempPath ( ref ValueStringBuilder builder )
156171 {
157172 uint result ;
158- while ( ( result = Interop . Kernel32 . GetTempPathW ( builder . Capacity , ref builder . GetPinnableReference ( ) ) ) > builder . Capacity )
173+ while ( ( result = GetTempPathW ( builder . Capacity , ref builder . GetPinnableReference ( ) ) ) > builder . Capacity )
159174 {
160175 // Reported size is greater than the buffer size. Increase the capacity.
161176 builder . EnsureCapacity ( checked ( ( int ) result ) ) ;
@@ -165,6 +180,27 @@ private static void GetTempPath(ref ValueStringBuilder builder)
165180 throw Win32Marshal . GetExceptionForLastWin32Error ( ) ;
166181
167182 builder . Length = ( int ) result ;
183+
184+ static uint GetTempPathW ( int bufferLen , ref char buffer )
185+ {
186+ delegate * unmanaged< int , char * , uint > func = s_GetTempPathWFunc ;
187+ if ( func == null )
188+ {
189+ func = s_GetTempPathWFunc = GetGetTempPathWFunc ( ) ;
190+ }
191+
192+ int lastError ;
193+ uint retVal ;
194+ fixed ( char * ptr = & buffer )
195+ {
196+ Marshal . SetLastSystemError ( 0 ) ;
197+ retVal = func ( bufferLen , ptr ) ;
198+ lastError = Marshal . GetLastSystemError ( ) ;
199+ }
200+
201+ Marshal . SetLastPInvokeError ( lastError ) ;
202+ return retVal ;
203+ }
168204 }
169205
170206 // Returns a unique temporary file name, and creates a 0-byte file by that
0 commit comments