Skip to content

Commit

Permalink
Use GetTempPath2 on Windows if available (dotnet#104642)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
tommcdon and hoyosjs authored Jul 10, 2024
1 parent 4a1a076 commit e3d2dd1
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 47 deletions.
3 changes: 3 additions & 0 deletions src/coreclr/debug/createdump/createdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ extern MINIDUMP_TYPE GetMiniDumpType(DumpType dumpType);

#ifdef HOST_WINDOWS
extern std::string GetLastErrorString();
extern DWORD GetTempPathWrapper(IN DWORD nBufferLength, OUT LPSTR lpBuffer);
#else
#define GetTempPathWrapper GetTempPathA
#endif
extern void printf_status(const char* format, ...);
extern void printf_error(const char* format, ...);
2 changes: 1 addition & 1 deletion src/coreclr/debug/createdump/createdumpmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ int createdump_main(const int argc, const char* argv[])
ArrayHolder<char> tmpPath = new char[MAX_LONGPATH];
if (options.DumpPathTemplate == nullptr)
{
if (::GetTempPathA(MAX_LONGPATH, tmpPath) == 0)
if (GetTempPathWrapper(MAX_LONGPATH, tmpPath) == 0)
{
printf_error("GetTempPath failed\n");
return -1;
Expand Down
35 changes: 35 additions & 0 deletions src/coreclr/debug/createdump/createdumpwindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,38 @@ GetLastErrorString()
return result;
}


typedef DWORD(WINAPI *pfnGetTempPathA)(DWORD nBufferLength, LPSTR lpBuffer);

static volatile pfnGetTempPathA
g_pfnGetTempPathA = nullptr;


DWORD
GetTempPathWrapper(
IN DWORD nBufferLength,
OUT LPSTR lpBuffer)
{
if (g_pfnGetTempPathA == nullptr)
{
HMODULE hKernel32 = LoadLibraryExW(L"kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);

pfnGetTempPathA pLocalGetTempPathA = NULL;
if (hKernel32 != NULL)
{
// store to thread local variable to prevent data race
pLocalGetTempPathA = (pfnGetTempPathA)::GetProcAddress(hKernel32, "GetTempPath2A");
}

if (pLocalGetTempPathA == NULL) // method is only available with Windows 10 Creators Update or later
{
g_pfnGetTempPathA = &GetTempPathA;
}
else
{
g_pfnGetTempPathA = pLocalGetTempPathA;
}
}

return g_pfnGetTempPathA(nBufferLength, lpBuffer);
}
4 changes: 0 additions & 4 deletions src/coreclr/inc/longfilepathwrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ SearchPathWrapper(
_Out_opt_ LPWSTR * lpFilePart
);

DWORD WINAPI GetTempPathWrapper(
SString& lpBuffer
);

DWORD
GetModuleFileNameWrapper(
_In_opt_ HMODULE hModule,
Expand Down
41 changes: 0 additions & 41 deletions src/coreclr/utilcode/longfilepathwrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,47 +184,6 @@ GetModuleFileNameWrapper(
return ret;
}

DWORD WINAPI GetTempPathWrapper(
SString& lpBuffer
)
{
CONTRACTL
{
NOTHROW;
}
CONTRACTL_END;

HRESULT hr = S_OK;
DWORD ret = 0;
DWORD lastError = 0;

EX_TRY
{
//Change the behaviour in Redstone to retry
COUNT_T size = MAX_LONGPATH;

ret = GetTempPathW(
size,
lpBuffer.OpenUnicodeBuffer(size - 1)
);

lastError = GetLastError();
lpBuffer.CloseBuffer(ret);
}
EX_CATCH_HRESULT(hr);

if (hr != S_OK)
{
SetLastError(hr);
}
else if (ret == 0)
{
SetLastError(lastError);
}

return ret;
}

DWORD WINAPI GetEnvironmentVariableWrapper(
_In_opt_ LPCTSTR lpName,
_Out_opt_ SString& lpBuffer
Expand Down
34 changes: 33 additions & 1 deletion src/native/corehost/hostmisc/pal.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,38 @@ void pal::out_vprint_line(const pal::char_t* format, va_list vl) {
print_line_to_handle(&buffer[0], ::GetStdHandle(STD_OUTPUT_HANDLE), stdout);
}

namespace
{
typedef DWORD(WINAPI *get_temp_path_func_ptr)(DWORD buffer_len, LPWSTR buffer);
static volatile get_temp_path_func_ptr s_get_temp_path_func = nullptr;

DWORD get_temp_path(DWORD buffer_len, LPWSTR buffer)
{
if (s_get_temp_path_func == nullptr)
{
HMODULE kernel32 = ::LoadLibraryExW(L"kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);

get_temp_path_func_ptr get_temp_path_func_local = NULL;
if (kernel32 != NULL)
{
// store to thread local variable to prevent data race
get_temp_path_func_local = (get_temp_path_func_ptr)::GetProcAddress(kernel32, "GetTempPath2W");
}

if (get_temp_path_func_local == NULL) // method is only available with Windows 10 Creators Update or later
{
s_get_temp_path_func = &GetTempPathW;
}
else
{
s_get_temp_path_func = get_temp_path_func_local;
}
}

return s_get_temp_path_func(buffer_len, buffer);
}
}

bool GetModuleFileNameWrapper(HMODULE hModule, pal::string_t* recv)
{
pal::string_t path;
Expand Down Expand Up @@ -695,7 +727,7 @@ bool get_extraction_base_parent_directory(pal::string_t& directory)
const size_t max_len = MAX_PATH + 1;
pal::char_t temp_path[max_len];

size_t len = GetTempPathW(max_len, temp_path);
size_t len = get_temp_path(max_len, temp_path);
if (len == 0)
{
return false;
Expand Down

0 comments on commit e3d2dd1

Please sign in to comment.