diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2018-12-05 16:57:00 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2018-12-05 16:57:00 -0500 |
commit | 7a336f63cc77a93362f5d4fcc274d1d908ef2f63 (patch) | |
tree | dfc8b7eb0e56d5bedd4954d44bd2ee35455999d2 /indra/llvfs | |
parent | d509e315cfedb1785723184d5f2105af0436eb57 (diff) |
SL-10153: If $APPDATA isn't already good, try SHGetFolderPath().
In that case, also update $APPDATA for child processes.
Diffstat (limited to 'indra/llvfs')
-rw-r--r-- | indra/llvfs/lldir_win32.cpp | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 9836fa28f2..3e48e086d7 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -48,10 +48,38 @@ LLDir_Win32::LLDir_Win32() // set this first: used by append() and add() methods mDirDelimiter = "\\"; + WCHAR w_str[MAX_PATH]; // Application Data is where user settings go. We rely on $APPDATA being // correct; in fact the VMP makes a point of setting it properly, since // Windows itself botches the job for non-ASCII usernames (MAINT-8087). mOSUserDir = ll_safe_string(getenv("APPDATA")); + // On Windows, it's a Bad Thing if a pathname contains ASCII question + // marks. In our experience, it means that the original pathname contained + // non-ASCII characters that were munged to '?' somewhere along the way. + // Convert to LLWString first, though, in case one of the bytes in a + // non-ASCII UTF-8 string accidentally resembles '?'. + if (utf8string_to_wstring(mOSUserDir).find(llwchar('?')) != LLWString::npos) + { + // It is really unclear what we should do if the following call fails. + // We use it, among other things, to find where to put our log file! + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, w_str))) + { + // But of course, only update mOSUserDir if SHGetFolderPathW() works. + mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); + // Not only that: update our environment so that child processes + // will see a reasonable value as well. Use _putenv_s() rather + // than _wputenv_s() because WE want to control the encoding with + // which APPDATA is passed to child processes, instead of letting + // somebody else pick it. + _putenv_s("APPDATA", mOSUserDir.c_str()); + // SL-10153: It is really tempting to make the above _putenv_s() + // call unconditional, since we've observed cases in which the + // parent viewer receives a valid non-ASCII APPDATA value while + // the child SLVersionChecker process receives one containing + // question marks. But if what we see is already valid, what do we + // gain by storing it again? + } + } // We want cache files to go on the local disk, even if the // user is on a network with a "roaming profile". @@ -63,7 +91,6 @@ LLDir_Win32::LLDir_Win32() // cleans up that version on upgrade. JC mOSCacheDir = ll_safe_string(getenv("LOCALAPPDATA")); - WCHAR w_str[MAX_PATH]; if (GetTempPath(MAX_PATH, w_str)) { if (wcslen(w_str)) /* Flawfinder: ignore */ |