void DVLib::RegistryDeleteKey(HKEY root, const std::wstring& key, DWORD ulFlags)
{
    DWORD namesize, subkeys, maxkeyname;
    if (ERROR_SUCCESS != ::RegDeleteKey(root, key.c_str()))
    {
        HKEY reg = NULL;

        CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg), 
            L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'");

        auto_hkey reg_ptr(reg); 

        // query subkey information
        CHECK_WIN32_DWORD(::RegQueryInfoKey(reg, NULL, NULL, NULL, & subkeys, & maxkeyname, NULL, NULL, NULL, NULL, NULL, NULL), 
            L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"' for subkeys");

        // walk through all subkeys, and recursively delete
        wchar_t name[MAX_PATH] = {0};
        namesize = MAX_PATH;

        while (ERROR_SUCCESS == ::RegEnumKeyEx(reg, 0, name, & namesize, NULL, NULL, NULL, NULL))
        {
            RegistryDeleteKey(root, key + L"\\" + name, ulFlags);
            namesize = MAX_PATH;
        }

        CHECK_WIN32_DWORD(::RegDeleteKey(root, key.c_str()), 
            L"Error deleting '" << HKEY2wstring(root) << L"\\" << key << L"'");
    }
}
std::wstring DVLib::RegistryGetStringValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;

    CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg),
        L"Error opening " << HKEY2wstring(root) << L"\\" << key);

    auto_hkey reg_ptr(reg);

    DWORD dwSize = 0;
    DWORD dwType = 0;

    CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value size:");

    CHECK_BOOL(dwType == REG_SZ || dwType == REG_EXPAND_SZ,
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value, unexpected type " << dwType);

    std::wstring value;
    if (dwSize > 0)
    {
        value.resize(dwSize / sizeof(WCHAR));

        CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& * value.begin()), & dwSize),
            L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value data");

        value.resize((dwSize - 1) / sizeof(WCHAR));
    }

    return value;
}
void DVLib::RegistryDeleteValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;
    CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_WRITE, & reg), 
        L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'");
    auto_hkey reg_ptr(reg);
    CHECK_WIN32_DWORD(::RegDeleteValue(reg, name.c_str()),
        L"Error deleting '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"'");
}
 i2c_ctrl::reg_ptr & i2c_ctrl::regs(std::size_t idx)
 {
   if (register_blocks[idx].get()==nullptr)
     {
       register_blocks[idx] = reg_ptr( physical_addresses[idx]
                                     , register_block_size
                                     );
     }
   return register_blocks[idx];
 }
std::vector<std::wstring> DVLib::RegistryGetMultiStringValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;

    CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg),
        L"Error opening " << HKEY2wstring(root) << L"\\" << key);

    auto_hkey reg_ptr(reg);

    DWORD dwSize = 0;
    DWORD dwType = 0;

    CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value size");

    CHECK_BOOL(dwType == REG_MULTI_SZ,
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value, unexpected type " << dwType);

    std::vector<std::wstring> result;
    std::vector<wchar_t> value;
    if (dwSize > 0)
    {
        value.resize(dwSize / sizeof(WCHAR));

        CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& * value.begin()), & dwSize),
            L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value data");

        value.resize((dwSize - 1) / sizeof(WCHAR));

        std::vector<wchar_t>::iterator l = value.begin();
        std::vector<wchar_t>::iterator r = value.begin();
        while(r != value.end())
        {
            if (* r == 0)
            {
                if (l == r) 
                    result.push_back(L"");
                else 
                    result.push_back(std::wstring(l, r));
                l = r + 1;
            }
            r++;
        }
    }

    return result;
}
DWORD DVLib::RegistryGetValueType(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;

    CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg),
        L"Error opening " << HKEY2wstring(root) << L"\\" << key);

    auto_hkey reg_ptr(reg);

    DWORD dwSize = 0;
    DWORD dwType = 0;

    CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"'");

    return dwType;
}
bool DVLib::RegistryValueExists(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;
    DWORD dwErr = ::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg);
    auto_hkey reg_ptr(reg);

    bool result = true;
    switch(dwErr)
    {
    case ERROR_SUCCESS:
        break;
    case ERROR_FILE_NOT_FOUND:
        result = false;
        break;
    default:
        CHECK_WIN32_DWORD(dwErr,
            L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"' exists");
        break;
    }

    if (result)
    {
        DWORD dwSize = 0;
        DWORD dwType = 0;
        dwErr = ::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize);
        switch(dwErr)
        {
        case ERROR_SUCCESS:
        case ERROR_INSUFFICIENT_BUFFER:
            break;
        case ERROR_FILE_NOT_FOUND:
            result = false;
            break;
        default:
            CHECK_WIN32_DWORD(dwErr,
                L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' exists");
            break;        
        }
    }

    return result;
}
bool DVLib::RegistryKeyExists(HKEY root, const std::wstring& key, DWORD ulFlags)
{
    HKEY reg = NULL;
    DWORD dwErr = ::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg);
    auto_hkey reg_ptr(reg);

    bool result = true;
    switch(dwErr)
    {
    case ERROR_SUCCESS:
        break;
    case ERROR_FILE_NOT_FOUND:
        result = false;
        break;
    default:
        CHECK_WIN32_DWORD(dwErr,
            L"Error checking whether '" << HKEY2wstring(root) << L"\\" << key << L"' exists");
        break;
    }

    return result;
}
DWORD DVLib::RegistryGetDWORDValue(HKEY root, const std::wstring& key, const std::wstring& name, DWORD ulFlags)
{
    HKEY reg = NULL;

    CHECK_WIN32_DWORD(::RegOpenKeyEx(root, key.c_str(), 0, ulFlags | KEY_READ, & reg),
        L"Error opening '" << HKEY2wstring(root) << L"\\" << key << L"'");

    auto_hkey reg_ptr(reg);

    DWORD dwSize = 0;
    DWORD dwType = 0;

    CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, NULL, & dwSize),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' size");

    CHECK_BOOL(dwType == REG_DWORD && dwSize == sizeof(DWORD),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"', unexpected type");

    DWORD value = 0;
    CHECK_WIN32_DWORD(::RegQueryValueEx(reg, name.c_str(), 0, & dwType, reinterpret_cast<LPBYTE>(& value), & dwSize),
        L"Error quering '" << HKEY2wstring(root) << L"\\" << key << L"\\" << name << L"' value");
    return value;
}