windows-nt/Source/XPSP1/NT/net/snmp/newagent/exe/registry.c

597 lines
14 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992-1997 Microsoft Corporation
Module Name:
registry.c
Abstract:
Contains routines for manipulating registry parameters.
Environment:
User Mode - Win32
Revision History:
10-Feb-1997 DonRyan
Rewrote to implement SNMPv2 support.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "globals.h"
#include "registry.h"
#include "contexts.h"
#include "regions.h"
#include "trapmgrs.h"
#include "snmpmgrs.h"
#include "snmpmgmt.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Private procedures //
// //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
INT
InitRegistryNotifiers(
)
/*++
Routine Description:
Setup registry notifiers
Arguments:
None.
Return Values:
Returns the number of events that have been registered successfully
--*/
{
DWORD nEvents = 0;
// on first call only create the default notifier
if (g_hDefaultRegNotifier == NULL)
g_hDefaultRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hDefaultKey == NULL)
{
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REG_KEY_SNMP_PARAMETERS,
0,
KEY_READ,
&g_hDefaultKey
);
}
// setup the default registry notifier
if (g_hDefaultRegNotifier &&
g_hDefaultKey &&
RegNotifyChangeKeyValue(
g_hDefaultKey,
TRUE,
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
g_hDefaultRegNotifier,
TRUE
) == ERROR_SUCCESS)
{
SNMPDBG((SNMP_LOG_TRACE,
"SNMP: REG: Default reg notifier initialized successfully.\n"));
nEvents++;
}
#ifdef _POLICY
// on first call only create the policy notifier
if (g_hPolicyRegNotifier == NULL)
g_hPolicyRegNotifier = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hPolicyKey == NULL)
{
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REG_POLICY_ROOT,
0,
KEY_READ,
&g_hPolicyKey
);
}
// setup the policy registry notifier
if (g_hPolicyRegNotifier &&
g_hPolicyKey &&
RegNotifyChangeKeyValue(
g_hPolicyKey,
TRUE,
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
g_hPolicyRegNotifier,
TRUE
) == ERROR_SUCCESS)
{
SNMPDBG((SNMP_LOG_TRACE,
"SNMP: REG: Policy reg notifier initialized successfully.\n"));
nEvents++;
}
SNMPDBG((SNMP_LOG_TRACE,
"SNMP: REG: Initialized notifiers ... %d.\n", nEvents));
#endif
return nEvents;
}
BOOL UnloadRegistryNotifiers();
INT
WaitOnRegNotification(
)
/*++
Routine Description:
Blocking call - waits for a notification that one of the registry parameters has change
Arguments:
None.
Return Values:
Returns the notifyer index (0 for the termination event, !=0 for parameter change)
--*/
{
HANDLE hNotifiers[3]; // hack - we now (hardcoded) that we are not going to wait for more than three events.
DWORD dwNotifiers = 0;
DWORD retCode;
hNotifiers[dwNotifiers++] = g_hTerminationEvent;
if (g_hDefaultRegNotifier != NULL)
hNotifiers[dwNotifiers++] = g_hDefaultRegNotifier;
#ifdef _POLICY
if (g_hPolicyRegNotifier != NULL)
hNotifiers[dwNotifiers++] = g_hPolicyRegNotifier;
#endif
SNMPDBG((SNMP_LOG_WARNING,
"SNMP: REG: Will listen for params changes on %d notifiers.\n",
dwNotifiers));
retCode = WaitForMultipleObjects(
dwNotifiers,
hNotifiers,
FALSE,
INFINITE);
UnloadRegistryNotifiers();
return retCode;
}
/*++
Inplace parser for the string formatted OID.
It is done in O(n) where n is the length of the string formatted OID (two passes)
--*/
BOOL
ConvStringToOid(
LPTSTR pStr,
AsnObjectIdentifier *pOid)
{
LPTSTR pDup;
int iComp;
DWORD dwCompValue;
enum
{ DOT,
DIGIT
} state = DIGIT;
// no need to check for parameters consistency (internal call->correct call :o)
// check the consistency and determine the number of components
pOid->idLength = 0;
if (*pStr == _T('.')) // skip a possible leading '.'
pStr++;
for (pDup = pStr; *pDup != _T('\0'); pDup++)
{
switch(state)
{
case DOT:
// note: a trailing dot results in a trailing 0
if (*pDup == _T('.'))
{
pOid->idLength++;
state = DIGIT;
break;
}
// intentionally missing 'break'
case DIGIT:
if (*pDup < _T('0') || *pDup > _T('9'))
return FALSE;
state = DOT;
break;
}
}
// add one to the id length as a trailing dot might not be present
pOid->idLength++;
// accept oids with two components at least;
// alloc memory and check for success;
if (pOid->idLength < 2 ||
(pOid->ids = SnmpUtilMemAlloc(pOid->idLength * sizeof(UINT))) == NULL)
return FALSE;
// we have now enough buffer and a correct input string. Just convert it to OID
iComp = 0;
dwCompValue = 0;
for (pDup = pStr; *pDup != _T('\0'); pDup++)
{
if (*pDup == _T('.'))
{
pOid->ids[iComp++] = dwCompValue;
dwCompValue = 0;
}
else
{
dwCompValue = dwCompValue * 10 + (*pDup - _T('0'));
}
}
pOid->ids[iComp] = dwCompValue;
return TRUE;
}
BOOL
LoadScalarParameters(
)
/*++
Routine Description:
Reads authentication trap flags key and manager timeout value.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
HKEY hKey;
LONG lStatus;
DWORD dwIndex;
DWORD dwNameSize;
DWORD dwValueSize;
DWORD dwValueType;
TCHAR szName[MAX_PATH];
TCHAR szValue[MAX_PATH];
LPTSTR pszKey = REG_KEY_SNMP_PARAMETERS;
BOOL bChangedSysID = FALSE;
// default value for the IsnmpNameResolutionRetries counter
// an address will resist to no more than MGRADDR_DYING (16 by default)
// consecutive name resolution failures.
snmpMgmtBase.AsnIntegerPool[IsnmpNameResolutionRetries].asnValue.number = MGRADDR_DYING;
// open registry subkey
lStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pszKey,
0,
KEY_READ,
&hKey
);
// validate return code
if (lStatus == ERROR_SUCCESS)
{
// initialize
dwIndex = 0;
// loop until error or end of list
while (lStatus == ERROR_SUCCESS)
{
// initialize buffer sizes
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
dwValueSize = sizeof(szValue); // size in number of bytes
// read next value
lStatus = RegEnumValue(
hKey,
dwIndex,
szName,
&dwNameSize,
NULL,
&dwValueType,
(LPBYTE)szValue,
&dwValueSize
);
// validate return code
if (lStatus == ERROR_SUCCESS)
{
// validate name of value
if (!lstrcmpi(szName, REG_VALUE_AUTH_TRAPS))
{
// set the 'EnableAuthenTraps' in the internal management structure
mgmtISet(IsnmpEnableAuthenTraps, *((PDWORD)&szValue));
}
else if (!lstrcmpi(szName, REG_VALUE_MGRRES_COUNTER))
{
// set the 'NameResolutionRetries' in the internal management structure
mgmtISet(IsnmpNameResolutionRetries, *((PDWORD)&szValue));
}
// next
dwIndex++;
}
}
RegCloseKey(hKey);
}
// look into MIB2 subtree ..SNMP\Parameters\RFC1156Agent for sysObjectID parameter
lStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REG_KEY_MIB2,
0,
KEY_READ,
&hKey
);
// validate return code
if (lStatus == ERROR_SUCCESS)
{
LPTSTR pszOid = szValue;
dwValueSize = sizeof(szValue); // size in number of bytes
// first, get the size of the buffer required for the sysObjectID parameter
lStatus = RegQueryValueEx(
hKey,
REG_VALUE_SYS_OBJECTID,
0,
&dwValueType,
(LPBYTE)pszOid,
&dwValueSize);
// the ERROR_MORE_DATA is the only error code we expect at this point
if (lStatus == ERROR_MORE_DATA)
{
pszOid = SnmpUtilMemAlloc(dwValueSize);
// if a buffer was set up correctly, go an read the oid value
if (pszOid != NULL)
{
lStatus = RegQueryValueEx(
hKey,
REG_VALUE_SYS_OBJECTID,
0,
&dwValueType,
(LPBYTE)pszOid,
&dwValueSize);
}
}
// at this point we should succeed
if (lStatus == ERROR_SUCCESS)
{
AsnObjectIdentifier sysObjectID;
// we have the string representation of the oid, convert it now to an AsnObjectIdentifier
// implement the convertion here, as I don't want to make this a public function in SNMPAPI.DLL
// otherwise I'll be forced to handle a lot of useless limit cases..
if (dwValueType == REG_SZ &&
ConvStringToOid(pszOid, &sysObjectID))
{
// don't free what has been alocated in ConvStringToOid as the buffer will be passed
// to the management variable below.
bChangedSysID = (mgmtOSet(OsnmpSysObjectID, &sysObjectID, FALSE) == ERROR_SUCCESS);
}
else
{
SNMPDBG((SNMP_LOG_WARNING,
"SNMP: SVC: LoadScalarParameters() - invalid type or value for sysObjectID param.\n"));
ReportSnmpEvent(
SNMP_EVENT_INVALID_ENTERPRISEOID,
0,
NULL,
0);
}
}
// cleanup the buffer if it was dynamically allocated
if (pszOid != szValue)
SnmpUtilMemFree(pszOid);
// cleanup the registry key
RegCloseKey(hKey);
}
if (!bChangedSysID)
{
mgmtOSet(OsnmpSysObjectID, SnmpSvcGetEnterpriseOID(), TRUE);
}
// all parameters here have default values, so there is no reason for this function to fail
// if a parameter could not be found into the registry, its default value will be considered.
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
LoadRegistryParameters(
)
/*++
Routine Description:
Loads registry parameters.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
// first thing to do is to setup the registry notifiers. If we don't do this before reading
// the registry values we might not sense an initial change of the registry.
InitRegistryNotifiers();
// need to load first the scalar parameters especially to know how
// to handle further the name resolution
LoadScalarParameters();
// load managers
LoadPermittedManagers(TRUE);
// load trap destinations
LoadTrapDestinations(TRUE);
// load communities with dynamic update
LoadValidCommunities(TRUE);
// load subagents
LoadSubagents();
// determine regions
LoadSupportedRegions();
return TRUE;
}
BOOL
UnloadRegistryNotifiers(
)
/*++
Routine Description:
Unloads registry notifiers
Arguments:
None.
Return Values:
Returns TRUE
--*/
{
if (g_hDefaultRegNotifier != NULL)
{
CloseHandle(g_hDefaultRegNotifier);
g_hDefaultRegNotifier = NULL;
}
#ifdef _POLICY
if (g_hPolicyRegNotifier != NULL)
{
CloseHandle(g_hPolicyRegNotifier);
g_hPolicyRegNotifier = NULL;
}
#endif
if (g_hDefaultKey != NULL)
{
RegCloseKey(g_hDefaultKey);
g_hDefaultKey = NULL;
}
#ifdef _POLICY
if (g_hPolicyKey != NULL)
{
RegCloseKey(g_hPolicyKey);
g_hPolicyKey = NULL;
}
#endif
return TRUE;
}
BOOL
UnloadRegistryParameters(
)
/*++
Routine Description:
Unloads registry parameters.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
// unload the registry notifiers as the first thing to do
UnloadRegistryNotifiers();
// unload managers
UnloadPermittedManagers();
// unload trap destinations
UnloadTrapDestinations();
// unload communities
UnloadValidCommunities();
// unload subagents
UnloadSubagents();
// unload mib regions
UnloadSupportedRegions();
return TRUE;
}