commit 0ae0a972
Merge pull request #11 from sago007/KnownFolders2
Known folders2
Changed files
| M | CMakeLists.txt before |
| M | platform_folders.cpp before |
| M | sago/platform_folders.cpp before |
| M | sago/platform_folders.h before |
| M | test/integration.cpp before |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e82cf99..b6315c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,6 +58,17 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_libraries(platform_folders PRIVATE "${_CoreServices_FRAMEWORK}")
endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ # You can pass these when calling Cmake, so don't override if the user does
+ if(NOT _WIN32_WINNT AND NOT WINVER)
+ target_compile_definitions(platform_folders PRIVATE
+ _WIN32_WINNT=0x0601
+ WINVER=0x0601
+ )
+ endif()
+endif()
+
+
# Cmake's find_package search path is different based on the system
# See https://cmake.org/cmake/help/latest/command/find_package.html for the list
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
@@ -123,4 +134,6 @@ include(CTest)
# BUILD_TESTING is defined (default ON) in CTest
if(BUILD_TESTING)
add_subdirectory(test)
+ add_executable(platform_folders_sample platform_folders.cpp)
+ target_link_libraries(platform_folders_sample PRIVATE platform_folders)
endif()
diff --git a/platform_folders.cpp b/platform_folders.cpp
index 8741eaf..b1b34c9 100644
--- a/platform_folders.cpp
+++ b/platform_folders.cpp
@@ -36,8 +36,9 @@ int main() {
std::cout << "Pictures: " << sago::getPicturesFolder() << "\n";
std::cout << "Music: " << sago::getMusicFolder() << "\n";
std::cout << "Video: " << sago::getVideoFolder() << "\n";
- std::cout << "Download: " << sago::getDownloadFolder1() << "\n";
+ std::cout << "Download: " << sago::getDownloadFolder() << "\n";
std::cout << "Save Games 1: " << sago::getSaveGamesFolder1() << "\n";
+ std::cout << "Save Games 2: " << sago::getSaveGamesFolder2() << "\n";
std::vector<std::string> extraData;
sago::appendAdditionalDataDirectories(extraData);
for (size_t i=0; i < extraData.size(); ++i) {
diff --git a/sago/platform_folders.cpp b/sago/platform_folders.cpp
index c7b1709..9bf1593 100644
--- a/sago/platform_folders.cpp
+++ b/sago/platform_folders.cpp
@@ -64,25 +64,37 @@ static std::string win32_utf16_to_utf8(const wchar_t* wstr) {
return res;
}
-static std::string GetWindowsFolder(int folderId, const char* errorMsg) {
- wchar_t szPath[MAX_PATH];
- szPath[0] = 0;
- if ( !SUCCEEDED( SHGetFolderPathW( nullptr, folderId, nullptr, 0, szPath ) ) ) {
+class FreeCoTaskMemory {
+ LPWSTR pointer = NULL;
+public:
+ explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer) {};
+ ~FreeCoTaskMemory() {
+ CoTaskMemFree(pointer);
+ }
+};
+
+static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
+ LPWSTR wszPath = NULL;
+ HRESULT hr;
+ hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
+ FreeCoTaskMemory scopeBoundMemory(wszPath);
+
+ if (!SUCCEEDED(hr)) {
throw std::runtime_error(errorMsg);
}
- return win32_utf16_to_utf8(szPath);
+ return win32_utf16_to_utf8(wszPath);
}
static std::string GetAppData() {
- return GetWindowsFolder(CSIDL_APPDATA, "RoamingAppData could not be found");
+ return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
}
static std::string GetAppDataCommon() {
- return GetWindowsFolder(CSIDL_COMMON_APPDATA, "Common appdata could not be found");
+ return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
}
static std::string GetAppDataLocal() {
- return GetWindowsFolder(CSIDL_LOCAL_APPDATA, "LocalAppData could not be found");
+ return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
}
#elif defined(__APPLE__)
#include <CoreServices/CoreServices.h>
@@ -291,7 +303,7 @@ PlatformFolders::~PlatformFolders() {
std::string PlatformFolders::getDocumentsFolder() const {
#ifdef _WIN32
- return GetWindowsFolder(CSIDL_PERSONAL, "Failed to find My Documents folder");
+ return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
#elif defined(__APPLE__)
return GetMacFolder(kDocumentsFolderType, "Failed to find Documents Folder");
#else
@@ -301,7 +313,7 @@ std::string PlatformFolders::getDocumentsFolder() const {
std::string PlatformFolders::getDesktopFolder() const {
#ifdef _WIN32
- return GetWindowsFolder(CSIDL_DESKTOP, "Failed to find Desktop folder");
+ return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
#elif defined(__APPLE__)
return GetMacFolder(kDesktopFolderType, "Failed to find Desktop folder");
#else
@@ -311,7 +323,7 @@ std::string PlatformFolders::getDesktopFolder() const {
std::string PlatformFolders::getPicturesFolder() const {
#ifdef _WIN32
- return GetWindowsFolder(CSIDL_MYPICTURES, "Failed to find My Pictures folder");
+ return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
#elif defined(__APPLE__)
return GetMacFolder(kPictureDocumentsFolderType, "Failed to find Picture folder");
#else
@@ -321,8 +333,7 @@ std::string PlatformFolders::getPicturesFolder() const {
std::string PlatformFolders::getDownloadFolder1() const {
#ifdef _WIN32
- //Pre Vista. Files was downloaded to the desktop
- return GetWindowsFolder(CSIDL_DESKTOP, "Failed to find My Downloads (Desktop) folder");
+ return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
#elif defined(__APPLE__)
return GetMacFolder(kDownloadsFolderType, "Failed to find Download folder");
#else
@@ -332,7 +343,7 @@ std::string PlatformFolders::getDownloadFolder1() const {
std::string PlatformFolders::getMusicFolder() const {
#ifdef _WIN32
- return GetWindowsFolder(CSIDL_MYMUSIC, "Failed to find My Music folder");
+ return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
#elif defined(__APPLE__)
return GetMacFolder(kMusicDocumentsFolderType, "Failed to find Music folder");
#else
@@ -342,7 +353,7 @@ std::string PlatformFolders::getMusicFolder() const {
std::string PlatformFolders::getVideoFolder() const {
#ifdef _WIN32
- return GetWindowsFolder(CSIDL_MYVIDEO, "Failed to find My Video folder");
+ return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
#elif defined(__APPLE__)
return GetMacFolder(kMovieDocumentsFolderType, "Failed to find Movie folder");
#else
@@ -354,7 +365,7 @@ std::string PlatformFolders::getSaveGamesFolder1() const {
#ifdef _WIN32
//A dedicated Save Games folder was not introduced until Vista. For XP and older save games are most often saved in a normal folder named "My Games".
//Data that should not be user accessible should be placed under GetDataHome() instead
- return GetWindowsFolder(CSIDL_PERSONAL, "Failed to find My Documents folder")+"\\My Games";
+ return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder")+"\\My Games";
#elif defined(__APPLE__)
return GetMacFolder(kApplicationSupportFolderType, "Failed to find Application Support Folder");
#else
@@ -370,10 +381,14 @@ std::string getDocumentsFolder() {
return PlatformFolders().getDocumentsFolder();
}
-std::string getDownloadFolder1() {
+std::string getDownloadFolder() {
return PlatformFolders().getDownloadFolder1();
}
+std::string getDownloadFolder1() {
+ return getDownloadFolder();
+}
+
std::string getPicturesFolder() {
return PlatformFolders().getPicturesFolder();
}
@@ -390,5 +405,12 @@ std::string getSaveGamesFolder1() {
return PlatformFolders().getSaveGamesFolder1();
}
+std::string getSaveGamesFolder2() {
+#ifdef _WIN32
+ return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
+#else
+ return PlatformFolders().getSaveGamesFolder1();
+#endif
+}
} //namespace sago
diff --git a/sago/platform_folders.h b/sago/platform_folders.h
index 193fa4d..6102c81 100644
--- a/sago/platform_folders.h
+++ b/sago/platform_folders.h
@@ -124,7 +124,13 @@ std::string getDocumentsFolder();
/**
* The folder where files are downloaded.
- * @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder.
+ * @return Absolute path to the folder where files are downloaded to.
+ */
+std::string getDownloadFolder();
+
+/**
+ * The folder where files are downloaded.
+ * @note This is provided for backward compatibility. Use getDownloadFolder instead.
* @return Absolute path to the folder where files are downloaded to.
*/
std::string getDownloadFolder1();
@@ -148,7 +154,7 @@ std::string getMusicFolder();
std::string getVideoFolder();
/**
- * The base folder for storring saved games.
+ * A base folder for storring saved games.
* You must add the program name to it like this:
* @code{.cpp}
* string saved_games_folder = sago::getSaveGamesFolder1()+"/My Program Name/";
@@ -159,6 +165,20 @@ std::string getVideoFolder();
*/
std::string getSaveGamesFolder1();
+/**
+ * A base folder for storring saved games.
+ * You must add the program name to it like this:
+ * @code{.cpp}
+ * string saved_games_folder = sago::getSaveGamesFolder2()+"/My Program Name/";
+ * @endcode
+ * @note PlatformFolders provide different folders to for saved games as not all operating systems has support for Saved Games yet.
+ * It is recommended to pick the highest number (currently getSaveGamesFolder2) at the time your product enters production and stick with it
+ * @note Windows: This returns the "Saved Games" folder. This folder exist in Vista and later
+ * @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
+ * @return The folder base folder for storring save games.
+ */
+std::string getSaveGamesFolder2();
+
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/**
diff --git a/test/integration.cpp b/test/integration.cpp
index 74a456a..a3084cc 100644
--- a/test/integration.cpp
+++ b/test/integration.cpp
@@ -12,11 +12,13 @@ int main() {
// Test non-member functions
run_test(sago::getDesktopFolder());
run_test(sago::getDocumentsFolder());
+ run_test(sago::getDownloadFolder());
run_test(sago::getDownloadFolder1());
run_test(sago::getPicturesFolder());
run_test(sago::getMusicFolder());
run_test(sago::getVideoFolder());
run_test(sago::getSaveGamesFolder1());
+ run_test(sago::getSaveGamesFolder2());
// Test class methods
sago::PlatformFolders p;
run_test(p.getDocumentsFolder());