#ifndef __ZREGISTRY_H__
#define __ZREGISTRY_H__

#include "ZString.h"

//
//  Wrapper for the registry key handle.
//

class ZRegistry
{

protected:
    HKEY  m_hKey;

public:
    ZRegistry() : m_hKey(0) {}
    ~ZRegistry() { closeKey(); }

public:
    operator HKEY () {
        return m_hKey;
    }
public:
    void closeKey() {
        if (!m_hKey) return;
        VERIFY(ERROR_SUCCESS == ::RegCloseKey(m_hKey));
        m_hKey = 0;
    }
    BOOL openKey(HKEY hBaseKey,LPCTSTR sSubKey) {
        ASSERT(hBaseKey);
        ASSERT(sSubKey);
        closeKey();
        BOOL bOK = (ERROR_SUCCESS == ::RegOpenKey(hBaseKey,sSubKey,&m_hKey));
        ASSERT(m_hKey || !bOK);
        return bOK;
    }
    BOOL createKey(HKEY hBaseKey,LPCTSTR sSubKey) {
        ASSERT(hBaseKey);
        ASSERT(sSubKey);
        closeKey();
        BOOL bOK = (ERROR_SUCCESS == ::RegCreateKey(hBaseKey,sSubKey,&m_hKey));
        ASSERT(m_hKey || !bOK);
        return bOK;
    }
    static BOOL deleteKey(HKEY hBaseKey,LPCTSTR sSubKey) {
        ASSERT(hBaseKey);
        ASSERT(sSubKey);
        return ERROR_SUCCESS == ::RegDeleteKey(hBaseKey,sSubKey);
    }
    BOOL deleteKey(LPCTSTR sSubKey) {
        ASSERT(m_hKey);
        ASSERT(sSubKey);
        return ERROR_SUCCESS == ::RegDeleteKey(m_hKey,sSubKey);
    }
    static BOOL deleteTree(HKEY hBaseKey,LPCTSTR sSubKey) {
        ASSERT(hBaseKey);
        ASSERT(sSubKey);
        return ERROR_SUCCESS == ::SHDeleteKey(hBaseKey,sSubKey);
    }
    BOOL deleteTree(LPCTSTR sSubKey) {
        ASSERT(m_hKey);
        ASSERT(sSubKey);
        return ERROR_SUCCESS == ::SHDeleteKey(m_hKey,sSubKey);
    }
    BOOL deleteValue(LPCTSTR sName) {
        ASSERT(sName);
        ASSERT(m_hKey);
        return ERROR_SUCCESS == ::RegDeleteValue(m_hKey,sName);
    }
    void setValue(LPCTSTR sName,LPCTSTR sValue) {
        ASSERT(m_hKey);
        ASSERT(sName);
        ASSERT(sValue);
        VERIFY(ERROR_SUCCESS == ::RegSetValueEx(m_hKey,sName,0,REG_SZ,(const BYTE*)sValue,sizeof(TCHAR)*_tcslen(sValue)));
    }
    BOOL queryValue(LPTSTR sValue,LPDWORD pcbValue) {
        ASSERT(m_hKey);
        ASSERT(sValue);
        *sValue = 0;
        DWORD dwType = REG_SZ;
        BOOL bOK = (ERROR_SUCCESS == ::RegQueryValueEx(m_hKey,0,0,&dwType,(LPBYTE)sValue,pcbValue));
        ASSERT(!bOK || (REG_SZ == dwType));
        return bOK;
    }
    BOOL queryValue(LPCTSTR sName,LPTSTR sValue,LPDWORD pcbValue) {
        ASSERT(m_hKey);
        ASSERT(sName);
        ASSERT(sValue);
        *sValue = 0;
        DWORD dwType = REG_SZ;
        BOOL bOK = (ERROR_SUCCESS == ::RegQueryValueEx(m_hKey,sName,0,&dwType,(LPBYTE)sValue,pcbValue));
        ASSERT(!bOK || (REG_SZ == dwType));
        return bOK;
    }
    BOOL queryValueDWORD(LPCTSTR sName,LPDWORD pValue) {
        ASSERT(m_hKey);
        ASSERT(sName);
        ASSERT(pValue);
        *pValue = 0;
        DWORD dwType = REG_DWORD;
        DWORD cbValue = sizeof(*pValue);
        BOOL bOK = (ERROR_SUCCESS == ::RegQueryValueEx(m_hKey,sName,0,&dwType,(LPBYTE)pValue,&cbValue));
        ASSERT(!bOK || (REG_DWORD == dwType));
        return bOK;
    }
    BOOL queryString(LPCTSTR sName,ZString& sValue) {
        DWORD cbValue = sValue.getBufferMax();
        return queryValue(sName,sValue.getBuffer(),&cbValue);
    }

};

#endif
