Update filesystem library to use GetTempPath2 on Windows 11 (#2302)

Co-authored-by: Nicole Mazzuca <mazzucan@outlook.com>
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
This commit is contained in:
Eugene 2022-07-20 16:25:53 -07:00 коммит произвёл GitHub
Родитель 27b006e4d1
Коммит d066aef441
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 56 добавлений и 4 удалений

Просмотреть файл

@ -15,6 +15,13 @@
#include <Windows.h>
#ifdef _M_CEE_PURE
#define __crtGetTempPath2W(BufferLength, Buffer) GetTempPathW(BufferLength, Buffer)
#else // vvv !defined(_M_CEE_PURE) vvv
extern "C" _Success_(return > 0 && return < BufferLength) DWORD
__stdcall __crtGetTempPath2W(_In_ DWORD BufferLength, _Out_writes_to_opt_(BufferLength, return +1) LPWSTR Buffer);
#endif // ^^^ !defined(_M_CEE_PURE) ^^^
_FS_BEGIN
static file_type _Map_mode(int _Mode) { // map Windows file attributes to file_status
constexpr int _File_attribute_regular =
@ -162,7 +169,7 @@ _FS_DLL wchar_t* __CLRCALL_PURE_OR_CDECL _Symlink_get(wchar_t (&_Dest)[_MAX_FILE
_FS_DLL wchar_t* __CLRCALL_PURE_OR_CDECL _Temp_get(wchar_t (&_Dest)[_MAX_FILESYS_NAME]) {
// get temp directory
wchar_t _Dentry[MAX_PATH];
return _Strcpy(_Dest, GetTempPathW(MAX_PATH, _Dentry) != 0 ? _Dentry : L".");
return _Strcpy(_Dest, __crtGetTempPath2W(MAX_PATH, _Dentry) != 0 ? _Dentry : L".");
}

Просмотреть файл

@ -9,6 +9,7 @@
// Do not include or define anything else here.
// In particular, basic_string must not be included here.
#include <atomic>
#include <clocale>
#include <corecrt_terminate.h>
#include <cstdlib>
@ -761,13 +762,38 @@ _Success_(return == __std_win_error::_Success) __std_win_error
return __std_win_error{GetLastError()};
}
namespace {
_Success_(return > 0 && return < nBufferLength) DWORD WINAPI
_Stl_GetTempPath2W(_In_ DWORD nBufferLength, _Out_writes_to_opt_(nBufferLength, return +1) LPWSTR lpBuffer) {
using _Fun_ptr = decltype(&::GetTempPath2W);
_Fun_ptr _PfGetTempPath2W;
{
static _STD atomic<_Fun_ptr> _Static{nullptr};
_PfGetTempPath2W = _Static.load(_STD memory_order_relaxed);
if (!_PfGetTempPath2W) {
const auto _Kernel32 = ::GetModuleHandleW(L"kernel32.dll");
_Analysis_assume_(_Kernel32);
_PfGetTempPath2W = reinterpret_cast<_Fun_ptr>(::GetProcAddress(_Kernel32, "GetTempPath2W"));
if (!_PfGetTempPath2W) {
_PfGetTempPath2W = &::GetTempPathW;
}
_Static.store(_PfGetTempPath2W, _STD memory_order_relaxed); // overwriting with the same value is okay
}
}
return _PfGetTempPath2W(nBufferLength, lpBuffer);
}
} // unnamed namespace
[[nodiscard]] _Success_(return._Error == __std_win_error::_Success) __std_ulong_and_error
__stdcall __std_fs_get_temp_path(_Out_writes_z_(__std_fs_temp_path_max) wchar_t* const _Target) noexcept {
// calls GetTempPathW
// calls GetTempPath2W if available (Win11+), else calls GetTempPathW
// If getting the path failed, returns 0 size; otherwise, returns the size of the
// expected directory. If the path could be resolved to an existing directory,
// returns __std_win_error::_Success; otherwise, returns __std_win_error::_Max.
const auto _Size = GetTempPathW(__std_fs_temp_path_max, _Target);
const auto _Size = _Stl_GetTempPath2W(__std_fs_temp_path_max, _Target);
if (_Size == 0) {
return {0, __std_win_error{GetLastError()}};
}

Просмотреть файл

@ -27,10 +27,12 @@ namespace {
eGetSystemTimePreciseAsFileTime,
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
eGetTempPath2W,
eMaxKernel32Function
};
PVOID __KERNEL32Functions[eMaxKernel32Function > 0 ? eMaxKernel32Function : 1]{};
PVOID __KERNEL32Functions[eMaxKernel32Function]{};
// Use this macro for caching a function pointer from a DLL
#define STOREFUNCTIONPOINTER(instance, function_name) \
@ -384,6 +386,19 @@ extern "C" void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpS
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
extern "C" _Success_(return > 0 && return < BufferLength) DWORD
__stdcall __crtGetTempPath2W(_In_ DWORD BufferLength, _Out_writes_to_opt_(BufferLength, return +1) LPWSTR Buffer) {
#if !defined(_ONECORE)
// use GetTempPath2W if it is available (only on Windows 11+)...
IFDYNAMICGETCACHEDFUNCTION(GetTempPath2W) {
return pfGetTempPath2W(BufferLength, Buffer);
}
#endif // ^^^ !defined(_ONECORE) ^^^
// ...otherwise use GetTempPathW.
return GetTempPathW(BufferLength, Buffer);
}
// Helper to load all necessary Win32 API function pointers
@ -405,6 +420,10 @@ static int __cdecl initialize_pointers() {
STOREFUNCTIONPOINTER(hKernel32, GetSystemTimePreciseAsFileTime);
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
// Note that GetTempPath2W is defined as of Windows 10 Build 20348 (a server release) or Windows 11,
// but there is no "_WIN32_WINNT_WIN11" constant, so we will always dynamically load it
STOREFUNCTIONPOINTER(hKernel32, GetTempPath2W);
return 0;
}