From 4b1e6683d258412dd6e02c55618ff158c749ab4a Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 18 Aug 2014 23:00:25 +0200 Subject: - can now filter by mod content - all files/directories that require write access can now be placed in AppData instead of the MO directory --- src/shared/directoryentry.h | 2 -- src/shared/fallout3info.cpp | 4 +-- src/shared/fallout3info.h | 2 +- src/shared/falloutnvinfo.cpp | 4 +-- src/shared/falloutnvinfo.h | 2 +- src/shared/gameinfo.cpp | 83 ++++++++++++++++++++++++++++---------------- src/shared/gameinfo.h | 7 ++-- src/shared/oblivioninfo.cpp | 4 +-- src/shared/oblivioninfo.h | 2 +- src/shared/skyriminfo.cpp | 4 +-- src/shared/skyriminfo.h | 2 +- 11 files changed, 70 insertions(+), 46 deletions(-) (limited to 'src/shared') diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 1e904311..7836d719 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -280,8 +280,6 @@ public: } } m_FileRegister->removeFile(iter->second); - } else { - log ("failed to remove %ls from %ls", fileName.c_str(), m_Name.c_str()); } } diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp index ea73c7f6..9487d2de 100644 --- a/src/shared/fallout3info.cpp +++ b/src/shared/fallout3info.cpp @@ -30,8 +30,8 @@ along with Mod Organizer. If not, see . namespace MOShared { -Fallout3Info::Fallout3Info(const std::wstring &omoDirectory, const std::wstring &gameDirectory) - : GameInfo(omoDirectory, gameDirectory) +Fallout3Info::Fallout3Info(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory) + : GameInfo(moDirectory, moDataDirectory, gameDirectory) { identifyMyGamesDirectory(L"fallout3"); } diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index 7c61ca6d..8e4c260d 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -93,7 +93,7 @@ public: private: - Fallout3Info(const std::wstring &omoDirectory, const std::wstring &gameDirectory); + Fallout3Info(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); static bool identifyGame(const std::wstring &searchPath); diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp index 1715912d..9bba7fe4 100644 --- a/src/shared/falloutnvinfo.cpp +++ b/src/shared/falloutnvinfo.cpp @@ -31,8 +31,8 @@ along with Mod Organizer. If not, see . namespace MOShared { -FalloutNVInfo::FalloutNVInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory) - : GameInfo(omoDirectory, gameDirectory) +FalloutNVInfo::FalloutNVInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory) + : GameInfo(moDirectory, moDataDirectory, gameDirectory) { identifyMyGamesDirectory(L"falloutnv"); } diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index 4de67a19..cfd373c7 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -94,7 +94,7 @@ public: private: - FalloutNVInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory); + FalloutNVInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); static bool identifyGame(const std::wstring &searchPath); }; diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp index ebeff55a..f1b72cfb 100644 --- a/src/shared/gameinfo.cpp +++ b/src/shared/gameinfo.cpp @@ -27,10 +27,12 @@ along with Mod Organizer. If not, see . #include "skyriminfo.h" #include "util.h" + #include #include #include #include +#include namespace MOShared { @@ -38,8 +40,8 @@ namespace MOShared { GameInfo* GameInfo::s_Instance = NULL; -GameInfo::GameInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory) - : m_GameDirectory(gameDirectory), m_OrganizerDirectory(omoDirectory) +GameInfo::GameInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory) + : m_GameDirectory(gameDirectory), m_OrganizerDirectory(moDirectory), m_OrganizerDataDirectory(moDataDirectory) { atexit(&cleanup); } @@ -53,53 +55,68 @@ void GameInfo::cleanup() { void GameInfo::identifyMyGamesDirectory(const std::wstring &file) { + // this function attempts 3 (three!) ways to determine the correct "My Games" folder. wchar_t myDocuments[MAX_PATH]; memset(myDocuments, '\0', MAX_PATH); - ::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocuments); + m_MyGamesDirectory.clear(); + + // a) this is the way it should work. get the configured My Documents\My Games directory + if (::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocuments) == S_OK) { + m_MyGamesDirectory = std::wstring(myDocuments) + L"\\My Games"; + } - m_MyGamesDirectory.assign(myDocuments).append(L"\\My Games"); - if (!FileExists(m_MyGamesDirectory.substr().append(L"/").append(file))) { - if (::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_DEFAULT, myDocuments) != S_OK) { - m_MyGamesDirectory.assign(myDocuments).append(L"\\My Games"); + // b) if there is no directory there, look in the default directory + if (m_MyGamesDirectory.empty() + || !FileExists(m_MyGamesDirectory + L"\\" + file)) { + if (::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_DEFAULT, myDocuments) == S_OK) { + std::wstring fromDefault = std::wstring(myDocuments) + L"\\My Games"; + if (FileExists(fromDefault + L"\\" + file)) { + m_MyGamesDirectory = fromDefault; + } } } - if (!FileExists(m_MyGamesDirectory.substr().append(L"/").append(file))) { - m_MyGamesDirectory.assign(getSpecialPath(L"Personal")).append(L"\\My Games"); + // c) finally, look in the registry. This is discouraged + if (m_MyGamesDirectory.empty() + || !FileExists(m_MyGamesDirectory + L"\\" + file)) { + std::wstring fromRegistry = getSpecialPath(L"Personal") + L"\\My Games"; + if (FileExists(fromRegistry + L"\\" + file)) { + m_MyGamesDirectory = fromRegistry; + } } } -bool GameInfo::identifyGame(const std::wstring &moDirectory, const std::wstring &searchPath) +bool GameInfo::identifyGame(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &searchPath) { if (OblivionInfo::identifyGame(searchPath)) { - s_Instance = new OblivionInfo(moDirectory, searchPath); + s_Instance = new OblivionInfo(moDirectory, moDataDirectory, searchPath); } else if (Fallout3Info::identifyGame(searchPath)) { - s_Instance = new Fallout3Info(moDirectory, searchPath); + s_Instance = new Fallout3Info(moDirectory, moDataDirectory, searchPath); } else if (FalloutNVInfo::identifyGame(searchPath)) { - s_Instance = new FalloutNVInfo(moDirectory, searchPath); + s_Instance = new FalloutNVInfo(moDirectory, moDataDirectory, searchPath); } else if (SkyrimInfo::identifyGame(searchPath)) { - s_Instance = new SkyrimInfo(moDirectory, searchPath); + s_Instance = new SkyrimInfo(moDirectory, moDataDirectory, searchPath); } return s_Instance != NULL; } -bool GameInfo::init(const std::wstring &moDirectory, const std::wstring &gamePath) +bool GameInfo::init(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gamePath) { if (s_Instance == NULL) { if (gamePath.length() == 0) { // search upward in the directory until a recognized game-binary is found std::wstring searchPath(moDirectory); - while (!identifyGame(moDirectory, searchPath)) { + while (!identifyGame(moDirectory, moDataDirectory, searchPath)) { size_t lastSep = searchPath.find_last_of(L"/\\"); if (lastSep == std::string::npos) { return false; } searchPath.erase(lastSep); } - } else if (!identifyGame(moDirectory, gamePath)) { + } else if (!identifyGame(moDirectory, moDataDirectory, gamePath)) { return false; } } @@ -121,21 +138,21 @@ std::wstring GameInfo::getGameDirectory() const std::wstring GameInfo::getModsDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << L"\\mods"; + temp << m_OrganizerDataDirectory << L"\\mods"; return temp.str(); } std::wstring GameInfo::getProfilesDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << L"\\profiles"; + temp << m_OrganizerDataDirectory << L"\\profiles"; return temp.str(); } std::wstring GameInfo::getIniFilename() const { std::wostringstream temp; - temp << m_OrganizerDirectory << L"\\ModOrganizer.ini"; + temp << m_OrganizerDataDirectory << L"\\ModOrganizer.ini"; return temp.str(); } @@ -143,7 +160,7 @@ std::wstring GameInfo::getIniFilename() const std::wstring GameInfo::getDownloadDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << L"\\downloads"; + temp << m_OrganizerDataDirectory << L"\\downloads"; return temp.str(); } @@ -151,7 +168,7 @@ std::wstring GameInfo::getDownloadDir() const std::wstring GameInfo::getCacheDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << L"\\webcache"; + temp << m_OrganizerDataDirectory << L"\\webcache"; return temp.str(); } @@ -159,7 +176,7 @@ std::wstring GameInfo::getCacheDir() const std::wstring GameInfo::getOverwriteDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << "\\overwrite"; + temp << m_OrganizerDataDirectory << "\\overwrite"; return temp.str(); } @@ -167,7 +184,7 @@ std::wstring GameInfo::getOverwriteDir() const std::wstring GameInfo::getLogDir() const { std::wostringstream temp; - temp << m_OrganizerDirectory << "\\logs"; + temp << m_OrganizerDataDirectory << "\\logs"; return temp.str(); } @@ -201,17 +218,25 @@ std::vector GameInfo::getSteamVariants() const std::wstring GameInfo::getLocalAppFolder() const { - return getSpecialPath(L"Local AppData"); + wchar_t localAppFolder[MAX_PATH]; + memset(localAppFolder, '\0', MAX_PATH); + + if (::SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, localAppFolder) == S_OK) { + return localAppFolder; + } else { + // fallback: try the registry + return getSpecialPath(L"Local AppData"); + } } std::wstring GameInfo::getSpecialPath(LPCWSTR name) const { HKEY key; - LONG errorcode = ::RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", - 0, KEY_QUERY_VALUE, &key); + LONG errorcode = ::RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + 0, KEY_QUERY_VALUE, &key); if (errorcode != ERROR_SUCCESS) { - throw windows_error("failed to look up special folder", errorcode); + throw windows_error("failed to look up special folder (path)", errorcode); } WCHAR temp[MAX_PATH]; @@ -219,7 +244,7 @@ std::wstring GameInfo::getSpecialPath(LPCWSTR name) const errorcode = ::RegQueryValueExW(key, name, NULL, NULL, (LPBYTE)temp, &bufferSize); if (errorcode != ERROR_SUCCESS) { - throw windows_error("failed to look up special folder", errorcode); + throw windows_error((boost::format("failed to look up special folder (%1%)") % ToString(name, true)).str(), errorcode); } WCHAR temp2[MAX_PATH]; diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h index 33467cb9..d719a073 100644 --- a/src/shared/gameinfo.h +++ b/src/shared/gameinfo.h @@ -168,13 +168,13 @@ public: // initialise with the path to the omo directory (needs to be where hook.dll is stored). This // needs to be called before the instance can be retrieved - static bool init(const std::wstring &omoDirectory, const std::wstring &gamePath = L""); + static bool init(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gamePath = L""); static GameInfo& instance(); protected: - GameInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory); + GameInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); std::wstring getLocalAppFolder() const; const std::wstring &getMyGamesDirectory() const { return m_MyGamesDirectory; } @@ -182,7 +182,7 @@ protected: private: - static bool identifyGame(const std::wstring &omoDirectory, const std::wstring &searchPath); + static bool identifyGame(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &searchPath); std::wstring getSpecialPath(LPCWSTR name) const; static void cleanup(); @@ -195,6 +195,7 @@ private: std::wstring m_GameDirectory; std::wstring m_OrganizerDirectory; + std::wstring m_OrganizerDataDirectory; }; diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index 532e49b8..f317812f 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -31,8 +31,8 @@ along with Mod Organizer. If not, see . namespace MOShared { -OblivionInfo::OblivionInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory) - : GameInfo(omoDirectory, gameDirectory) +OblivionInfo::OblivionInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory) + : GameInfo(moDirectory, moDataDirectory, gameDirectory) { identifyMyGamesDirectory(L"oblivion"); } diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index 121cad43..02fd90b4 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -90,7 +90,7 @@ public: private: - OblivionInfo(const std::wstring &omoDirectory, const std::wstring &gameDirectory); + OblivionInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); static bool identifyGame(const std::wstring &searchPath); diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index 72452255..c985fe9f 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -33,8 +33,8 @@ along with Mod Organizer. If not, see . namespace MOShared { -SkyrimInfo::SkyrimInfo(const std::wstring &moDirectory, const std::wstring &gameDirectory) - : GameInfo(moDirectory, gameDirectory) +SkyrimInfo::SkyrimInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory) + : GameInfo(moDirectory, moDataDirectory, gameDirectory) { identifyMyGamesDirectory(L"skyrim"); diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index 3b3b6d8e..132f2aee 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -100,7 +100,7 @@ public: private: - SkyrimInfo(const std::wstring &moDirectory, const std::wstring &gameDirectory); + SkyrimInfo(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gameDirectory); static bool identifyGame(const std::wstring &searchPath); -- cgit v1.3.1