summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-28 07:34:25 -0700
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-04-08 13:47:09 +0200
commit12ac98a5375f38a190925ef59bc923318a37fd0f (patch)
tree2695f64d6369edb511d25f83e4d20b42d8b3a593
parent8aa84d089e4233e17a6263cb0cf629331e63d051 (diff)
downloadmana-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.cpp6
-rw-r--r--src/utils/specialfolder.cpp55
-rw-r--r--src/utils/specialfolder.h4
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