#include "pch.h" #pragma hdrstop #include "global.h" #include "ncreg.h" #include "ncstring.h" #include "ncxbase.h" #include "param.h" #include "resource.h" #include "util.h" CParam::CParam () : m_fInit(FALSE), m_eType(VALUETYPE_UNKNOWN), m_hkRoot(NULL), m_pszKeyName(NULL), m_pszDesc(NULL), m_pszHelpFile(NULL), m_dwHelpContext(0), m_uLimitText(0), m_hkEnum(NULL), m_fOptional(FALSE), m_fModified(FALSE), m_fReadOnly(FALSE), m_fOEMText(FALSE), m_fUppercase(FALSE) { } BOOL CParam::FInit(HKEY hkRoot, HKEY hkNdiParam, PWSTR pszSubKey) { HRESULT hr = S_OK; DWORD cbBuf; BYTE szBuf[VALUE_SZMAX]; UINT uTemp; DWORD dwType; HKEY hkParamInfo; // store hkRoot, pszSubKey for future reference m_hkRoot = hkRoot; m_pszKeyName = new WCHAR[lstrlenW (pszSubKey) + 1]; if (m_pszKeyName == NULL) { return(FALSE); } lstrcpyW (m_pszKeyName, pszSubKey); hr = HrRegOpenKeyEx(hkNdiParam, pszSubKey, KEY_READ, &hkParamInfo); if (FAILED(hr)) { hkParamInfo = NULL; goto error; } // Get the parameter type, use EDIT if none specified // range values (etc.) for the type. If 'type' is empty // or invalid, the "int" type is returned. cbBuf = sizeof(szBuf); hr = HrRegQueryValueEx(hkParamInfo,c_szRegParamType,&dwType,szBuf,&cbBuf); if (SUCCEEDED(hr)) { AssertSz(REG_SZ == dwType, "Expecting REG_SZ type but got something else."); } else { ((PWCHAR)szBuf)[0] = L'\0'; } InitParamType((PTSTR)szBuf); // Get the description text cbBuf = sizeof(szBuf); hr = HrRegQueryValueEx(hkParamInfo,c_szRegParamDesc,&dwType,szBuf,&cbBuf); if (SUCCEEDED(hr)) { AssertSz(REG_SZ == dwType, "Expecting REG_SZ type but got something else."); } else { // No description string lstrcpyW((WCHAR *)szBuf, SzLoadIds (IDS_NO_DESCRIPTION)); } // allocate and store description m_pszDesc = new WCHAR[lstrlenW((WCHAR *)szBuf) + 1]; if (m_pszDesc == NULL) { return(FALSE); } lstrcpyW(m_pszDesc, (WCHAR *)szBuf); // Optional parameter m_fOptional = FALSE; uTemp = Reg_QueryInt(hkParamInfo,c_szRegParamOptional,0); if (uTemp != 0) { m_fOptional = TRUE; } // Help file info m_pszHelpFile = NULL; m_dwHelpContext = 0; cbBuf = sizeof(szBuf); hr = HrRegQueryValueEx(hkParamInfo,c_szRegParamHelpFile,&dwType, szBuf,&cbBuf); if (SUCCEEDED(hr)) { AssertSz(REG_SZ == dwType, "Expecting REG_SZ type but got something else."); m_pszHelpFile = new WCHAR[lstrlenW((WCHAR *)szBuf)+1]; if (m_pszHelpFile == NULL) { return(FALSE); } lstrcpyW(m_pszHelpFile, (WCHAR *)szBuf); m_dwHelpContext = Reg_QueryInt(hkParamInfo,c_szRegParamHelpContext,0); } // Numeric Type Info if (m_vValue.IsNumeric()) { // if no step value in registry, default to 1 (default already // set in FInitParamType() ) m_vStep.FLoadFromRegistry(hkParamInfo,c_szRegParamStep); if (m_vStep.GetNumericValueAsDword() == 0) { m_vStep.SetNumericValue(1); } // get m_vMix and m_vMax from registry (no effect if doesn't exist, // defaults were set in FInitParamType() ) (VOID) m_vMin.FLoadFromRegistry(hkParamInfo,c_szRegParamMin); (VOID) m_vMax.FLoadFromRegistry(hkParamInfo,c_szRegParamMax); } // Edit type info else if (m_eType == VALUETYPE_EDIT) { // Limit text m_uLimitText = VALUE_SZMAX-1; uTemp = Reg_QueryInt(hkParamInfo,c_szRegParamLimitText,m_uLimitText); if ((uTemp > 0) && (uTemp < VALUE_SZMAX)) { m_uLimitText = uTemp; } // Read-only m_fReadOnly = FALSE; uTemp = Reg_QueryInt(hkParamInfo,c_szRegParamReadOnly,0); if (uTemp != 0) { m_fReadOnly = TRUE; } // OEMText m_fOEMText = FALSE; uTemp = Reg_QueryInt(hkParamInfo,c_szRegParamOEMText,0); if (uTemp != 0) { m_fOEMText = TRUE; } // Uppercase m_fUppercase = FALSE; uTemp = Reg_QueryInt(hkParamInfo,c_szRegParamUppercase,0); if (uTemp != 0) { m_fUppercase = TRUE; } } // Enum type info else if (m_eType == VALUETYPE_ENUM) { hr = HrRegOpenKeyEx(hkParamInfo,c_szRegParamTypeEnum,KEY_READ, &m_hkEnum); if (FAILED(hr)) { m_hkEnum = NULL; } } // Current Value m_fModified = FALSE; if (!m_vValue.FLoadFromRegistry(m_hkRoot,m_pszKeyName,hkParamInfo)) { // Use default value (current value not in registry) if (!m_vValue.FLoadFromRegistry(hkParamInfo,c_szRegParamDefault)) { // If no default in registry, assume a decent value if (m_vValue.IsNumeric()) { m_vValue.Copy(&m_vMin); } else { m_vValue.FromString(L""); } } // Keep not-present state of optional parameters. // Mark required parameters modified since we read the default. if (m_fOptional) { m_vValue.SetPresent(FALSE); } else { m_fModified = TRUE; } } // Save initial value for comparison in Param_Validate // The initial value is always valid - in case the user hand-mucks // it to something outside the specified range. m_vInitial.Copy(&m_vValue); m_fInit = TRUE; RegSafeCloseKey(hkParamInfo); return TRUE; error: // Cleanup done by destructor. return FALSE; } VOID CParam::InitParamType(PTSTR pszType) { typedef struct tagPTABLE { const WCHAR * pszToken; VALUETYPE type; DWORD dwMin; DWORD dwMax; } PTABLE; static PTABLE ptable[] = { // 1st entry is default if pszType is invalid or unknown {c_szRegParamTypeEdit, VALUETYPE_EDIT, NULL, NULL}, {c_szRegParamTypeInt, VALUETYPE_INT, SHRT_MIN, SHRT_MAX}, {c_szRegParamTypeLong, VALUETYPE_LONG, LONG_MIN,(DWORD)LONG_MAX}, {c_szRegParamTypeWord, VALUETYPE_WORD, 0, USHRT_MAX}, {c_szRegParamTypeDword, VALUETYPE_DWORD, 0, ULONG_MAX}, {c_szRegParamTypeEnum, VALUETYPE_ENUM, NULL, NULL}, {c_szRegParamTypeKeyonly, VALUETYPE_KONLY, NULL, NULL} }; UINT i; PTABLE* pt; Assert(pszType != NULL); // Lookup token in param table for (i=0; i < celems(ptable); i++) { pt = &ptable[i]; if (lstrcmpiW(pt->pszToken,pszType) == 0) { break; } } if (i >= celems(ptable)) { pt = &ptable[0]; } // Table default values m_eType = pt->type; m_vValue.Init(pt->type,0); m_vInitial.Init(pt->type,0); if (m_vValue.IsNumeric()) { m_vMin.Init(pt->type,pt->dwMin); m_vMax.Init(pt->type,pt->dwMax); m_vStep.Init(pt->type,1); } else { m_vMin.Init(pt->type,NULL); m_vMax.Init(pt->type,NULL); m_vStep.Init(pt->type,0); } } // Notes: Don't close m_hkRoot since other's may have copies of it. // ~CAdvanced will close it. // CParam::~CParam() { // Close the enum subkey RegSafeCloseKey(m_hkEnum); // free strings delete m_pszKeyName; delete m_pszDesc; delete m_pszHelpFile; // free values m_vValue.Destroy(); m_vInitial.Destroy(); m_vMin.Destroy(); m_vMax.Destroy(); m_vStep.Destroy(); } // Applies from In-Memory storage to registry BOOL CParam::Apply() { AssertSz(m_fInit,"CParam not FInit()'ed."); if (!FIsModified()) { return TRUE; // not modified, don't save. } Assert(0 == m_vValue.Compare(&m_vValue)); m_fModified = FALSE; m_vInitial.Copy(&m_vValue); return m_vValue.FSaveToRegistry(m_hkRoot,m_pszKeyName); } UINT CParam::Validate() { AssertSz(m_fInit, "CParam not FInit()'ed."); // Equal to the initial value is ok if (m_vValue.Compare(&m_vInitial) == 0) { return VALUE_OK; } // Unpresent-optional value is ok if (FIsOptional() && !m_vValue.IsPresent()) { return VALUE_OK; } // Invalid characters if (m_vValue.IsInvalidChars()) { return VALUE_BAD_CHARS; } // Empty required field if (m_vValue.IsEmptyString() && m_vValue.IsPresent() && (m_vValue.GetType() != VALUETYPE_KONLY)) { return VALUE_EMPTY; } // Numeric range if (m_vValue.IsNumeric()) { // If value is < min, out of range if (m_vValue.Compare(&m_vMin) < 0) { return VALUE_OUTOFRANGE; } // If value is > max, out of range if (m_vValue.Compare(&m_vMax) > 0) { return VALUE_OUTOFRANGE; } // Step-range Assert(m_vStep.GetNumericValueAsDword() != 0); if (((m_vValue.GetNumericValueAsDword() - m_vMin.GetNumericValueAsDword()) % m_vStep.GetNumericValueAsDword()) != 0) { return VALUE_OUTOFRANGE; } } return VALUE_OK; } VOID CParam::GetDescription(WCHAR * sz, UINT cch) { AssertSz(m_fInit, "CParam not FInit()'ed."); lstrcpynW(sz, m_pszDesc, cch); } VOID CParam::GetHelpFile(WCHAR * sz, UINT cch) { AssertSz(m_fInit, "CParam not FInit()'ed."); lstrcpynW(sz, m_pszHelpFile, cch); }