Skip to content

Commit e3d2dd1

Browse files
tommcdonhoyosjs
andauthored
Use GetTempPath2 on Windows if available (#104642)
Since Windows 10 Build 20348, there is a new API to get the temporary files path called [`GetTempPath2`](https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-gettemppath2w). This API returns a directory inaccessible to non-SYSTEM processes if the calling process runs as SYSTEM, and [it is recommended to call this function instead of `GetTempPath`](https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-gettemppathw#remarks). This PR tries to find `GetTempPath2A` / `GetTempPath2W` and uses that, otherwise it falls back to `GetTempPathA` / `GetTempPathW`. *Note:* this PR removes an unused function `GetTempPathWrapper` that which referenced `GetTempPathW` Co-authored-by: Juan Sebastian Hoyos Ayala <juhoyosa@microsoft.com>
1 parent 4a1a076 commit e3d2dd1

File tree

6 files changed

+72
-47
lines changed

6 files changed

+72
-47
lines changed

src/coreclr/debug/createdump/createdump.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ extern MINIDUMP_TYPE GetMiniDumpType(DumpType dumpType);
149149

150150
#ifdef HOST_WINDOWS
151151
extern std::string GetLastErrorString();
152+
extern DWORD GetTempPathWrapper(IN DWORD nBufferLength, OUT LPSTR lpBuffer);
153+
#else
154+
#define GetTempPathWrapper GetTempPathA
152155
#endif
153156
extern void printf_status(const char* format, ...);
154157
extern void printf_error(const char* format, ...);

src/coreclr/debug/createdump/createdumpmain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ int createdump_main(const int argc, const char* argv[])
205205
ArrayHolder<char> tmpPath = new char[MAX_LONGPATH];
206206
if (options.DumpPathTemplate == nullptr)
207207
{
208-
if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0)
208+
if (GetTempPathWrapper(MAX_LONGPATH, tmpPath) == 0)
209209
{
210210
printf_error("GetTempPath failed\n");
211211
return -1;

src/coreclr/debug/createdump/createdumpwindows.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,38 @@ GetLastErrorString()
135135
return result;
136136
}
137137

138+
139+
typedef DWORD(WINAPI *pfnGetTempPathA)(DWORD nBufferLength, LPSTR lpBuffer);
140+
141+
static volatile pfnGetTempPathA
142+
g_pfnGetTempPathA = nullptr;
143+
144+
145+
DWORD
146+
GetTempPathWrapper(
147+
IN DWORD nBufferLength,
148+
OUT LPSTR lpBuffer)
149+
{
150+
if (g_pfnGetTempPathA == nullptr)
151+
{
152+
HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
153+
154+
pfnGetTempPathA pLocalGetTempPathA = NULL;
155+
if (hKernel32 != NULL)
156+
{
157+
// store to thread local variable to prevent data race
158+
pLocalGetTempPathA = (pfnGetTempPathA)::GetProcAddress(hKernel32, "GetTempPath2A");
159+
}
160+
161+
if (pLocalGetTempPathA == NULL) // method is only available with Windows 10 Creators Update or later
162+
{
163+
g_pfnGetTempPathA = &GetTempPathA;
164+
}
165+
else
166+
{
167+
g_pfnGetTempPathA = pLocalGetTempPathA;
168+
}
169+
}
170+
171+
return g_pfnGetTempPathA(nBufferLength, lpBuffer);
172+
}

src/coreclr/inc/longfilepathwrappers.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ SearchPathWrapper(
5959
_Out_opt_ LPWSTR * lpFilePart
6060
);
6161

62-
DWORD WINAPI GetTempPathWrapper(
63-
SString& lpBuffer
64-
);
65-
6662
DWORD
6763
GetModuleFileNameWrapper(
6864
_In_opt_ HMODULE hModule,

src/coreclr/utilcode/longfilepathwrappers.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -184,47 +184,6 @@ GetModuleFileNameWrapper(
184184
return ret;
185185
}
186186

187-
DWORD WINAPI GetTempPathWrapper(
188-
SString& lpBuffer
189-
)
190-
{
191-
CONTRACTL
192-
{
193-
NOTHROW;
194-
}
195-
CONTRACTL_END;
196-
197-
HRESULT hr = S_OK;
198-
DWORD ret = 0;
199-
DWORD lastError = 0;
200-
201-
EX_TRY
202-
{
203-
//Change the behaviour in Redstone to retry
204-
COUNT_T size = MAX_LONGPATH;
205-
206-
ret = GetTempPathW(
207-
size,
208-
lpBuffer.OpenUnicodeBuffer(size - 1)
209-
);
210-
211-
lastError = GetLastError();
212-
lpBuffer.CloseBuffer(ret);
213-
}
214-
EX_CATCH_HRESULT(hr);
215-
216-
if (hr != S_OK)
217-
{
218-
SetLastError(hr);
219-
}
220-
else if (ret == 0)
221-
{
222-
SetLastError(lastError);
223-
}
224-
225-
return ret;
226-
}
227-
228187
DWORD WINAPI GetEnvironmentVariableWrapper(
229188
_In_opt_ LPCTSTR lpName,
230189
_Out_opt_ SString& lpBuffer

src/native/corehost/hostmisc/pal.windows.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,38 @@ void pal::out_vprint_line(const pal::char_t* format, va_list vl) {
6666
print_line_to_handle(&buffer[0], ::GetStdHandle(STD_OUTPUT_HANDLE), stdout);
6767
}
6868

69+
namespace
70+
{
71+
typedef DWORD(WINAPI *get_temp_path_func_ptr)(DWORD buffer_len, LPWSTR buffer);
72+
static volatile get_temp_path_func_ptr s_get_temp_path_func = nullptr;
73+
74+
DWORD get_temp_path(DWORD buffer_len, LPWSTR buffer)
75+
{
76+
if (s_get_temp_path_func == nullptr)
77+
{
78+
HMODULE kernel32 = ::LoadLibraryExW(L"kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
79+
80+
get_temp_path_func_ptr get_temp_path_func_local = NULL;
81+
if (kernel32 != NULL)
82+
{
83+
// store to thread local variable to prevent data race
84+
get_temp_path_func_local = (get_temp_path_func_ptr)::GetProcAddress(kernel32, "GetTempPath2W");
85+
}
86+
87+
if (get_temp_path_func_local == NULL) // method is only available with Windows 10 Creators Update or later
88+
{
89+
s_get_temp_path_func = &GetTempPathW;
90+
}
91+
else
92+
{
93+
s_get_temp_path_func = get_temp_path_func_local;
94+
}
95+
}
96+
97+
return s_get_temp_path_func(buffer_len, buffer);
98+
}
99+
}
100+
69101
bool GetModuleFileNameWrapper(HMODULE hModule, pal::string_t* recv)
70102
{
71103
pal::string_t path;
@@ -695,7 +727,7 @@ bool get_extraction_base_parent_directory(pal::string_t& directory)
695727
const size_t max_len = MAX_PATH + 1;
696728
pal::char_t temp_path[max_len];
697729

698-
size_t len = GetTempPathW(max_len, temp_path);
730+
size_t len = get_temp_path(max_len, temp_path);
699731
if (len == 0)
700732
{
701733
return false;

0 commit comments

Comments
 (0)