#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(dw)); break; case VALUETYPE_INT: Assert(dw <= SHRT_MAX); Assert(dw >= SHRT_MIN); SetShort(static_cast(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; }