diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-03-28 07:34:25 -0700 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2024-04-08 13:47:09 +0200 |
commit | 12ac98a5375f38a190925ef59bc923318a37fd0f (patch) | |
tree | 2695f64d6369edb511d25f83e4d20b42d8b3a593 | |
parent | 8aa84d089e4233e17a6263cb0cf629331e63d051 (diff) | |
download | mana-12ac98a5375f38a190925ef59bc923318a37fd0f.tar.gz mana-12ac98a5375f38a190925ef59bc923318a37fd0f.tar.bz2 mana-12ac98a5375f38a190925ef59bc923318a37fd0f.tar.xz mana-12ac98a5375f38a190925ef59bc923318a37fd0f.zip |
Windows: Modernize getSpecialFolderLocation
Ported from CSIDL to newer FOLDERID API and used wcstombs_s to
convert the returned path to a multi-byte string.
Fixes issues when the Windows username contains special characters.
-rw-r--r-- | src/client.cpp | 6 | ||||
-rw-r--r-- | src/utils/specialfolder.cpp | 55 | ||||
-rw-r--r-- | src/utils/specialfolder.h | 4 |
3 files changed, 32 insertions, 33 deletions
diff --git a/src/client.cpp b/src/client.cpp index 63452112..abd426ce 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1116,7 +1116,7 @@ void Client::initHomeDir() mLocalDataDir = PHYSFS_getUserDir(); mLocalDataDir += "/config/data/Mana"; #elif defined _WIN32 - mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA); + mLocalDataDir = getSpecialFolderLocation(FOLDERID_LocalAppData); if (mLocalDataDir.empty()) mLocalDataDir = PHYSFS_getUserDir(); mLocalDataDir += "/Mana"; @@ -1281,9 +1281,9 @@ void Client::initScreenshotDir() else if (mScreenshotDir.empty()) { #ifdef _WIN32 - mScreenshotDir = getSpecialFolderLocation(CSIDL_MYPICTURES); + mScreenshotDir = getSpecialFolderLocation(FOLDERID_Pictures); if (mScreenshotDir.empty()) - mScreenshotDir = getSpecialFolderLocation(CSIDL_DESKTOP); + mScreenshotDir = getSpecialFolderLocation(FOLDERID_Desktop); #else mScreenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop"; #endif diff --git a/src/utils/specialfolder.cpp b/src/utils/specialfolder.cpp index bd3e1bca..c351ba1a 100644 --- a/src/utils/specialfolder.cpp +++ b/src/utils/specialfolder.cpp @@ -1,6 +1,6 @@ /* * The Mana Client - * Copyright (C) 2010-2012 The Mana Developers + * Copyright (C) 2010-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -21,6 +21,7 @@ #ifdef _WIN32 #include "specialfolder.h" #include <windows.h> +#include <stdlib.h> #ifdef SPECIALFOLDERLOCATION_TEST // compile with -DSPECIALFOLDERLOCATION_TEST to get a standalone @@ -29,49 +30,47 @@ #endif /* - * Retrieve the pathname of special folders on win32, or an empty string - * on error / if the folder does not exist. - * See http://msdn.microsoft.com/en-us/library/bb762494(VS.85).aspx for - * a list of folder ids + * Retrieve the pathname of special folders on Windows, or an empty string + * on error. + * + * See https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid + * for a list of folder IDs. */ -std::string getSpecialFolderLocation(int folderId) +std::string getSpecialFolderLocation(const KNOWNFOLDERID &folderId) { std::string ret; - LPITEMIDLIST pItemIdList; - LPMALLOC pMalloc; - char szPath[MAX_PATH]; - - // get the item ID list for folderId - HRESULT hr = SHGetSpecialFolderLocation(NULL, folderId, &pItemIdList); - if (hr != S_OK) - return ret; + PWSTR widePath = 0; - // convert the ID list into a file system path - if (SHGetPathFromIDList(pItemIdList, szPath) == FALSE) - return ret; + HRESULT hr = SHGetKnownFolderPath(folderId, 0, NULL, &widePath); + if (hr == S_OK) + { + // determine needed bytes + size_t len; + if (wcstombs_s(&len, nullptr, 0, widePath, 0) == 0) + { + ret.resize(len - 1); // subtract null character + if (wcstombs_s(nullptr, ret.data(), len, widePath, len - 1) != 0) + ret.clear(); + } + } - // get the IMalloc pointer and free all resources we used - hr = SHGetMalloc(&pMalloc); - pMalloc->Free(pItemIdList); - pMalloc->Release(); + CoTaskMemFree(widePath); - ret = szPath; return ret; } #ifdef SPECIALFOLDERLOCATION_TEST int main() { - std::cout << "APPDATA " << getSpecialFolderLocation(CSIDL_APPDATA) + std::cout << "RoamingAppData " << getSpecialFolderLocation(FOLDERID_RoamingAppData) << std::endl; - std::cout << "DESKTOP " << getSpecialFolderLocation(CSIDL_DESKTOP) + std::cout << "Desktop " << getSpecialFolderLocation(FOLDERID_Desktop) << std::endl; - std::cout << "LOCAL_APPDATA " - << getSpecialFolderLocation(CSIDL_LOCAL_APPDATA) + std::cout << "LocalAppData " << getSpecialFolderLocation(FOLDERID_LocalAppData) << std::endl; - std::cout << "MYPICTURES " << getSpecialFolderLocation(CSIDL_MYPICTURES) + std::cout << "Pictures " << getSpecialFolderLocation(FOLDERID_Pictures) << std::endl; - std::cout << "PERSONAL " << getSpecialFolderLocation(CSIDL_PERSONAL) + std::cout << "Documents " << getSpecialFolderLocation(FOLDERID_Documents) << std::endl; } #endif diff --git a/src/utils/specialfolder.h b/src/utils/specialfolder.h index 411752a2..8570d009 100644 --- a/src/utils/specialfolder.h +++ b/src/utils/specialfolder.h @@ -1,6 +1,6 @@ /* * The Mana Client - * Copyright (C) 2010-2012 The Mana Developers + * Copyright (C) 2010-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -24,7 +24,7 @@ #ifdef _WIN32 #include <shlobj.h> #include <string> -std::string getSpecialFolderLocation(int folderId); +std::string getSpecialFolderLocation(const KNOWNFOLDERID &folderId); #endif #endif |