905 lines
19 KiB
C
905 lines
19 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
subagnts.c
|
||
|
||
Abstract:
|
||
|
||
Contains definitions for manipulating subagent structures.
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
10-Feb-1997 DonRyan
|
||
Rewrote to implement SNMPv2 support.
|
||
|
||
--*/
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Include files //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "globals.h"
|
||
#include "subagnts.h"
|
||
#include "regions.h"
|
||
#include "snmpmgmt.h"
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Private procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
FindSubagent(
|
||
PSUBAGENT_LIST_ENTRY * ppSLE,
|
||
LPSTR pPathname
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Locates subagent in list.
|
||
|
||
Arguments:
|
||
|
||
ppSLE - pointer to receive pointer to entry.
|
||
|
||
pPathname - pointer to pathname to find.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PSUBAGENT_LIST_ENTRY pSLE;
|
||
|
||
// initialize
|
||
*ppSLE = NULL;
|
||
|
||
// obtain pointer to head
|
||
pLE = g_Subagents.Flink;
|
||
|
||
// process all entries in list
|
||
while (pLE != &g_Subagents) {
|
||
|
||
// retrieve pointer to trap destination structure
|
||
pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
|
||
|
||
// compare pathname string with entry
|
||
if (!strcmp(pSLE->pPathname, pPathname)) {
|
||
|
||
// transfer
|
||
*ppSLE = pSLE;
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
|
||
// next entry
|
||
pLE = pLE->Flink;
|
||
}
|
||
|
||
// failure
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
AddSubagentRegion(
|
||
PSUBAGENT_LIST_ENTRY pSLE,
|
||
AsnObjectIdentifier * pPrefixOid
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds subagent supported region to structure.
|
||
|
||
Arguments:
|
||
|
||
pSLE - pointer to subagent structure.
|
||
|
||
pPrefixOid - pointer to supported region.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PMIB_REGION_LIST_ENTRY pRLE = NULL;
|
||
|
||
// allocate region
|
||
if (AllocRLE(&pRLE)) {
|
||
|
||
// save pointer
|
||
pRLE->pSLE = pSLE;
|
||
|
||
// copy prefix to structure
|
||
SnmpUtilOidCpy(&pRLE->PrefixOid, pPrefixOid);
|
||
|
||
// copy prefix as temporary limit
|
||
SnmpUtilOidCpy(&pRLE->LimitOid, pPrefixOid);
|
||
|
||
// modify limit oid to be one past the prefix
|
||
++pRLE->LimitOid.ids[pRLE->LimitOid.idLength - 1];
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: %s supports %s.\n",
|
||
pSLE->pPathname,
|
||
SnmpUtilOidToA(&pRLE->PrefixOid)
|
||
));
|
||
|
||
// attach to mib region to subagent structure
|
||
InsertTailList(&pSLE->SupportedRegions, &pRLE->Link);
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
BOOL
|
||
OfferInternalMgmtVariables(
|
||
PSUBAGENT_LIST_ENTRY pSLE
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
if the subagent is willing to monitor the SNMP service
|
||
this function is offering it a pointer to the internal
|
||
management variables
|
||
|
||
Arguments:
|
||
|
||
pSLE - pointer to subagent structure.
|
||
|
||
Return Values:
|
||
|
||
Returns true anyway.
|
||
|
||
--*/
|
||
{
|
||
if (pSLE->pfnSnmpExtensionMonitor != NULL)
|
||
{
|
||
__try {
|
||
|
||
// attempt to initialize agent
|
||
(*pSLE->pfnSnmpExtensionMonitor)(&snmpMgmtBase);
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: exception 0x%08lx offering internals to %s.\n",
|
||
GetExceptionCode(),
|
||
pSLE->pPathname
|
||
));
|
||
|
||
// failure
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadSubagentRegions(
|
||
PSUBAGENT_LIST_ENTRY pSLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Loads subagent supported regions.
|
||
|
||
Arguments:
|
||
|
||
pSLE - pointer to subagent structure.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
HANDLE hSubagentTrapEvent = NULL;
|
||
AsnObjectIdentifier PrefixOid = { 0, NULL };
|
||
|
||
__try {
|
||
|
||
// attempt to initialize agent
|
||
if ((*pSLE->pfnSnmpExtensionInit)(
|
||
g_dwUpTimeReference,
|
||
&hSubagentTrapEvent,
|
||
&PrefixOid
|
||
)) {
|
||
|
||
// store subagent trap event handle
|
||
pSLE->hSubagentTrapEvent = hSubagentTrapEvent;
|
||
|
||
// add subagent region to list entry
|
||
fOk = AddSubagentRegion(pSLE, &PrefixOid);
|
||
|
||
// check to see if subagent supports additional regions
|
||
if (fOk && (pSLE->pfnSnmpExtensionInitEx != NULL)) {
|
||
|
||
BOOL fMoreRegions = TRUE;
|
||
|
||
// get other regions
|
||
while (fOk && fMoreRegions) {
|
||
|
||
// retrieve next supported region
|
||
fMoreRegions = (*pSLE->pfnSnmpExtensionInitEx)(
|
||
&PrefixOid
|
||
);
|
||
|
||
// validate
|
||
if (fMoreRegions) {
|
||
|
||
// add subagent region to list entry
|
||
fOk = AddSubagentRegion(pSLE, &PrefixOid);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: exception 0x%08lx loading %s.\n",
|
||
GetExceptionCode(),
|
||
pSLE->pPathname
|
||
));
|
||
|
||
// failure
|
||
fOk = FALSE;
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadSubagent(
|
||
PSUBAGENT_LIST_ENTRY pSLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Loads subagent dll and initializes.
|
||
|
||
Arguments:
|
||
|
||
pSLE - pointer to subagent structure.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
|
||
// attempt to load subagent library - we use the altered search path flag so that
|
||
// the subagent can load DLLs that live in its directory
|
||
pSLE->hSubagentDll = LoadLibraryExA(pSLE->pPathname, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||
|
||
// validate handle
|
||
if (pSLE->hSubagentDll != NULL) {
|
||
|
||
// load primary initialization routine
|
||
pSLE->pfnSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_INIT
|
||
);
|
||
|
||
// load secondary initialization routine
|
||
pSLE->pfnSnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_INIT_EX
|
||
);
|
||
|
||
// load secondary initialization routine
|
||
pSLE->pfnSnmpExtensionClose = (PFNSNMPEXTENSIONCLOSE)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_CLOSE
|
||
);
|
||
|
||
// load the extension monitor routine
|
||
pSLE->pfnSnmpExtensionMonitor = (PFNSNMPEXTENSIONMONITOR)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_MONITOR
|
||
);
|
||
|
||
// load snmpv1-based subagent request routine
|
||
pSLE->pfnSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_QUERY
|
||
);
|
||
|
||
// load snmpv2-based subagent request routine
|
||
pSLE->pfnSnmpExtensionQueryEx = (PFNSNMPEXTENSIONQUERYEX)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_QUERY_EX
|
||
);
|
||
|
||
// load snmpv1-based subagent trap routine
|
||
pSLE->pfnSnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP)
|
||
GetProcAddress(
|
||
pSLE->hSubagentDll,
|
||
SNMP_EXTENSION_TRAP
|
||
);
|
||
|
||
// validate subagent agent entry points
|
||
if ((pSLE->pfnSnmpExtensionInit != NULL) &&
|
||
((pSLE->pfnSnmpExtensionQuery != NULL) ||
|
||
(pSLE->pfnSnmpExtensionQueryEx != NULL))) {
|
||
|
||
// load supported regions
|
||
if (fOk = LoadSubagentRegions(pSLE)) // !!intentional assignement!!
|
||
{
|
||
// offering internal management variables;
|
||
fOk = OfferInternalMgmtVariables(pSLE);
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
DWORD errCode = GetLastError();
|
||
LPTSTR pPathname;
|
||
|
||
#ifdef UNICODE
|
||
SnmpUtilUTF8ToUnicode(&pPathname, pSLE->pPathname, TRUE);
|
||
#else
|
||
pPathname = pSLE->pPathname;
|
||
#endif
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: error %d loading subagent.\n",
|
||
errCode
|
||
));
|
||
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL,
|
||
1,
|
||
&pPathname,
|
||
errCode);
|
||
|
||
#ifdef UNICODE
|
||
SnmpUtilMemFree(pPathname);
|
||
#endif
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
AddSubagentByDll(
|
||
LPSTR pPathname,
|
||
UCHAR uchInitFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds subagent to list.
|
||
|
||
Arguments:
|
||
|
||
pPathname - pointer to subagent's dll path.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PSUBAGENT_LIST_ENTRY pSLE = NULL;
|
||
|
||
// attempt to locate in list
|
||
if (FindSubagent(&pSLE, pPathname)) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_WARNING,
|
||
"SNMP: SVC: duplicate entry for %s.\n",
|
||
pPathname
|
||
));
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
|
||
} else {
|
||
|
||
// allocate subagent structure
|
||
if (AllocSLE(&pSLE, pPathname, uchInitFlags)) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: processing subagent %s.\n",
|
||
pPathname
|
||
));
|
||
|
||
// initialize subagent
|
||
if (LoadSubagent(pSLE)) {
|
||
|
||
// insert into valid communities list
|
||
InsertTailList(&g_Subagents, &pSLE->Link);
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
|
||
// cleanup
|
||
if (!fOk) {
|
||
|
||
// release
|
||
FreeSLE(pSLE);
|
||
}
|
||
}
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
AddSubagentByKey(
|
||
LPTSTR pKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds subagent to list.
|
||
|
||
Arguments:
|
||
|
||
pKey - pointer to subagent's registry key path.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hKey;
|
||
LONG lStatus;
|
||
DWORD dwIndex;
|
||
DWORD dwNameSize;
|
||
DWORD dwValueSize;
|
||
DWORD dwValueType;
|
||
CHAR szName[MAX_PATH];
|
||
CHAR szValue[MAX_PATH];
|
||
BOOL fOk = FALSE;
|
||
PSUBAGENT_LIST_ENTRY pSLE = NULL;
|
||
|
||
// open registry subkey
|
||
lStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
pKey,
|
||
0,
|
||
KEY_READ,
|
||
&hKey
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
|
||
// initialize
|
||
dwIndex = 0;
|
||
|
||
// initialize buffer sizes
|
||
dwNameSize = sizeof(szName);
|
||
dwValueSize = sizeof(szValue);
|
||
|
||
// loop until error or end of list
|
||
while (lStatus == ERROR_SUCCESS) {
|
||
|
||
// read next value
|
||
lStatus = RegEnumValueA(
|
||
hKey,
|
||
dwIndex,
|
||
szName,
|
||
&dwNameSize,
|
||
NULL,
|
||
&dwValueType,
|
||
szValue,
|
||
&dwValueSize
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
|
||
// check to see if value is pathname
|
||
if (!_stricmp(szName, REG_VALUE_SUBAGENT_PATH)) {
|
||
|
||
DWORD dwRequired;
|
||
CHAR szExpanded[MAX_PATH];
|
||
|
||
// expand environment strings in path
|
||
dwRequired = ExpandEnvironmentStringsA(
|
||
szValue,
|
||
szExpanded,
|
||
sizeof(szExpanded)
|
||
);
|
||
|
||
// load subagent library - no flags set
|
||
fOk = AddSubagentByDll(szExpanded, 0);
|
||
|
||
break; // bail...
|
||
}
|
||
|
||
// initialize buffer sizes
|
||
dwNameSize = sizeof(szName);
|
||
dwValueSize = sizeof(szValue);
|
||
|
||
// next
|
||
dwIndex++;
|
||
|
||
} else if (lStatus == ERROR_NO_MORE_ITEMS) {
|
||
|
||
// failure
|
||
fOk = FALSE;
|
||
}
|
||
}
|
||
|
||
// release handle
|
||
RegCloseKey(hKey);
|
||
}
|
||
else
|
||
{
|
||
// the registry key for this subagent could not be located.
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_INVALID_EXTENSION_AGENT_KEY,
|
||
1,
|
||
&pKey,
|
||
lStatus);
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Public procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
AllocSLE(
|
||
PSUBAGENT_LIST_ENTRY * ppSLE,
|
||
LPSTR pPathname,
|
||
UCHAR uchInitFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocates trap destination structure and initializes.
|
||
|
||
Arguments:
|
||
|
||
ppSLE - pointer to receive pointer to entry.
|
||
|
||
pPathname - pointer to subgent's dll path.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PSUBAGENT_LIST_ENTRY pSLE = NULL;
|
||
|
||
// attempt to allocate structure
|
||
pSLE = AgentMemAlloc(sizeof(SUBAGENT_LIST_ENTRY));
|
||
|
||
// validate
|
||
if (pSLE != NULL) {
|
||
|
||
// allocate memory for trap destination string
|
||
pSLE->pPathname = AgentMemAlloc(strlen(pPathname)+1);
|
||
|
||
// validate
|
||
if (pSLE->pPathname != NULL) {
|
||
|
||
// transfer trap destination string
|
||
strcpy(pSLE->pPathname, pPathname);
|
||
|
||
// set the initial flags value
|
||
pSLE->uchFlags = uchInitFlags;
|
||
|
||
// initialize list of supported regions
|
||
InitializeListHead(&pSLE->SupportedRegions);
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
|
||
// cleanup
|
||
if (!fOk) {
|
||
|
||
// release
|
||
FreeSLE(pSLE);
|
||
|
||
// re-init
|
||
pSLE = NULL;
|
||
}
|
||
}
|
||
|
||
// transfer
|
||
*ppSLE = pSLE;
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FreeSLE(
|
||
PSUBAGENT_LIST_ENTRY pSLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Releases subagent structure.
|
||
|
||
Arguments:
|
||
|
||
pSLE - pointer to list entry to be freed.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = TRUE;
|
||
|
||
// validate pointer
|
||
if (pSLE != NULL) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: unloading %s.\n",
|
||
pSLE->pPathname
|
||
));
|
||
|
||
// release manager structures
|
||
UnloadRegions(&pSLE->SupportedRegions);
|
||
|
||
// validate subagent dll handle
|
||
if (pSLE->hSubagentDll != NULL) {
|
||
|
||
__try {
|
||
if (pSLE->pfnSnmpExtensionClose != NULL)
|
||
(*pSLE->pfnSnmpExtensionClose)();
|
||
|
||
// unload subagent
|
||
FreeLibrary(pSLE->hSubagentDll);
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: exception 0x%08lx unloading %s.\n",
|
||
GetExceptionCode(),
|
||
pSLE->pPathname
|
||
));
|
||
}
|
||
}
|
||
|
||
// release string
|
||
AgentMemFree(pSLE->pPathname);
|
||
|
||
// release structure
|
||
AgentMemFree(pSLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadSubagents(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Constructs list of subagents.
|
||
|
||
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_EXTENSION_AGENTS;
|
||
BOOL fOk = FALSE;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: loading subagents.\n"
|
||
));
|
||
|
||
// open registry subkey
|
||
lStatus = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
pszKey,
|
||
0,
|
||
KEY_READ,
|
||
&hKey
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
|
||
// initialize
|
||
dwIndex = 0;
|
||
|
||
// initialize buffer sizes
|
||
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
|
||
dwValueSize = sizeof(szValue); // size in number of bytes
|
||
|
||
// loop until error or end of list
|
||
while (lStatus == ERROR_SUCCESS) {
|
||
|
||
// read next value
|
||
lStatus = RegEnumValue(
|
||
hKey,
|
||
dwIndex,
|
||
szName,
|
||
&dwNameSize,
|
||
NULL,
|
||
&dwValueType,
|
||
(LPBYTE)szValue,
|
||
&dwValueSize
|
||
);
|
||
|
||
// validate return code
|
||
if (lStatus == ERROR_SUCCESS) {
|
||
|
||
// add subagent to list
|
||
AddSubagentByKey(szValue);
|
||
|
||
// re-initialize buffer sizes
|
||
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
|
||
dwValueSize = sizeof(szValue); // size in number of bytes
|
||
|
||
// next
|
||
dwIndex++;
|
||
|
||
} else if (lStatus == ERROR_NO_MORE_ITEMS) {
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!fOk) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: error %d processing Subagents subkey.\n",
|
||
lStatus
|
||
));
|
||
|
||
// report event
|
||
ReportSnmpEvent(
|
||
SNMP_EVENT_INVALID_REGISTRY_KEY,
|
||
1,
|
||
&pszKey,
|
||
lStatus
|
||
);
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UnloadSubagents(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Destroys list of subagents.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PSUBAGENT_LIST_ENTRY pSLE;
|
||
|
||
// process entries until list is empty
|
||
while (!IsListEmpty(&g_Subagents)) {
|
||
|
||
// extract next entry from head of list
|
||
pLE = RemoveHeadList(&g_Subagents);
|
||
|
||
// retrieve pointer to community structure
|
||
pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
|
||
|
||
// release
|
||
FreeSLE(pSLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|