summaryrefslogtreecommitdiffstats
path: root/win/rfb_win32/Registry.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win/rfb_win32/Registry.cxx')
-rw-r--r--win/rfb_win32/Registry.cxx316
1 files changed, 316 insertions, 0 deletions
diff --git a/win/rfb_win32/Registry.cxx b/win/rfb_win32/Registry.cxx
new file mode 100644
index 00000000..4ece4bac
--- /dev/null
+++ b/win/rfb_win32/Registry.cxx
@@ -0,0 +1,316 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+// -=- Registry.cxx
+
+#include <rfb_win32/Registry.h>
+#include <rfb_win32/Security.h>
+#include <rfb_win32/DynamicFn.h>
+#include <rdr/MemOutStream.h>
+#include <rdr/HexOutstream.h>
+#include <rdr/HexInStream.h>
+#include <stdlib.h>
+#include <rfb/LogWriter.h>
+
+// These flags are required to control access control inheritance,
+// but are not defined by VC6's headers. These definitions comes
+// from the Microsoft Platform SDK.
+#ifndef PROTECTED_DACL_SECURITY_INFORMATION
+#define PROTECTED_DACL_SECURITY_INFORMATION (0x80000000L)
+#endif
+#ifndef UNPROTECTED_DACL_SECURITY_INFORMATION
+#define UNPROTECTED_DACL_SECURITY_INFORMATION (0x20000000L)
+#endif
+
+
+using namespace rfb;
+using namespace rfb::win32;
+
+
+static LogWriter vlog("Registry");
+
+
+RegKey::RegKey() : key(0), freeKey(false), valueNameBufLen(0) {}
+
+RegKey::RegKey(const HKEY k) : key(0), freeKey(false), valueNameBufLen(0) {
+ LONG result = RegOpenKeyEx(k, 0, 0, KEY_ALL_ACCESS, &key);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegOpenKeyEx(HKEY)", result);
+ vlog.debug("duplicated %x to %x", k, key);
+ freeKey = true;
+}
+
+RegKey::RegKey(const RegKey& k) : key(0), freeKey(false), valueNameBufLen(0) {
+ LONG result = RegOpenKeyEx(k.key, 0, 0, KEY_ALL_ACCESS, &key);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegOpenKeyEx(RegKey&)", result);
+ vlog.debug("duplicated %x to %x", k.key, key);
+ freeKey = true;
+}
+
+RegKey::~RegKey() {
+ close();
+}
+
+
+void RegKey::setHKEY(HKEY k, bool fK) {
+ vlog.debug("setHKEY(%x,%d)", k, (int)fK);
+ close();
+ freeKey = fK;
+ key = k;
+}
+
+
+bool RegKey::createKey(const RegKey& root, const TCHAR* name) {
+ close();
+ LONG result = RegCreateKey(root.key, name, &key);
+ if (result != ERROR_SUCCESS) {
+ vlog.error("RegCreateKey(%x, %s): %x", root.key, name, result);
+ throw rdr::SystemException("RegCreateKeyEx", result);
+ }
+ vlog.debug("createKey(%x,%s) = %x", root.key, (const char*)CStr(name), key);
+ freeKey = true;
+ return true;
+}
+
+void RegKey::openKey(const RegKey& root, const TCHAR* name, bool readOnly) {
+ close();
+ LONG result = RegOpenKeyEx(root.key, name, 0, readOnly ? KEY_READ : KEY_ALL_ACCESS, &key);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegOpenKeyEx (open)", result);
+ vlog.debug("openKey(%x,%s,%s) = %x", root.key, (const char*)CStr(name),
+ readOnly ? "ro" : "rw", key);
+ freeKey = true;
+}
+
+void RegKey::setDACL(const PACL acl, bool inherit) {
+ DWORD result;
+ typedef DWORD (WINAPI *_SetSecurityInfo_proto) (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID, PSID, PACL, PACL);
+ DynamicFn<_SetSecurityInfo_proto> _SetSecurityInfo(_T("advapi32.dll"), "SetSecurityInfo");
+ if (!_SetSecurityInfo.isValid())
+ throw rdr::SystemException("RegKey::setDACL failed", ERROR_CALL_NOT_IMPLEMENTED);
+ if ((result = (*_SetSecurityInfo)(key, SE_REGISTRY_KEY,
+ DACL_SECURITY_INFORMATION |
+ (inherit ? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION),
+ 0, 0, acl, 0)) != ERROR_SUCCESS)
+ throw rdr::SystemException("RegKey::setDACL failed", result);
+}
+
+void RegKey::close() {
+ if (freeKey) {
+ vlog.debug("RegCloseKey(%x)", key);
+ RegCloseKey(key);
+ key = 0;
+ }
+}
+
+void RegKey::deleteKey(const TCHAR* name) const {
+ LONG result = RegDeleteKey(key, name);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegDeleteKey", result);
+}
+
+void RegKey::deleteValue(const TCHAR* name) const {
+ LONG result = RegDeleteValue(key, name);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegDeleteValue", result);
+}
+
+void RegKey::awaitChange(bool watchSubTree, DWORD filter, HANDLE event) const {
+ LONG result = RegNotifyChangeKeyValue(key, watchSubTree, filter, event, event != 0);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegNotifyChangeKeyValue", result);
+}
+
+
+RegKey::operator HKEY() const {return key;}
+
+
+void RegKey::setExpandString(const TCHAR* valname, const TCHAR* value) const {
+ LONG result = RegSetValueEx(key, valname, 0, REG_EXPAND_SZ, (const BYTE*)value, (_tcslen(value)+1)*sizeof(TCHAR));
+ if (result != ERROR_SUCCESS) throw rdr::SystemException("setExpandString", result);
+}
+
+void RegKey::setString(const TCHAR* valname, const TCHAR* value) const {
+ LONG result = RegSetValueEx(key, valname, 0, REG_SZ, (const BYTE*)value, (_tcslen(value)+1)*sizeof(TCHAR));
+ if (result != ERROR_SUCCESS) throw rdr::SystemException("setString", result);
+}
+
+void RegKey::setBinary(const TCHAR* valname, const void* value, int length) const {
+ LONG result = RegSetValueEx(key, valname, 0, REG_BINARY, (const BYTE*)value, length);
+ if (result != ERROR_SUCCESS) throw rdr::SystemException("setBinary", result);
+}
+
+void RegKey::setInt(const TCHAR* valname, int value) const {
+ LONG result = RegSetValueEx(key, valname, 0, REG_DWORD, (const BYTE*)&value, sizeof(value));
+ if (result != ERROR_SUCCESS) throw rdr::SystemException("setInt", result);
+}
+
+void RegKey::setBool(const TCHAR* valname, bool value) const {
+ setInt(valname, value ? 1 : 0);
+}
+
+TCHAR* RegKey::getString(const TCHAR* valname) const {return getRepresentation(valname);}
+TCHAR* RegKey::getString(const TCHAR* valname, const TCHAR* def) const {
+ try {
+ return getString(valname);
+ } catch(rdr::Exception) {
+ return tstrDup(def);
+ }
+}
+
+void RegKey::getBinary(const TCHAR* valname, void** data, int* length) const {
+ TCharArray hex = getRepresentation(valname);
+ if (!rdr::HexInStream::hexStrToBin(CStr(hex.buf), (char**)data, length))
+ throw rdr::Exception("getBinary failed");
+}
+void RegKey::getBinary(const TCHAR* valname, void** data, int* length, void* def, int deflen) const {
+ try {
+ getBinary(valname, data, length);
+ } catch(rdr::Exception) {
+ if (deflen) {
+ *data = new char[deflen];
+ memcpy(*data, def, deflen);
+ } else
+ *data = 0;
+ *length = deflen;
+ }
+}
+
+int RegKey::getInt(const TCHAR* valname) const {
+ TCharArray tmp = getRepresentation(valname);
+ return _ttoi(tmp.buf);
+}
+int RegKey::getInt(const TCHAR* valname, int def) const {
+ try {
+ return getInt(valname);
+ } catch(rdr::Exception) {
+ return def;
+ }
+}
+
+bool RegKey::getBool(const TCHAR* valname) const {
+ return getInt(valname) > 0;
+}
+bool RegKey::getBool(const TCHAR* valname, bool def) const {
+ return getInt(valname, def ? 1 : 0) > 0;
+}
+
+static inline TCHAR* terminateData(char* data, int length)
+{
+ // We must terminate the string, just to be sure. Stupid Win32...
+ int len = length/sizeof(TCHAR);
+ TCharArray str(len+1);
+ memcpy(str.buf, data, length);
+ str.buf[len] = 0;
+ return str.takeBuf();
+}
+
+TCHAR* RegKey::getRepresentation(const TCHAR* valname) const {
+ DWORD type, length;
+ LONG result = RegQueryValueEx(key, valname, 0, &type, 0, &length);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("get registry value length", result);
+ CharArray data(length);
+ result = RegQueryValueEx(key, valname, 0, &type, (BYTE*)data.buf, &length);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("get registry value", result);
+
+ switch (type) {
+ case REG_BINARY:
+ {
+ TCharArray hex = rdr::HexOutStream::binToHexStr(data.buf, length);
+ return hex.takeBuf();
+ }
+ case REG_SZ:
+ if (length) {
+ return terminateData(data.buf, length);
+ } else {
+ return tstrDup(_T(""));
+ }
+ case REG_DWORD:
+ {
+ TCharArray tmp(16);
+ _stprintf(tmp.buf, _T("%u"), *((DWORD*)data.buf));
+ return tmp.takeBuf();
+ }
+ case REG_EXPAND_SZ:
+ {
+ if (length) {
+ TCharArray str(terminateData(data.buf, length));
+ DWORD required = ExpandEnvironmentStrings(str.buf, 0, 0);
+ if (required==0)
+ throw rdr::SystemException("ExpandEnvironmentStrings", GetLastError());
+ TCharArray result(required);
+ length = ExpandEnvironmentStrings(str.buf, result.buf, required);
+ if (required<length)
+ rdr::Exception("unable to expand environment strings");
+ return result.takeBuf();
+ } else {
+ return tstrDup(_T(""));
+ }
+ }
+ default:
+ throw rdr::Exception("unsupported registry type");
+ }
+}
+
+bool RegKey::isValue(const TCHAR* valname) const {
+ try {
+ TCharArray tmp = getRepresentation(valname);
+ return true;
+ } catch(rdr::Exception) {
+ return false;
+ }
+}
+
+const TCHAR* RegKey::getValueName(int i) {
+ DWORD maxValueNameLen;
+ LONG result = RegQueryInfoKey(key, 0, 0, 0, 0, 0, 0, 0, &maxValueNameLen, 0, 0, 0);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegQueryInfoKey", result);
+ if (valueNameBufLen < maxValueNameLen + 1) {
+ valueNameBufLen = maxValueNameLen + 1;
+ delete [] valueName.buf;
+ valueName.buf = new TCHAR[valueNameBufLen];
+ }
+ DWORD length = valueNameBufLen;
+ result = RegEnumValue(key, i, valueName.buf, &length, NULL, 0, 0, 0);
+ if (result == ERROR_NO_MORE_ITEMS) return 0;
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegEnumValue", result);
+ return valueName.buf;
+}
+
+const TCHAR* RegKey::getKeyName(int i) {
+ DWORD maxValueNameLen;
+ LONG result = RegQueryInfoKey(key, 0, 0, 0, 0, &maxValueNameLen, 0, 0, 0, 0, 0, 0);
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegQueryInfoKey", result);
+ if (valueNameBufLen < maxValueNameLen + 1) {
+ valueNameBufLen = maxValueNameLen + 1;
+ delete [] valueName.buf;
+ valueName.buf = new TCHAR[valueNameBufLen];
+ }
+ DWORD length = valueNameBufLen;
+ result = RegEnumKeyEx(key, i, valueName.buf, &length, NULL, 0, 0, 0);
+ if (result == ERROR_NO_MORE_ITEMS) return 0;
+ if (result != ERROR_SUCCESS)
+ throw rdr::SystemException("RegEnumKey", result);
+ return valueName.buf;
+}