windows-nt/Source/XPSP1/NT/net/config/netcfg/netcomm/param.cpp
2020-09-26 16:20:57 +08:00

403 lines
9.6 KiB
C++

#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);
}