597 lines
14 KiB
C
597 lines
14 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|