You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
10 KiB
484 lines
10 KiB
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "global.h"
|
|
#include "value.h"
|
|
#include "util.h"
|
|
#include "ncreg.h"
|
|
#include "ncstring.h"
|
|
|
|
static const int c_valueSzMax;
|
|
|
|
CValue::CValue()
|
|
: m_fInit(FALSE),
|
|
m_eType(VALUETYPE_UNKNOWN),
|
|
m_fNumeric(FALSE),
|
|
m_fHex(FALSE),
|
|
m_fPresent(FALSE),
|
|
m_fInvalidChars(FALSE),
|
|
m_fEmptyString(FALSE),
|
|
m_psz(0)
|
|
{
|
|
}
|
|
|
|
CValue::~CValue()
|
|
{
|
|
#ifdef DBG
|
|
if (!m_fNumeric)
|
|
{
|
|
AssertSz(!m_psz, "m_psz not deallocated before ~CValue called.");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
VOID CValue::Init(VALUETYPE type, DWORD value)
|
|
{
|
|
Assert(m_fInit == FALSE);
|
|
m_fInit = TRUE;
|
|
SetType(type);
|
|
SetPresent(TRUE);
|
|
SetInvalidChars(FALSE);
|
|
SetEmptyString(FALSE);
|
|
if ((GetType() == VALUETYPE_EDIT) ||
|
|
(GetType() == VALUETYPE_ENUM) ||
|
|
(GetType() == VALUETYPE_KONLY))
|
|
{
|
|
m_fNumeric = FALSE;
|
|
m_psz = NULL;
|
|
FromString(NULL);
|
|
}
|
|
else
|
|
{
|
|
m_fNumeric = TRUE;
|
|
m_dw = value;
|
|
}
|
|
}
|
|
|
|
VOID CValue::InitNotPresent(VALUETYPE type)
|
|
{
|
|
Init(type, 0);
|
|
SetPresent(FALSE);
|
|
}
|
|
|
|
VOID CValue::Destroy()
|
|
{
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
if (!IsNumeric())
|
|
{
|
|
delete m_psz;
|
|
m_psz = NULL;
|
|
}
|
|
m_dw = NULL; // since all other values are a union, this'll clear
|
|
// out everything.
|
|
m_fInit = FALSE;
|
|
}
|
|
|
|
// copies into current object
|
|
VOID CValue::Copy(CValue *pvSrc)
|
|
{
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
Assert(pvSrc != NULL);
|
|
AssertSz(m_eType == pvSrc->m_eType,
|
|
"Can't copy from different value types.");
|
|
// Clear out the destination value
|
|
Destroy();
|
|
AssertSz( ! m_psz, "Memory should have been deallocated by Destroy()");
|
|
|
|
// Copy contents of source value
|
|
*this = *pvSrc;
|
|
|
|
// Reallocate string
|
|
if ( ! pvSrc->IsNumeric())
|
|
{
|
|
if (pvSrc->m_psz)
|
|
{
|
|
// allocate and copy string.
|
|
m_psz = new WCHAR[lstrlenW(pvSrc->m_psz) + 1];
|
|
|
|
if (m_psz == NULL)
|
|
{
|
|
Assert(0);
|
|
return;
|
|
}
|
|
|
|
lstrcpyW(m_psz,pvSrc->m_psz);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID CValue::SetNumericValue(DWORD dw)
|
|
{
|
|
Assert(m_fInit);
|
|
Assert(m_fNumeric);
|
|
switch(m_eType)
|
|
{
|
|
case VALUETYPE_DWORD:
|
|
SetDword(dw);
|
|
break;
|
|
case VALUETYPE_LONG:
|
|
SetLong(dw);
|
|
break;
|
|
case VALUETYPE_WORD:
|
|
Assert(dw <= USHRT_MAX);
|
|
SetWord(static_cast<WORD>(dw));
|
|
break;
|
|
case VALUETYPE_INT:
|
|
Assert(dw <= SHRT_MAX);
|
|
Assert(dw >= SHRT_MIN);
|
|
SetShort(static_cast<short>(dw));
|
|
break;
|
|
default:
|
|
AssertSz(FALSE, "Invalid numeric type for this value");
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL CValue::FromString(const WCHAR * const pszValue)
|
|
{
|
|
UINT uBase;
|
|
PWSTR pszEnd;
|
|
PWSTR psz;
|
|
WCHAR szTemp[VALUE_SZMAX];
|
|
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
|
|
// Fixup string
|
|
if (!pszValue)
|
|
{
|
|
szTemp[0] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
lstrcpynW(szTemp,pszValue, celems(szTemp));
|
|
StripSpaces(szTemp);
|
|
}
|
|
psz = szTemp;
|
|
|
|
// Get numeric base
|
|
uBase = IsHex() ? 16 : 10;
|
|
|
|
// Initialize to valid
|
|
SetInvalidChars(FALSE);
|
|
SetEmptyString(FALSE);
|
|
|
|
if ( ! *psz)
|
|
{
|
|
SetEmptyString(TRUE);
|
|
}
|
|
|
|
// Convert
|
|
switch (GetType())
|
|
{
|
|
default:
|
|
case VALUETYPE_INT:
|
|
SetShort((short)wcstol(psz,&pszEnd,uBase));
|
|
|
|
if (*pszEnd != L'\0')
|
|
{
|
|
SetInvalidChars(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUETYPE_LONG:
|
|
SetLong(wcstol(psz,&pszEnd,uBase));
|
|
|
|
if (*pszEnd != L'\0')
|
|
{
|
|
SetInvalidChars(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUETYPE_WORD:
|
|
SetWord((WORD)wcstoul(psz,&pszEnd,uBase));
|
|
|
|
if (*pszEnd != L'\0')
|
|
{
|
|
SetInvalidChars(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUETYPE_DWORD:
|
|
SetDword(wcstoul(psz,&pszEnd,uBase));
|
|
|
|
if (*pszEnd != L'\0')
|
|
{
|
|
SetInvalidChars(TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case VALUETYPE_ENUM:
|
|
case VALUETYPE_EDIT:
|
|
if (m_psz)
|
|
{
|
|
delete m_psz;
|
|
m_psz = NULL;
|
|
}
|
|
|
|
m_psz = new WCHAR[lstrlenW(psz) + 1];
|
|
|
|
if (m_psz == NULL)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
lstrcpyW(m_psz,psz);
|
|
break;
|
|
|
|
case VALUETYPE_KONLY:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CValue::ToString(WCHAR * sz, UINT cch)
|
|
{
|
|
UINT len;
|
|
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
Assert(sz != NULL);
|
|
|
|
switch (GetType())
|
|
{
|
|
case VALUETYPE_INT:
|
|
len = (UINT)wsprintfW(sz,L"%d",GetShort());
|
|
Assert(len+1 <= cch); // verify that we allocated enough space
|
|
break;
|
|
|
|
case VALUETYPE_LONG:
|
|
len = (UINT)wsprintfW(sz,L"%ld",GetLong());
|
|
Assert(len+1 <= cch);
|
|
break;
|
|
|
|
case VALUETYPE_WORD:
|
|
if (IsHex()) {
|
|
len = (UINT)wsprintfW(sz,L"%-2X",GetWord());
|
|
} else {
|
|
len = (UINT)wsprintfW(sz,L"%u",GetWord());
|
|
}
|
|
Assert(len+1 <= cch);
|
|
break;
|
|
|
|
case VALUETYPE_DWORD:
|
|
if (IsHex()) {
|
|
len = (UINT)wsprintfW(sz,L"%-2lX",GetDword());
|
|
} else {
|
|
len = (UINT)wsprintfW(sz,L"%lu",GetDword());
|
|
}
|
|
Assert(len+1 <= cch);
|
|
break;
|
|
|
|
case VALUETYPE_ENUM:
|
|
case VALUETYPE_EDIT:
|
|
lstrcpynW (sz, m_psz, cch);
|
|
break;
|
|
|
|
case VALUETYPE_KONLY:
|
|
Assert(cch >= 2);
|
|
lstrcpynW (sz, L"1", cch); // If present, store a "1" in the registry.
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Compares the current object to another object
|
|
// Return values: 0 = both objs are the same
|
|
// <0 = cur obj is less then the other obj
|
|
// >0 = cur obj is greater than the other obj
|
|
int CValue::Compare(CValue *pv2)
|
|
{
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
Assert(pv2 != NULL);
|
|
Assert(GetType() == pv2->GetType());
|
|
|
|
// Present/not present (present is greater than not present)
|
|
if (!IsPresent() && !pv2->IsPresent())
|
|
{
|
|
return 0;
|
|
}
|
|
if (!IsPresent() && pv2->IsPresent())
|
|
{
|
|
return -1;
|
|
}
|
|
if (IsPresent() && !pv2->IsPresent())
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// Compare
|
|
switch (GetType())
|
|
{
|
|
case VALUETYPE_INT:
|
|
if (GetShort() == pv2->GetShort())
|
|
{
|
|
return 0;
|
|
}
|
|
return (GetShort() < pv2->GetShort()) ? -1 : 1;
|
|
case VALUETYPE_LONG:
|
|
if (GetLong() == pv2->GetLong())
|
|
{
|
|
return 0;
|
|
}
|
|
return (GetLong() < pv2->GetLong())? -1 : 1;
|
|
case VALUETYPE_WORD:
|
|
if (GetWord() == pv2->GetWord())
|
|
{
|
|
return 0;
|
|
}
|
|
return (GetWord() < pv2->GetWord())? -1 : 1;
|
|
case VALUETYPE_DWORD:
|
|
if (GetDword() == pv2->GetDword())
|
|
{
|
|
return 0;
|
|
}
|
|
return (GetDword() < pv2->GetDword())? -1 : 1;
|
|
case VALUETYPE_ENUM:
|
|
case VALUETYPE_EDIT:
|
|
if ((GetPsz() != NULL) && (pv2->GetPsz() != NULL))
|
|
{
|
|
return lstrcmpW(GetPsz(),pv2->GetPsz());
|
|
}
|
|
else
|
|
{
|
|
return -2; // REVIEW: what does -2 mean?
|
|
}
|
|
case VALUETYPE_KONLY:
|
|
return 1;
|
|
default:
|
|
Assert(FALSE);
|
|
return 1; // to stop compiler warning.
|
|
}
|
|
}
|
|
|
|
// if false, then value doesn't change.
|
|
BOOL CValue::FLoadFromRegistry(HKEY hk, const WCHAR * pszValueName, HKEY hkParam /* = INVALID_HANDLE_VALUE */)
|
|
{
|
|
DWORD cbBuf;
|
|
WCHAR szBuf[VALUE_SZMAX];
|
|
DWORD dwType;
|
|
HRESULT hr = S_OK;
|
|
HKEY hkTemp;
|
|
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
Assert(hk);
|
|
Assert(pszValueName);
|
|
|
|
// determine base
|
|
SetHex(FALSE);
|
|
|
|
if (hkParam != (HKEY)INVALID_HANDLE_VALUE)
|
|
hkTemp = hkParam;
|
|
else
|
|
hkTemp = hk;
|
|
|
|
if (Reg_QueryInt(hkTemp, c_szRegParamBase,10) == 16)
|
|
{
|
|
SetHex(TRUE);
|
|
}
|
|
|
|
cbBuf = sizeof(szBuf);
|
|
|
|
hr = HrRegQueryValueEx(hk,pszValueName,&dwType,(BYTE*)szBuf,&cbBuf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
AssertSz(REG_SZ == dwType,
|
|
"Expecting REG_SZ, but got something else.");
|
|
}
|
|
if (FAILED(hr) || !szBuf[0])
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_fPresent = TRUE;
|
|
return FromString(szBuf);
|
|
}
|
|
|
|
BOOL CValue::FSaveToRegistry(HKEY hk, const WCHAR * pszValueName)
|
|
{
|
|
DWORD cbBuf;
|
|
WCHAR szBuf[VALUE_SZMAX];
|
|
|
|
AssertSz(m_fInit, "CValue class not Init'ed");
|
|
Assert(hk);
|
|
Assert(pszValueName);
|
|
if (!IsPresent())
|
|
{
|
|
RegDeleteValue(hk,pszValueName);
|
|
return TRUE;
|
|
}
|
|
|
|
ToString(szBuf,celems(szBuf));
|
|
cbBuf = CbOfSzAndTerm(szBuf);
|
|
return (RegSetValueEx(
|
|
hk,
|
|
pszValueName,
|
|
NULL,
|
|
REG_SZ,
|
|
(LPBYTE)
|
|
szBuf,
|
|
cbBuf)
|
|
== ERROR_SUCCESS);
|
|
}
|
|
|
|
int CValue::GetNumericValueAsSignedInt()
|
|
{
|
|
Assert(m_fInit);
|
|
Assert(m_fPresent);
|
|
Assert(m_fNumeric);
|
|
|
|
int nret = 0;
|
|
switch (m_eType)
|
|
{
|
|
case VALUETYPE_DWORD:
|
|
nret = GetDword();
|
|
break;
|
|
case VALUETYPE_LONG:
|
|
nret = GetLong();
|
|
break;
|
|
case VALUETYPE_WORD:
|
|
nret = GetWord();
|
|
break;
|
|
case VALUETYPE_INT:
|
|
nret = GetShort();
|
|
break;
|
|
default:
|
|
Assert("Hit default case in GetNumericValueAsSignedInt");
|
|
break;
|
|
}
|
|
|
|
return nret;
|
|
}
|
|
|
|
DWORD CValue::GetNumericValueAsDword()
|
|
{
|
|
AssertH(m_fInit);
|
|
AssertH(m_fPresent);
|
|
AssertH(m_fNumeric);
|
|
|
|
DWORD dwret = 0;
|
|
switch (m_eType)
|
|
{
|
|
case VALUETYPE_DWORD:
|
|
dwret = GetDword();
|
|
break;
|
|
case VALUETYPE_LONG:
|
|
dwret = GetLong();
|
|
break;
|
|
case VALUETYPE_WORD:
|
|
dwret = GetWord();
|
|
break;
|
|
case VALUETYPE_INT:
|
|
dwret = GetShort();
|
|
break;
|
|
default:
|
|
Assert("Hit default case in GetNumericValueAsSignedInt");
|
|
break;
|
|
}
|
|
|
|
return dwret;
|
|
}
|
|
|