summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2020-07-23 03:01:00 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2020-11-03 11:39:03 -0500
commit3c791b092054192fcff27b599728d3482688aec8 (patch)
tree91e9ea09a5339575cf6e2ddd35a10cb57a012267 /src
parent5b13704275fc3cf02f6c3f4d4bd77d32425ad2c9 (diff)
moved registry key from "Tannin" to "Mod Organizer Team"
Diffstat (limited to 'src')
-rw-r--r--src/env.cpp160
-rw-r--r--src/env.h9
-rw-r--r--src/instancemanager.cpp31
-rw-r--r--src/instancemanager.h2
4 files changed, 196 insertions, 6 deletions
diff --git a/src/env.cpp b/src/env.cpp
index 9f0acbbd..5bed84c1 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -846,6 +846,166 @@ Association getAssociation(const QFileInfo& targetInfo)
}
+struct RegistryKeyCloser
+{
+ using pointer = HKEY;
+
+ void operator()(HKEY key)
+ {
+ if (key != 0) {
+ ::RegCloseKey(key);
+ }
+ }
+};
+
+using RegistryKeyPtr = std::unique_ptr<HKEY, RegistryKeyCloser>;
+
+RegistryKeyPtr openRegistryKey(HKEY parent, const wchar_t* name)
+{
+ HKEY subkey = 0;
+
+ auto r = ::RegOpenKeyExW(
+ parent, name,
+ 0, KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,
+ &subkey);
+
+ if (r != ERROR_SUCCESS) {
+ return {};
+ }
+
+ return RegistryKeyPtr(subkey);
+}
+
+bool keyHasValues(HKEY key)
+{
+ auto name = std::make_unique<wchar_t[]>(1000 + 1);
+ DWORD nameSize = 1000;
+
+ // note that RegEnumValueW() also enumerates the default value if it exists
+ auto r = ::RegEnumValueW(
+ key, 0, name.get(), &nameSize, nullptr, nullptr, nullptr, nullptr);
+
+ if (r != ERROR_NO_MORE_ITEMS) {
+ return true;
+ }
+
+ // no values, no default, it's empty
+ return false;
+}
+
+bool forEachSubKey(HKEY key, std::function<bool (const wchar_t* name)> f)
+{
+ auto name = std::make_unique<wchar_t[]>(1000 + 1);
+ DWORD nameSize = 1000;
+
+ DWORD i = 0;
+
+ // something would be really wrong if it had more than 100 keys
+ while (i < 100)
+ {
+ auto r = ::RegEnumKeyExW(
+ key, i, name.get(), &nameSize, nullptr, nullptr, nullptr, nullptr);
+
+ if (r == ERROR_NO_MORE_ITEMS) {
+ // no more subkeys
+ break;
+ }
+
+ if (r == ERROR_SUCCESS) {
+ // a subkey exists
+ auto subkey = openRegistryKey(key, name.get());
+
+ if (!subkey) {
+ // can't open it, stop
+ return false;
+ }
+
+ // fire callback
+ if (!f(name.get())) {
+ return false;
+ }
+ } else {
+ // something went wrong, stop
+ return false;
+ }
+
+ ++i;
+ }
+
+ return true;
+}
+
+bool isKeyEmpty(HKEY key)
+{
+ // check for any values
+ if (keyHasValues(key)) {
+ return false;
+ }
+
+ auto r = forEachSubKey(key, [&](const wchar_t* name) {
+ // a subkey exists, recursively check if it's empty
+ auto subkey = openRegistryKey(key, name);
+
+ if (!subkey) {
+ // can't open, stop
+ return false;
+ }
+
+ if (!isKeyEmpty(subkey.get())) {
+ // not empty, stop
+ return false;
+ }
+
+ // empty, go on
+ return true;
+ });
+
+ if (!r) {
+ // something went wrong or some subkey has values
+ return false;
+ }
+
+ // key has no values and has either no subkeys or all subkeys are empty
+ return true;
+}
+
+void deleteRegistryKeyIfEmpty(const QString& name)
+{
+ if (name.isEmpty()) {
+ return;
+ }
+
+ auto key = openRegistryKey(HKEY_CURRENT_USER, name.toStdWString().c_str());
+ if (!key) {
+ return;
+ }
+
+ if (!isKeyEmpty(key.get())) {
+ return;
+ }
+
+ ::RegDeleteTreeW(HKEY_CURRENT_USER, name.toStdWString().c_str());
+}
+
+bool registryValueExists(const QString& keyName, const QString& valueName)
+{
+ auto key = openRegistryKey(
+ HKEY_CURRENT_USER, keyName.toStdWString().c_str());
+
+ if (!key) {
+ return false;
+ }
+
+ DWORD type = 0;
+
+ auto r = ::RegQueryValueExW(
+ key.get(), valueName.toStdWString().c_str(),
+ nullptr, &type, nullptr, nullptr);
+
+ return (r == ERROR_SUCCESS);
+}
+
+
// returns the filename of the given process or the current one
//
std::wstring processFilename(HANDLE process=INVALID_HANDLE_VALUE)
diff --git a/src/env.h b/src/env.h
index a563f2c3..dbbd5cf4 100644
--- a/src/env.h
+++ b/src/env.h
@@ -301,6 +301,15 @@ struct Association
Association getAssociation(const QFileInfo& file);
+// returns whether the given value exists
+//
+bool registryValueExists(const QString& key, const QString& value);
+
+// deletes a registry key if it's empty or only contains empty keys
+//
+void deleteRegistryKeyIfEmpty(const QString& name);
+
+
enum class CoreDumpTypes
{
Mini = 1,
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp
index 9bcd0f3c..aa8f1d8c 100644
--- a/src/instancemanager.cpp
+++ b/src/instancemanager.cpp
@@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "settings.h"
#include "shared/appconfig.h"
#include "plugincontainer.h"
+#include "env.h"
#include <report.h>
#include <iplugingame.h>
#include <utility.h>
@@ -37,14 +38,15 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
-static const char COMPANY_NAME[] = "Tannin";
-static const char APPLICATION_NAME[] = "Mod Organizer";
-static const char INSTANCE_KEY[] = "CurrentInstance";
+const QString Organization = "Mod Organizer Team";
+const QString Application = "Mod Organizer";
+const QString InstanceValue = "CurrentInstance";
InstanceManager::InstanceManager()
- : m_AppSettings(COMPANY_NAME, APPLICATION_NAME)
+ : m_AppSettings(Organization, Application)
{
+ updateRegistryKey();
}
InstanceManager &InstanceManager::instance()
@@ -53,6 +55,23 @@ InstanceManager &InstanceManager::instance()
return s_Instance;
}
+void InstanceManager::updateRegistryKey()
+{
+ const QString OldOrganization = "Tannin";
+ const QString OldApplication = "Mod Organizer";
+ const QString OldInstanceValue = "CurrentInstance";
+
+ const QString OldRootKey = "Software\\" + OldOrganization;
+
+ if (env::registryValueExists(OldRootKey + "\\" + OldApplication, OldInstanceValue)) {
+ QSettings old(OldOrganization, OldApplication);
+ setCurrentInstance(old.value(OldInstanceValue).toString());
+ old.remove(OldInstanceValue);
+ }
+
+ env::deleteRegistryKeyIfEmpty(OldRootKey);
+}
+
void InstanceManager::overrideInstance(const QString& instanceName)
{
m_overrideInstanceName = instanceName;
@@ -70,7 +89,7 @@ QString InstanceManager::currentInstance() const
if (m_overrideInstance)
return m_overrideInstanceName;
else
- return m_AppSettings.value(INSTANCE_KEY, "").toString();
+ return m_AppSettings.value(InstanceValue, "").toString();
}
void InstanceManager::clearCurrentInstance()
@@ -82,7 +101,7 @@ void InstanceManager::clearCurrentInstance()
void InstanceManager::setCurrentInstance(const QString &name)
{
- m_AppSettings.setValue(INSTANCE_KEY, name);
+ m_AppSettings.setValue(InstanceValue, name);
}
bool InstanceManager::deleteLocalInstance(const QString &instanceId) const
diff --git a/src/instancemanager.h b/src/instancemanager.h
index 2331ebfd..7f87045d 100644
--- a/src/instancemanager.h
+++ b/src/instancemanager.h
@@ -71,6 +71,8 @@ private:
bool portableInstall() const;
bool portableInstallIsLocked() const;
+ void updateRegistryKey();
+
private:
QSettings m_AppSettings;