|
|
/*++
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++; } else { SNMPDBG((SNMP_LOG_TRACE, "SNMP: REG: Default reg notifier initialization failed.\n")); if (g_hDefaultRegNotifier != NULL) { CloseHandle(g_hDefaultRegNotifier); g_hDefaultRegNotifier = NULL; } if (g_hDefaultKey != NULL) { RegCloseKey(g_hDefaultKey); g_hDefaultKey = NULL; } }
#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_PARAMETERS, 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++; } else { SNMPDBG((SNMP_LOG_TRACE, "SNMP: REG: Policy reg notifier initialization failed.\n"));
if (g_hPolicyRegNotifier != NULL) { CloseHandle(g_hPolicyRegNotifier); g_hPolicyRegNotifier = NULL; } if (g_hPolicyKey != NULL) { RegCloseKey(g_hPolicyKey); g_hPolicyKey = NULL; } }
#endif
SNMPDBG((SNMP_LOG_TRACE, "SNMP: REG: Initialized notifiers ... %d.\n", nEvents));
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; }
|