
#include "stdafx.h"
#include "commrcfg.h"
#include "Trace.h"
#include "commrcfg.tmh"

// returns key for HKEY_LOCAL_MACHINE\SOFTWARE\RegistryKey\ProfileName
// creating it if it doesn't exist
// responsibility of the caller to call RegCloseKey() on the returned HKEY
static HKEY GetAppRegistryKey( )
{
	CWinApp* pApp = AfxGetApp( );
	HKEY hAppKey  = NULL;
	HKEY hSoftKey = NULL;
	HKEY hCompanyKey = NULL;
	if (RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,
        _T("SOFTWARE"),
        0,
        KEY_WRITE|KEY_READ,
		&hSoftKey) == ERROR_SUCCESS)
	{
		DWORD dw;
		if (RegCreateKeyEx(
            hSoftKey,
            pApp->m_pszRegistryKey,
            0,
            REG_NONE,
			REG_OPTION_NON_VOLATILE,
            KEY_WRITE|KEY_READ,
            NULL,
			&hCompanyKey, &dw) == ERROR_SUCCESS)
		{
			RegCreateKeyEx(
                hCompanyKey,
                pApp->m_pszProfileName,
                0,
                REG_NONE,
				REG_OPTION_NON_VOLATILE,
                KEY_WRITE|KEY_READ,
                NULL,
				&hAppKey,
                &dw
                );
		}
	}
	if (hSoftKey != NULL)
		RegCloseKey(hSoftKey);
	if (hCompanyKey != NULL)
		RegCloseKey(hCompanyKey);

	return hAppKey;
}

// returns key for:
//      HKEY_LOCAL_MACHINE\SOFTWARE\RegistryKey\AppName\lpszSection
// creating it if it doesn't exist.
// responsibility of the caller to call RegCloseKey() on the returned HKEY
static HKEY GetSectionKey(LPCTSTR lpszSection)
{
	HKEY hSectionKey = NULL;
	HKEY hAppKey = GetAppRegistryKey( );
	if (hAppKey == NULL)
		return NULL;
	DWORD dw;
	RegCreateKeyEx(
        hAppKey,
        lpszSection,
        0,
        REG_NONE,
		REG_OPTION_NON_VOLATILE,
        KEY_WRITE|KEY_READ,
        NULL,
		&hSectionKey,
        &dw);
	RegCloseKey(hAppKey);
	return hSectionKey;
}

UINT GetConfigInt(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	UINT nDefault)
{
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return nDefault;
	DWORD dwValue;
	DWORD dwType;
	DWORD dwCount = sizeof(DWORD);
	LONG lResult = RegQueryValueEx(
        hSecKey,
        lpszEntry,
        NULL,
        &dwType,
		(LPBYTE)&dwValue,
        &dwCount);
	RegCloseKey(hSecKey);
	if (lResult == ERROR_SUCCESS)
	{
		ASSERT(dwType == REG_DWORD);
		ASSERT(dwCount == sizeof(dwValue));
		return (UINT)dwValue;
	}
	return nDefault;
}

UINT64 GetConfigInt64(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	UINT64 nDefault)
{
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return nDefault;
	QWORD dwValue;
	DWORD dwType;
	DWORD dwCount = sizeof(DWORD);
	LONG lResult = RegQueryValueEx(
        hSecKey,
        lpszEntry,
        NULL,
        &dwType,
		(LPBYTE)&dwValue,
        &dwCount);
	RegCloseKey(hSecKey);
	if (lResult == ERROR_SUCCESS)
	{
        ASSERT(dwType == REG_QWORD);
		ASSERT(dwCount == sizeof(dwValue));
		return (UINT64)dwValue;
	}
	return nDefault;
}

