From 5b5ded058c92c51ef59b34d7b6cd3d2652b15475 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 4 Jan 2020 10:57:23 -0800 Subject: [PATCH] Windows: Support long My Documents paths. --- Core/System.cpp | 11 +++++++---- UI/GameSettingsScreen.cpp | 24 +++++++++--------------- Windows/W32Util/ShellUtil.cpp | 24 +++++++++++++++++++++++- Windows/W32Util/ShellUtil.h | 4 +++- Windows/main.cpp | 1 + headless/Headless.cpp | 1 + 6 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Core/System.cpp b/Core/System.cpp index f36cbcec83..5ccd0ddd55 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -23,6 +23,9 @@ #include #include #include +#if !PPSSPP_PLATFORM(UWP) +#include "Windows/W32Util/ShellUtil.h" +#endif #endif #include @@ -560,14 +563,14 @@ void InitSysDirectories() { // We set g_Config.memStickDirectory outside. #else - wchar_t myDocumentsPath[MAX_PATH]; - const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); - const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/"; + // Caller sets this to the Documents folder. + const std::string rootMyDocsPath = g_Config.internalDataDirectory; + const std::string myDocsPath = rootMyDocsPath + "/PPSSPP/"; const std::string installedFile = path + "installed.txt"; const bool installed = File::Exists(installedFile); // If installed.txt exists(and we can determine the Documents directory) - if (installed && (result == S_OK)) { + if (installed && rootMyDocsPath.size() > 0) { #if defined(_WIN32) && defined(__MINGW32__) std::ifstream inputFile(installedFile); #else diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ae317198d6..e8c39d0a6c 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -743,13 +743,12 @@ void GameSettingsScreen::CreateViews() { SavePathInOtherChoice = systemSettings->Add(new CheckBox(&otherinstalled_, sy->T("Save path in installed.txt", "Save path in installed.txt"))); SavePathInOtherChoice->SetEnabled(false); SavePathInOtherChoice->OnClick.Handle(this, &GameSettingsScreen::OnSavePathOther); - wchar_t myDocumentsPath[MAX_PATH]; - const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); + const bool myDocsExists = W32Util::UserDocumentsPath().size() != 0; const std::string PPSSPPpath = File::GetExeDirectory(); const std::string installedFile = PPSSPPpath + "installed.txt"; installed_ = File::Exists(installedFile); otherinstalled_ = false; - if (!installed_ && result == S_OK) { + if (!installed_ && myDocsExists) { if (File::CreateEmptyFile(PPSSPPpath + "installedTEMP.txt")) { // Disable the setting whether cannot create & delete file if (!(File::Delete(PPSSPPpath + "installedTEMP.txt"))) @@ -759,7 +758,7 @@ void GameSettingsScreen::CreateViews() { } else SavePathInMyDocumentChoice->SetEnabled(false); } else { - if (installed_ && (result == S_OK)) { + if (installed_ && myDocsExists) { #ifdef _MSC_VER std::ifstream inputFile(ConvertUTF8ToWString(installedFile)); #else @@ -779,8 +778,9 @@ void GameSettingsScreen::CreateViews() { } } inputFile.close(); - } else if (result != S_OK) + } else if (!myDocsExists) { SavePathInMyDocumentChoice->SetEnabled(false); + } } #endif @@ -925,26 +925,20 @@ UI::EventReturn GameSettingsScreen::OnSavePathMydoc(UI::EventParams &e) { File::Delete(PPSSPPpath + "installed.txt"); File::CreateEmptyFile(PPSSPPpath + "installed.txt"); otherinstalled_ = false; - wchar_t myDocumentsPath[MAX_PATH]; - const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); - const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/"; + const std::string myDocsPath = W32Util::UserDocumentsPath() + "/PPSSPP/"; g_Config.memStickDirectory = myDocsPath; - } - else if (installed_) { + } else if (installed_) { File::Delete(PPSSPPpath + "installed.txt"); installed_ = false; g_Config.memStickDirectory = PPSSPPpath + "memstick/"; - } - else { + } else { std::ofstream myfile; myfile.open(PPSSPPpath + "installed.txt"); if (myfile.is_open()){ myfile.close(); } - wchar_t myDocumentsPath[MAX_PATH]; - const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath); - const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/"; + const std::string myDocsPath = W32Util::UserDocumentsPath() + "/PPSSPP/"; g_Config.memStickDirectory = myDocsPath; installed_ = true; } diff --git a/Windows/W32Util/ShellUtil.cpp b/Windows/W32Util/ShellUtil.cpp index 29386bb993..39938b3fc0 100644 --- a/Windows/W32Util/ShellUtil.cpp +++ b/Windows/W32Util/ShellUtil.cpp @@ -33,7 +33,7 @@ namespace W32Util auto idList = SHBrowseForFolder(&info); HMODULE shell32 = GetModuleHandle(L"shell32.dll"); typedef BOOL (WINAPI *SHGetPathFromIDListEx_f)(PCIDLIST_ABSOLUTE pidl, PWSTR pszPath, DWORD cchPath, GPFIDL_FLAGS uOpts); - SHGetPathFromIDListEx_f SHGetPathFromIDListEx_= (SHGetPathFromIDListEx_f)GetProcAddress(shell32, "SHGetPathFromIDListEx"); + SHGetPathFromIDListEx_f SHGetPathFromIDListEx_ = (SHGetPathFromIDListEx_f)GetProcAddress(shell32, "SHGetPathFromIDListEx"); std::string result; if (SHGetPathFromIDListEx_) { @@ -152,6 +152,28 @@ namespace W32Util return files; } + std::string UserDocumentsPath() { + std::string result; + HMODULE shell32 = GetModuleHandle(L"shell32.dll"); + typedef HRESULT(WINAPI *SHGetKnownFolderPath_f)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath); + SHGetKnownFolderPath_f SHGetKnownFolderPath_ = (SHGetKnownFolderPath_f)GetProcAddress(shell32, "SHGetKnownFolderPath"); + if (SHGetKnownFolderPath_) { + PWSTR path = nullptr; + if (SHGetKnownFolderPath_(FOLDERID_Documents, 0, nullptr, &path) == S_OK) { + result = ConvertWStringToUTF8(path); + } + if (path) + CoTaskMemFree(path); + } else { + wchar_t path[MAX_PATH]; + if (SHGetFolderPath(nullptr, CSIDL_PERSONAL, nullptr, SHGFP_TYPE_CURRENT, path) == S_OK) { + result = ConvertWStringToUTF8(path); + } + } + + return result; + } + AsyncBrowseDialog::AsyncBrowseDialog(HWND parent, UINT completeMsg, std::wstring title) : type_(DIR), parent_(parent), completeMsg_(completeMsg), title_(title), complete_(false), result_(false) { thread_ = new std::thread(std::bind(&AsyncBrowseDialog::Execute, this)); diff --git a/Windows/W32Util/ShellUtil.h b/Windows/W32Util/ShellUtil.h index da5b83ee52..8231d8c31c 100644 --- a/Windows/W32Util/ShellUtil.h +++ b/Windows/W32Util/ShellUtil.h @@ -14,6 +14,8 @@ namespace W32Util std::vector BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t*_pTitle, const wchar_t*_pInitialFolder,const wchar_t*_pFilter,const wchar_t*_pExtension); + std::string UserDocumentsPath(); + struct AsyncBrowseDialog { public: enum Type { @@ -49,4 +51,4 @@ namespace W32Util bool result_; std::string filename_; }; -} \ No newline at end of file +} diff --git a/Windows/main.cpp b/Windows/main.cpp index 24718559ed..5ceb76d849 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -493,6 +493,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin // On Win32 it makes more sense to initialize the system directories here // because the next place it was called was in the EmuThread, and it's too late by then. + g_Config.internalDataDirectory = W32Util::UserDocumentsPath(); InitSysDirectories(); // Load config up here, because those changes below would be overwritten diff --git a/headless/Headless.cpp b/headless/Headless.cpp index ed8d7cf917..72c6620c6c 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -379,6 +379,7 @@ int main(int argc, const char* argv[]) g_Config.iAudioLatency = 1; #ifdef _WIN32 + g_Config.internalDataDirectory = ""; InitSysDirectories(); #endif