Kawe Mazidjatari 04bee896be Fix string/wstring type conflict
cppkore uses string/wstring as StringBase while we use std::string/std::wstring as string/wstring. Changed all types in cppkore to String/WString instead.
2022-05-21 21:51:35 +02:00

218 lines
6.5 KiB
C++

#pragma once
#include <cstdint>
#include "StringBase.h"
#include <Windows.h>
#include "Win32Error.h"
#include "ListBase.h"
#include "StringBase.h"
#include "RegistryHive.h"
#include "RegistryView.h"
#include "RegistryValueType.h"
namespace Win32
{
class RegistryKey
{
private:
RegistryKey(HKEY hKey, bool Writable, RegistryView View);
RegistryKey(HKEY hKey, bool Writable, bool SystemKey, RegistryView View);
public:
~RegistryKey();
// Closes all resources tied to this key
void Close();
// Flush all pending changes to the disk
void Flush();
// Creates a new subkey
RegistryKey CreateSubKey(const String& SubKey);
// Deletes a subkey
void DeleteSubKey(const String& SubKey, bool ThrowOnMissingSubKey = false);
// Deletes a subkey and all nested values
void DeleteSubKeyTree(const String& SubKey, bool ThrowOnMissingSubKey = false);
// Deletes a value
void DeleteValue(const String& Name, bool ThrowOnMissingSubKey = false);
// Opens a subkey of this instance
RegistryKey OpenSubKey(const String& Name, bool Writable = true);
// Returns a value
template<RegistryValueType T>
auto GetValue(const String& Name);
// Returns a list of value names
List<String> GetValueNames();
// Returns the type of value this key is
RegistryValueType GetValueKind(const String& Name);
// Sets a value
template<RegistryValueType T, typename Tval>
void SetValue(const String& Name, const Tval& Value);
// Returns the count of subkeys
uint32_t GetSubKeyCount();
// Returns the count of values
uint32_t GetValueCount();
// Returns the subkey names
List<String> GetSubKeyNames();
// Opens one of the base registry hives on the system
static RegistryKey OpenBaseKey(RegistryHive Hive, RegistryView View);
// Returns a key from the specified handle
static RegistryKey FromHandle(HKEY hKey, RegistryView View);
private:
// Cached key flags
HKEY _Handle;
uint32_t _State;
RegistryView _View;
String _KeyName;
// Helper routines
bool IsDirty();
bool IsSystemKey();
bool IsWritable();
// Internal routine to create a subkeu
RegistryKey CreateSubKeyInternal(const String& SubKey);
// Internal routine to delete a subkey tree
void DeleteSubKeyTreeInternal(const String& SubKey);
// Internal routine to open a subkey
RegistryKey InternalOpenSubKey(const String& SubKey, bool Writable);
// Internal routine to get a value
std::unique_ptr<uint8_t[]> InternalGetValue(const String& Name, uint64_t& ValueSize);
// Internal routine to set a value
void InternalSetValue(const String& Name, uint32_t ValueType, uint8_t* Buffer, uint64_t BufferSize);
// Internal routine to get subkey count
uint32_t InternalSubKeyCount();
// Internal routine to get value count
uint32_t InternalValueCount();
// Internal routine to get subkey names
List<String> InternalGetSubKeyNames();
// Cleans up a key name
static String FixupName(String Name);
// Cleans up a key path
static void FixupPath(String& Path);
// Internal key states
constexpr static uint32_t STATE_DIRTY = 0x1;
constexpr static uint32_t STATE_SYSTEMKEY = 0x2;
constexpr static uint32_t STATE_WRITEACCESS = 0x4;
// Maximum key lengths
constexpr static uint32_t MaxKeyLength = 255;
constexpr static uint32_t MaxValueLength = 16383;
// Internal hive names
constexpr static const char* const HiveNames[] =
{
"HKEY_CLASSES_ROOT",
"HKEY_CURRENT_USER",
"HKEY_LOCAL_MACHINE",
"HKEY_USERS",
"HKEY_PERFORMANCE_DATA",
"HKEY_CURRENT_CONFIG",
"HKEY_DYN_DATA"
};
};
template<RegistryValueType T>
inline auto RegistryKey::GetValue(const String& Name)
{
uint64_t BufferSize = 0;
auto Buffer = this->InternalGetValue(Name, BufferSize);
if constexpr (T == RegistryValueType::Dword)
{
return *(uint32_t*)Buffer.get();
}
else if constexpr (T == RegistryValueType::DwordBigEndian)
{
return _byteswap_ulong(*(uint32_t*)Buffer.get());
}
else if constexpr (T == RegistryValueType::Qword)
{
return *(uint64_t*)Buffer.get();
}
else if constexpr (T == RegistryValueType::String)
{
return String((const char*)Buffer.get());
}
else if constexpr (T == RegistryValueType::MultiString)
{
auto Result = List<String>();
uint64_t Position = 0;
// We must parse each String as we go, and ensure we haven't reached the buffer size
while (Position < BufferSize)
{
// Read the str with strlen() because it doesn't store the size of each one
auto cStr = String((const char*)(Buffer.get() + Position));
// Shift based on the size + null char...
Position += cStr.Length() + sizeof(char);
// Move the str into it's list
Result.EmplaceBack(std::move(cStr));
}
return Result;
}
else if constexpr (T == RegistryValueType::Binary)
{
RegistryBinaryBlob Blob;
Blob.Buffer = std::move(Buffer);
Blob.Size = BufferSize;
return Blob;
}
return nullptr;
}
template<RegistryValueType T, typename Tval>
inline void RegistryKey::SetValue(const String& Name, const Tval& Value)
{
if constexpr (T == RegistryValueType::Dword)
{
uint32_t LittleEndian = (uint32_t)Value;
this->InternalSetValue(Name, REG_DWORD, (uint8_t*)&LittleEndian, sizeof(uint32_t));
}
else if constexpr (T == RegistryValueType::DwordBigEndian)
{
uint32_t BigEndian = _byteswap_ulong((uint32_t)Value);
this->InternalSetValue(Name, REG_DWORD_BIG_ENDIAN, (uint8_t*)&BigEndian, sizeof(uint32_t));
}
else if constexpr (T == RegistryValueType::Qword)
{
uint64_t LittleEndian = (uint64_t)Value;
this->InternalSetValue(Name, REG_QWORD, (uint8_t*)&LittleEndian, sizeof(uint64_t));
}
else if constexpr (T == RegistryValueType::String)
{
this->InternalSetValue(Name, REG_SZ, (uint8_t*)&Value[0], Value.Length() + sizeof(char));
}
else if constexpr (T == RegistryValueType::MultiString)
{
// Calculate the resulting buffer size
uint32_t BufferSize = 0;
for (auto& Str : Value)
BufferSize += Str.Length() + sizeof(char);
auto Buffer = std::make_unique<uint8_t[]>(BufferSize);
BufferSize = 0;
// Iterate and copy the entire string including the null-char which is in StringBase<>
for (auto& Str : Value)
{
std::memcpy(Buffer.get() + BufferSize, &Str[0], Str.Length() + sizeof(char));
BufferSize += Str.Length() + sizeof(char);
}
// Pass our temporary buffer of all strings to the value
this->InternalSetValue(Name, REG_MULTI_SZ, (uint8_t*)Buffer.get(), BufferSize);
}
else if constexpr (T == RegistryValueType::Binary)
{
this->InternalSetValue(Name, REG_BINARY, (uint8_t*)Value.Buffer, Value.Size);
}
}
}