mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2024-11-24 17:14:01 +01:00
312 lines
9.8 KiB
C++
312 lines
9.8 KiB
C++
|
/* 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 <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 %p to %p", 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 %p to %p", k.key, key);
|
||
|
freeKey = true;
|
||
|
}
|
||
|
|
||
|
RegKey::~RegKey() {
|
||
|
close();
|
||
|
}
|
||
|
|
||
|
|
||
|
void RegKey::setHKEY(HKEY k, bool fK) {
|
||
|
vlog.debug("setHKEY(%p,%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(%p, %s): %lx", root.key, name, result);
|
||
|
throw rdr::SystemException("RegCreateKeyEx", result);
|
||
|
}
|
||
|
vlog.debug("createKey(%p,%s) = %p", 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(%p,%s,%s) = %p", root.key, (const char*)CStr(name),
|
||
|
readOnly ? "ro" : "rw", key);
|
||
|
freeKey = true;
|
||
|
}
|
||
|
|
||
|
void RegKey::setDACL(const PACL acl, bool inherit) {
|
||
|
DWORD result;
|
||
|
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(%p)", 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("%lu"), *((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;
|
||
|
}
|