@@ -712,14 +712,44 @@ std::string FindBasePath()
712712#endif
713713}
714714
715- std::string FindUserPath ()
715+ std::optional<std:: string> FindUserPath (std::optional<std::string>& invalidPath )
716716{
717717#ifdef _WIN32
718- PWSTR os_path{};
719- SHGetKnownFolderPath (FOLDERID_Documents, KF_FLAG_DEFAULT , nullptr , &os_path);
720- std::filesystem::path path (os_path);
721- CoTaskMemFree (os_path);
722- return path.string ();
718+ PWSTR osPath{};
719+ HRESULT hr = SHGetKnownFolderPath (FOLDERID_Documents, KF_FLAG_DEFAULT , nullptr , &osPath);
720+ if (FAILED (hr)) {
721+ // The path may be inaccessible due to malfunctioning cloud providers.
722+ CoTaskMemFree (osPath);
723+ invalidPath.reset ();
724+ return {};
725+ }
726+ std::wstring pathStr = osPath;
727+ CoTaskMemFree (osPath);
728+ std::filesystem::path path (pathStr);
729+ try {
730+ return path.string ();
731+ }
732+ catch (std::system_error) {
733+ // The path could not be converted into the narrow representation, convert the path
734+ // string lossily for use in an ASCII error message on the Lua side.
735+ invalidPath.reset ();
736+ std::wstring pathStr = path.wstring ();
737+ char defGlyph = ' ?' ;
738+ BOOL defGlyphUsed{};
739+ DWORD convFlags = WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS | WC_DEFAULTCHAR ;
740+ int cb = WideCharToMultiByte (CP_ACP , 0 , pathStr.c_str (), -1 , nullptr , 0 , &defGlyph, &defGlyphUsed);
741+ if (cb) {
742+ std::vector<char > buf (cb);
743+ WideCharToMultiByte (CP_ACP , 0 , pathStr.c_str (), -1 , buf.data (), cb, &defGlyph, &defGlyphUsed);
744+ for (auto & ch : buf) {
745+ if ((unsigned char )ch >= 0x80 ) {
746+ ch = ' ?' ; // Substitute characters that we can represent but can't draw.
747+ }
748+ }
749+ invalidPath = buf.data ();
750+ }
751+ return {};
752+ }
723753#else
724754 if (char const * data_home_path = getenv (" XDG_DATA_HOME" )) {
725755 return data_home_path;
@@ -755,7 +785,7 @@ sys_main_c::sys_main_c()
755785
756786 // Set the local system information
757787 basePath = FindBasePath ();
758- userPath = FindUserPath ();
788+ userPath = FindUserPath (invalidUserPath );
759789}
760790
761791bool sys_main_c::Run (int argc, char ** argv)
0 commit comments