#include "registry.h"
#include "unicode.h"
#include "util/mallocHelper.h"
static const char* hKey2Str(HKEY hKey)
{
#define HKEY_CASE(compareKey) if(hKey == compareKey) return #compareKey;
HKEY_CASE(HKEY_CLASSES_ROOT)
HKEY_CASE(HKEY_CURRENT_USER)
HKEY_CASE(HKEY_LOCAL_MACHINE)
HKEY_CASE(HKEY_USERS)
HKEY_CASE(HKEY_PERFORMANCE_DATA)
HKEY_CASE(HKEY_PERFORMANCE_TEXT)
HKEY_CASE(HKEY_PERFORMANCE_NLSTEXT)
HKEY_CASE(HKEY_CURRENT_CONFIG)
HKEY_CASE(HKEY_DYN_DATA)
HKEY_CASE(HKEY_CURRENT_USER_LOCAL_SETTINGS)
#undef HKEY_CASE
return "UNKNOWN";
}
bool ffRegOpenKeyForRead(HKEY hKey, const wchar_t* subKeyW, HKEY* result, FFstrbuf* error)
{
if(RegOpenKeyExW(hKey, subKeyW, 0, KEY_READ, result) != ERROR_SUCCESS)
{
if(error)
{
FF_STRBUF_AUTO_DESTROY subKeyA = ffStrbufCreateWS(subKeyW);
ffStrbufAppendF(error, "RegOpenKeyExW(%s\\%s) failed", hKey2Str(hKey), subKeyA.chars);
}
return false;
}
return true;
}
bool ffRegReadStrbuf(HKEY hKey, const wchar_t* valueNameW, FFstrbuf* result, FFstrbuf* error)
{
DWORD bufSize; if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, NULL, RRF_RT_REG_SZ) failed", valueNameA.chars);
}
return false;
}
wchar_t* FF_AUTO_FREE resultW = (wchar_t*)malloc(bufSize);
if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_SZ, NULL, resultW, &bufSize) != ERROR_SUCCESS)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_REG_SZ) failed", valueNameA.chars);
}
return false;
}
ffStrbufSetWS(result, resultW);
return true;
}
bool ffRegReadData(HKEY hKey, const wchar_t* valueNameW, uint8_t** result, uint32_t* length, FFstrbuf* error)
{
assert(result && length);
DWORD bufSize = 0;
LONG err = RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_BINARY, NULL, NULL, &bufSize);
if(err != ERROR_SUCCESS || bufSize == 0)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, NULL, RRF_RT_REG_BINARY, NULL, NULL, &bufSize) failed", valueNameA.chars);
}
return false;
}
uint8_t* buf = (uint8_t*) malloc(bufSize);
err = RegGetValueW(hKey, NULL, valueNameW, RRF_RT_REG_BINARY, NULL, buf, &bufSize);
if(err != ERROR_SUCCESS)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, NULL, RRF_RT_REG_BINARY, NULL, length) failed", valueNameA.chars);
}
free(buf);
return false;
}
*result = buf;
*length = bufSize;
return true;
}
bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstrbuf* error)
{
DWORD bufSize = sizeof(*result);
if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_DWORD) failed", valueNameA.chars);
}
return false;
}
return true;
}
bool ffRegReadUint64(HKEY hKey, const wchar_t* valueNameW, uint64_t* result, FFstrbuf* error)
{
DWORD bufSize = sizeof(*result);
if(RegGetValueW(hKey, NULL, valueNameW, RRF_RT_QWORD, NULL, result, &bufSize) != ERROR_SUCCESS)
{
if(error)
{
if(!valueNameW)
valueNameW = L"(default)";
FF_STRBUF_AUTO_DESTROY valueNameA = ffStrbufCreateWS(valueNameW);
ffStrbufAppendF(error, "RegGetValueW(%s, result, RRF_RT_QWORD) failed", valueNameA.chars);
}
return false;
}
return true;
}
bool ffRegGetSubKey(HKEY hKey, uint32_t index, FFstrbuf* result, FFstrbuf* error)
{
DWORD bufSize = 0;
if(RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, &bufSize, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
if (error)
ffStrbufAppendS(error, "RegQueryInfoKeyW(hKey) failed");
return false;
}
++bufSize;
wchar_t* FF_AUTO_FREE resultW = (wchar_t*) malloc(bufSize * sizeof(*resultW));
if(RegEnumKeyExW(hKey, index, resultW, &bufSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
if (error)
ffStrbufAppendF(error, "RegEnumKeyExW(hKey, %u) failed", (unsigned) index);
return false;
}
ffStrbufSetWS(result, resultW);
return true;
}
bool ffRegGetNSubKeys(HKEY hKey, uint32_t* result, FFstrbuf* error)
{
DWORD buffer;
if(RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &buffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
{
if (error)
ffStrbufAppendS(error, "RegQueryInfoKeyW(hKey) failed");
return false;
}
*result = buffer;
return true;
}