CString GetConfigString(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	LPCTSTR lpszDefault)
{
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return lpszDefault;
	CString strValue;
	DWORD dwType, dwCount;
	LONG lResult = RegQueryValueEx(hSecKey, lpszEntry, NULL, &dwType,
		NULL, &dwCount);
	if (lResult == ERROR_SUCCESS)
	{
		ASSERT(dwType == REG_SZ);
		lResult = RegQueryValueEx(hSecKey, lpszEntry, NULL, &dwType,
			(LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)), &dwCount);
		strValue.ReleaseBuffer();
	}
	RegCloseKey(hSecKey);
	if (lResult == ERROR_SUCCESS)
	{
		ASSERT(dwType == REG_SZ);
		return strValue;
	}
	return lpszDefault;
}

BOOL GetConfigBinary(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	BYTE** ppData,
    UINT* pBytes)
{
	*ppData = NULL;
	*pBytes = 0;
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return FALSE;
	DWORD dwType, dwCount;
	LONG lResult = RegQueryValueEx(hSecKey, lpszEntry, NULL, &dwType,
		NULL, &dwCount);
	*pBytes = dwCount;
	if (lResult == ERROR_SUCCESS)
	{
		ASSERT(dwType == REG_BINARY);
		*ppData = new BYTE[*pBytes];
		lResult = RegQueryValueEx(hSecKey, lpszEntry, NULL, &dwType,
			*ppData, &dwCount);
	}
	RegCloseKey(hSecKey);
	if (lResult == ERROR_SUCCESS)
	{
		ASSERT(dwType == REG_BINARY);
		return TRUE;
	}
	else
	{
		delete [] *ppData;
		*ppData = NULL;
	}
	return FALSE;
}

BOOL WriteConfigInt(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	UINT nValue)
{
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return FALSE;
	LONG lResult = RegSetValueEx(
        hSecKey,
        lpszEntry,
        NULL,
        REG_DWORD,
		(LPBYTE)&nValue,
        sizeof(nValue)
        );
	RegCloseKey(hSecKey);
	return lResult == ERROR_SUCCESS;
}

BOOL WriteConfigInt64(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	UINT64 nValue)
{
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return FALSE;
	LONG lResult = RegSetValueEx(
        hSecKey,
        lpszEntry,
        NULL,
        REG_QWORD,
		(LPBYTE)&nValue,
        sizeof(nValue)
        );
	RegCloseKey(hSecKey);
	return lResult == ERROR_SUCCESS;
}

BOOL WriteConfigString(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	LPCTSTR lpszValue)
{
	LONG lResult;
	if (lpszEntry == NULL) //delete whole section
	{
		HKEY hAppKey = GetAppRegistryKey();
		if (hAppKey == NULL)
			return FALSE;
		lResult = ::RegDeleteKey(hAppKey, lpszSection);
		RegCloseKey(hAppKey);
	}
	else if (lpszValue == NULL)
	{
		HKEY hSecKey = GetSectionKey(lpszSection);
		if (hSecKey == NULL)
			return FALSE;
		// necessary to cast away const below
		lResult = ::RegDeleteValue(hSecKey, (LPTSTR)lpszEntry);
		RegCloseKey(hSecKey);
	}
	else
	{
		HKEY hSecKey = GetSectionKey(lpszSection);
		if (hSecKey == NULL)
			return FALSE;
		lResult = RegSetValueEx(
            hSecKey,
            lpszEntry,
            NULL,
            REG_SZ,
			(LPBYTE)lpszValue,
            (lstrlen(lpszValue)+1)*sizeof(TCHAR));
		RegCloseKey(hSecKey);
	}
	return lResult == ERROR_SUCCESS;
}

BOOL WriteConfigBinary(
    LPCTSTR lpszSection,
    LPCTSTR lpszEntry,
	LPBYTE pData,
    UINT nBytes)
{
	LONG lResult;
	HKEY hSecKey = GetSectionKey(lpszSection);
	if (hSecKey == NULL)
		return FALSE;
	lResult = RegSetValueEx(
        hSecKey,
        lpszEntry,
        NULL,
        REG_BINARY,
		pData,
        nBytes);
	RegCloseKey(hSecKey);
	return lResult == ERROR_SUCCESS;
}
