From bdea97399b12a1e9ede23b1fe4e8c4e28f25210e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Dec 2017 17:54:06 -0500 Subject: MAINT-8087: Use SHGetKnownFolderPath(), not SHGetSpecialFolderPath(). SHGetSpecialFolderPath() is deprecated, and empirically it appears to be failing when the user name contains non-ASCII characters. The relevant Microsoft documentation pages recommend calling SHGetKnownFolderPath() instead. Also, the SHGetSpecialFolderPath() calls had no error checking or reporting, which is why we can only say it "appears to be" failing. Make sure that if SHGetKnownFolderPath() fails, at least we try to tell somebody about it. --- indra/llvfs/lldir_win32.cpp | 62 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index ebc8fdca33..55f0a6338d 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -31,7 +31,10 @@ #include "lldir_win32.h" #include "llerror.h" #include "llrand.h" // for gLindenLabRandomNumber -#include "shlobj.h" +#include +#include +#include +#include #include #include @@ -42,30 +45,59 @@ #define PACKVERSION(major,minor) MAKELONG(minor,major) DWORD GetDllVersion(LPCTSTR lpszDllName); +namespace { + +std::string getKnownFolderPath(const std::string& desc, REFKNOWNFOLDERID folderid) +{ + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx + PWSTR wstrptr = 0; + HRESULT result = SHGetKnownFolderPath( + folderid, + KF_FLAG_DEFAULT, // no flags + NULL, // current user, no impersonation + &wstrptr); + if (result == S_OK) + { + std::string utf8 = utf16str_to_utf8str(llutf16string(wstrptr)); + // have to free the returned pointer after copying its data + CoTaskMemFree(wstrptr); + return utf8; + } + + // gack, no logging yet! + // at least say something to a developer trying to debug this... + static std::map codes + { + { E_FAIL, "E_FAIL; known folder does not have a path?" }, + { E_INVALIDARG, "E_INVALIDARG; not present on system?" } + }; + auto found = codes.find(result); + const char* text = (found == codes.end())? "unknown" : found->second; + std::cout << "*** SHGetKnownFolderPath(" << desc << ") failed with " + << result << " (" << text << ")\n"; + return {}; +} + +} // anonymous namespace + LLDir_Win32::LLDir_Win32() { mDirDelimiter = "\\"; - WCHAR w_str[MAX_PATH]; - // Application Data is where user settings go - SHGetSpecialFolderPath(NULL, w_str, CSIDL_APPDATA, TRUE); - - mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); + mOSUserDir = getKnownFolderPath("RoamingAppData", FOLDERID_RoamingAppData); // We want cache files to go on the local disk, even if the // user is on a network with a "roaming profile". // - // On XP this is: - // C:\Docments and Settings\James\Local Settings\Application Data // On Vista this is: // C:\Users\James\AppData\Local // // We used to store the cache in AppData\Roaming, and the installer // cleans up that version on upgrade. JC - SHGetSpecialFolderPath(NULL, w_str, CSIDL_LOCAL_APPDATA, TRUE); - mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str)); + mOSCacheDir = getKnownFolderPath("LocalAppData", FOLDERID_LocalAppData); + WCHAR w_str[MAX_PATH]; if (GetTempPath(MAX_PATH, w_str)) { if (wcslen(w_str)) /* Flawfinder: ignore */ @@ -73,6 +105,16 @@ LLDir_Win32::LLDir_Win32() w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash } mTempDir = utf16str_to_utf8str(llutf16string(w_str)); + + if (mOSUserDir.empty()) + { + mOSUserDir = mTempDir; + } + + if (mOSCacheDir.empty()) + { + mOSCacheDir = mTempDir; + } } else { -- cgit v1.2.3 From 867b5f5a904366810c614d7b3327f253e46e59ae Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Dec 2017 18:47:15 -0500 Subject: MAINT-8087: #include header for CoTaskMemFree() function which is required to free the pointer returned by SHGetKnownFolderPath(). --- indra/llvfs/lldir_win32.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 55f0a6338d..4d8aa0e189 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -35,6 +35,7 @@ #include #include #include +#include // CoTaskMemFree() #include #include -- cgit v1.2.3 From 870008f15b60399af6971ea746bcf7a05a8ea1db Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Dec 2017 19:33:10 -0500 Subject: MAINT-8087: New LLDir_Win32 code requires ole32 in a few more places. --- indra/test/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 8344cead57..3f12431acc 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -73,6 +73,9 @@ if (NOT WINDOWS) list(APPEND test_SOURCE_FILES llmessagetemplateparser_tut.cpp ) + set(EXTRA_WINDOWS_LIBRARIES "") +else (NOT WINDOWS) + set(EXTRA_WINDOWS_LIBRARIES ole32) endif (NOT WINDOWS) set_source_files_properties(${test_HEADER_FILES} @@ -96,6 +99,7 @@ target_link_libraries(lltest ${GOOGLEMOCK_LIBRARIES} ${PTHREAD_LIBRARY} ${WINDOWS_LIBRARIES} + ${EXTRA_WINDOWS_LIBRARIES} ${BOOST_PROGRAM_OPTIONS_LIBRARY} ${BOOST_REGEX_LIBRARY} ${BOOST_COROUTINE_LIBRARY} -- cgit v1.2.3