зеркало из https://github.com/microsoft/STL.git
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:
Родитель
27b006e4d1
Коммит
d066aef441
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче