1221 lines
35 KiB
C++
1221 lines
35 KiB
C++
/*****************************************************************************\
|
||
* MODULE: olesnmp.cpp
|
||
*
|
||
* PURPOSE: Implementation of COM interface for SNMP
|
||
*
|
||
* Copyright (C) 1997-1998 Microsoft Corporation
|
||
*
|
||
* History:
|
||
*
|
||
* 08/16/97 paulmo Created
|
||
* 09/12/97 weihaic Moved to oleprn.dll
|
||
*
|
||
\*****************************************************************************/
|
||
|
||
#include "stdafx.h"
|
||
#include "oleprn.h"
|
||
#include "olesnmp.h"
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// CSNMP
|
||
|
||
|
||
CSNMP::
|
||
CSNMP(
|
||
VOID
|
||
)
|
||
{
|
||
m_SNMPSession = NULL;
|
||
}
|
||
|
||
CSNMP::
|
||
~CSNMP(
|
||
VOID
|
||
)
|
||
{
|
||
if (m_SNMPSession != NULL) SnmpMgrClose(m_SNMPSession);
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: Open
|
||
*
|
||
* PURPOSE: COM wrapper for SnmpMgrOpen
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* bstrHost: Host name or Server Name
|
||
* bstrCommunity: Community Name
|
||
* varRetry: Retry times [optional in VB]
|
||
* varTimeOut: Time out Value (in millisecond) [optional in VB]
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid argument. It occurs when either varRetry or varTimeOut
|
||
* can not be converted to a short integer.
|
||
* E_FAIL: If SNMPMgrOpen fails
|
||
*
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
Open(
|
||
IN BSTR bstrHost,
|
||
IN BSTR bstrCommunity,
|
||
IN VARIANT varRetry,
|
||
IN VARIANT varTimeOut
|
||
)
|
||
{
|
||
const INT iDefaultRetry = 5;
|
||
const INT iDefaultTimeOut = 5000;
|
||
INT iRetry;
|
||
INT iTimeOut;
|
||
LPSTR pAnsiHost = NULL;
|
||
LPSTR pAnsiCommunity = NULL;
|
||
HRESULT hr = E_FAIL;
|
||
|
||
// To prevent a second open
|
||
if (m_SNMPSession != NULL){
|
||
SnmpMgrClose(m_SNMPSession);
|
||
m_SNMPSession = NULL;
|
||
}
|
||
|
||
if (varRetry.vt == VT_ERROR) {
|
||
iRetry = iDefaultRetry;
|
||
}
|
||
else {
|
||
VARIANT varTemp;
|
||
|
||
VariantInit (&varTemp);
|
||
hr = VariantChangeType (&varTemp, &varRetry, 0, VT_I2);
|
||
if (FAILED (hr))
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
iRetry = varTemp.iVal;
|
||
}
|
||
|
||
if (varTimeOut.vt == VT_ERROR) {
|
||
iTimeOut = iDefaultTimeOut;
|
||
}
|
||
else {
|
||
VARIANT varTemp;
|
||
|
||
VariantInit (&varTemp);
|
||
hr = VariantChangeType (&varTemp, &varTimeOut, 0, VT_I2);
|
||
if (FAILED (hr))
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
iTimeOut = varTemp.iVal;
|
||
}
|
||
|
||
pAnsiHost = MakeNarrow(bstrHost);
|
||
pAnsiCommunity = MakeNarrow(bstrCommunity);
|
||
|
||
if (pAnsiHost && pAnsiCommunity) {
|
||
__try {
|
||
|
||
m_SNMPSession = SnmpMgrOpen(pAnsiHost, pAnsiCommunity, iTimeOut, iRetry);
|
||
|
||
} __except(1) {
|
||
|
||
hr = E_FAIL;
|
||
}
|
||
}
|
||
|
||
LocalFree(pAnsiHost);
|
||
LocalFree(pAnsiCommunity);
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return Error(IDS_FAILED_OPEN_SNMP, IID_ISNMP, E_FAIL);
|
||
|
||
return S_OK;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: Get
|
||
*
|
||
* PURPOSE: Get a value of a SNMP oid
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* bstrOID: The SNMP Oid in BSTR
|
||
* pvarValue: The return value for the corresponding Oid
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid.
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
Get(
|
||
IN BSTR bstrOID,
|
||
OUT VARIANT *pvarValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
HRESULT hr = E_FAIL;
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
|
||
|
||
if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList))){
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (!SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (asniErrorStatus > 0) {
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = RFC1157ToVariant(pvarValue, &rfcVarList.list[0]);
|
||
|
||
Cleanup:
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
return hr;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: GetAsByte
|
||
*
|
||
* PURPOSE: Get a value of a SNMP oid as an integer
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* bstrOID: The SNMP Oid in BSTR
|
||
* puValue: The return value for the corresponding Oid
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid.
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
GetAsByte(
|
||
IN BSTR bstrOID,
|
||
OUT PUINT puValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
HRESULT hr = E_FAIL;
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
|
||
|
||
if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList))){
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (!SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (asniErrorStatus > 0) {
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = RFC1157ToUInt(puValue, &rfcVarList.list[0]);
|
||
|
||
Cleanup:
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
return hr;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: GetList
|
||
*
|
||
* PURPOSE: Get a list of a SNMP oids
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* pvarList: The array of SNMP Oids. The type must be a 1D array of BSTRs
|
||
* pvarValue: The return value for the corresponding Oids, it is 1D array
|
||
* of Variants
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid or the type of the variant is not a 1D array
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
GetList(
|
||
IN VARIANT *pvarList,
|
||
OUT VARIANT *pvarValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
HRESULT hr = E_FAIL;
|
||
SAFEARRAY *psa,*psaOut = NULL;
|
||
SAFEARRAYBOUND rgsabound[1];
|
||
long lbound, ubound, half, step;
|
||
VARIANT var;
|
||
BOOL bFound;
|
||
BOOL bTooBig;
|
||
|
||
// Check if Open Method has been called
|
||
if (m_SNMPSession == NULL)
|
||
return (Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL));
|
||
|
||
// Validate the input variable
|
||
if (!(pvarList->vt & VT_ARRAY))
|
||
return (Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG));
|
||
|
||
if (pvarList->vt & VT_BYREF)
|
||
psa = *(pvarList->pparray);
|
||
else
|
||
psa = pvarList->parray;
|
||
|
||
if (SafeArrayGetDim(psa)!=1)
|
||
return (Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG));
|
||
|
||
// Get the array boundary
|
||
SafeArrayGetLBound(psa, 1, &lbound);
|
||
SafeArrayGetUBound(psa, 1, &ubound);
|
||
|
||
VariantInit(pvarValue);
|
||
VariantInit(&var);
|
||
|
||
// Alloc the destination array
|
||
rgsabound[0].lLbound = 0;
|
||
rgsabound[0].cElements = ubound - lbound + 1;
|
||
|
||
if (! (psaOut = SafeArrayCreate(VT_VARIANT, 1, rgsabound))) {
|
||
hr = Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
goto Cleanup;
|
||
}
|
||
|
||
// Try to determine the size of data we can put into one call
|
||
half = ubound;
|
||
|
||
bFound = FALSE;
|
||
while (!bFound) {
|
||
|
||
bTooBig = FALSE;
|
||
|
||
// Convert items of the array to rfcVarList
|
||
hr = VarToRfcVarList (lbound, half, psa, &rfcVarList);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
if (! SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
|
||
if (GetLastError() != ERROR_NOT_ENOUGH_MEMORY)
|
||
{
|
||
// SNMP call fails. Setup error and return
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
else
|
||
bTooBig = TRUE;
|
||
}
|
||
|
||
if (asniErrorStatus > 0) {
|
||
// SNMP call succeeds but the returned status if wrong
|
||
if (asniErrorStatus != SNMP_ERRORSTATUS_TOOBIG) {
|
||
// Other errors occur in the call, setup error and return
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
else
|
||
bTooBig = TRUE;
|
||
}
|
||
|
||
if (bTooBig){
|
||
// The size of input is too big, reduce it again
|
||
if (half - lbound < 2) {
|
||
// Something must be wrong, quit
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
else {
|
||
// Divdie the size by 2
|
||
half = (lbound + half) / 2;
|
||
}
|
||
}
|
||
else {
|
||
// We've found the proper steps and also got the first portion
|
||
// Save them to the destination safe array psaout
|
||
hr = RfcToVarList (lbound, &rfcVarList, psaOut);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
bFound = TRUE;
|
||
}
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
rfcVarList.list = NULL;
|
||
rfcVarList.len = 0;
|
||
}
|
||
|
||
step = half - lbound;
|
||
for (lbound = half + 1; lbound <= ubound; lbound += step) {
|
||
half = lbound + step;
|
||
if (half > ubound)
|
||
half = ubound;
|
||
|
||
hr = VarToRfcVarList (lbound, half, psa, &rfcVarList);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
if (! SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
// SNMP call fails. Setup error and return
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
if (asniErrorStatus > 0) {
|
||
// SNMP call succeeds but the returned status if wrong
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
// Everything is OK
|
||
hr = RfcToVarList (lbound, &rfcVarList, psaOut);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
rfcVarList.list = NULL;
|
||
rfcVarList.len = 0;
|
||
}
|
||
|
||
VariantInit(pvarValue);
|
||
pvarValue->vt = VT_ARRAY|VT_VARIANT;
|
||
pvarValue->parray = psaOut;
|
||
hr = S_OK;
|
||
return hr;
|
||
|
||
Cleanup:
|
||
if (rfcVarList.len > 0)
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
if (psaOut)
|
||
SafeArrayDestroy (psaOut);
|
||
return hr;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: GetTree
|
||
*
|
||
* PURPOSE: It walks through SNMP oids
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* bstrTree: The array of SNMP Oids. The type must be a 1D array of BSTRs
|
||
* pvarValue: The return value for the corresponding Oids, it is 1D array
|
||
* of Variants
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid.
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
GetTree(
|
||
IN BSTR bstrTree,
|
||
OUT VARIANT *pvarValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
VARIANT v;
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
AsnObjectIdentifier asnRootOid;
|
||
AsnObjectIdentifier asnTmpOid;
|
||
HRESULT hr = E_FAIL;
|
||
SAFEARRAY *psa = NULL;
|
||
SAFEARRAYBOUND rgsabound[2];
|
||
long ix[2];
|
||
LPSTR pszStr;
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return (Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL));
|
||
|
||
rgsabound[0].lLbound = 0;
|
||
rgsabound[0].cElements = 2;
|
||
rgsabound[1].lLbound = 0;
|
||
rgsabound[1].cElements = 0;
|
||
if (! (psa = SafeArrayCreate(VT_VARIANT, 2, rgsabound)))
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
|
||
hr = VarListAdd(bstrTree, &rfcVarList);
|
||
if (FAILED (hr))
|
||
{
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup2;
|
||
}
|
||
|
||
if (!SnmpUtilOidCpy(&asnRootOid, &rfcVarList.list[0].name)){
|
||
hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
goto Cleanup2;
|
||
}
|
||
|
||
while(1){
|
||
if (!SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_GETNEXTREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (asniErrorStatus == SNMP_ERRORSTATUS_NOSUCHNAME ||
|
||
SnmpUtilOidNCmp(&rfcVarList.list[0].name, &asnRootOid, asnRootOid.idLength))
|
||
break;
|
||
|
||
if (asniErrorStatus > 0) {
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
|
||
rgsabound[1].cElements++;
|
||
ix[1] = rgsabound[1].cElements - 1;
|
||
hr = SafeArrayRedim(psa, &rgsabound[1]);
|
||
if (FAILED (hr))
|
||
{
|
||
Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
goto Cleanup;
|
||
}
|
||
|
||
// put a pszStr version of the OID in the result array
|
||
|
||
pszStr = NULL;
|
||
if (!SnmpMgrOidToStr(&rfcVarList.list[0].name, &pszStr)){
|
||
hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
goto Cleanup;
|
||
}
|
||
|
||
ix[0] = 0;
|
||
hr = PutString(psa, ix, pszStr);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
SnmpUtilMemFree(pszStr);
|
||
|
||
// Put the value variant in the result array
|
||
|
||
hr = RFC1157ToVariant(&v, &rfcVarList.list[0]);
|
||
if (FAILED (hr)) goto Cleanup;
|
||
|
||
ix[0] = 1;
|
||
hr = SafeArrayPutElement(psa, ix, &v);
|
||
if (FAILED (hr))
|
||
{
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
VariantClear(&v);
|
||
|
||
if (! SnmpUtilOidCpy(&asnTmpOid, &rfcVarList.list[0].name)) {
|
||
hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
goto Cleanup;
|
||
}
|
||
|
||
SnmpUtilVarBindFree(&rfcVarList.list[0]);
|
||
|
||
if (! SnmpUtilOidCpy(&rfcVarList.list[0].name, &asnTmpOid)) {
|
||
hr = SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
SnmpUtilOidFree(&asnTmpOid);
|
||
goto Cleanup;
|
||
}
|
||
|
||
rfcVarList.list[0].value.asnType = ASN_NULL;
|
||
SnmpUtilOidFree(&asnTmpOid);
|
||
}
|
||
|
||
SnmpUtilOidFree(&asnRootOid);
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
|
||
VariantInit(pvarValue);
|
||
pvarValue->vt = VT_ARRAY|VT_VARIANT;
|
||
pvarValue->parray = psa;
|
||
return S_OK;
|
||
|
||
Cleanup:
|
||
SnmpUtilOidFree(&asnRootOid);
|
||
Cleanup2:
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
if (psa)
|
||
SafeArrayDestroy(psa);
|
||
return hr;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: Close
|
||
*
|
||
* PURPOSE: A Com Wrapper for SnmpMgrClose()
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: always.
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
Close(
|
||
VOID
|
||
)
|
||
{
|
||
if (m_SNMPSession)
|
||
SnmpMgrClose(m_SNMPSession);
|
||
m_SNMPSession = NULL;
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
OIDFromString(
|
||
BSTR bstrOID,
|
||
VARIANT *pvarOID
|
||
)
|
||
{
|
||
SAFEARRAY *psaOID;
|
||
SAFEARRAYBOUND rgsaOID[1];
|
||
long ixOID[1];
|
||
LPSTR pszOID;
|
||
BOOL bResult;
|
||
VARIANT v;
|
||
AsnObjectIdentifier asnReqObject;
|
||
HRESULT hr;
|
||
|
||
VariantInit(&v);
|
||
if (! (pszOID = MakeNarrow(bstrOID)))
|
||
return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
|
||
bResult = SnmpMgrStrToOid(pszOID, &asnReqObject);
|
||
LocalFree(pszOID);
|
||
|
||
if (!bResult )
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
|
||
// put a numeric array of the pvarOID in the result array
|
||
|
||
rgsaOID[0].lLbound = 0;
|
||
rgsaOID[0].cElements = asnReqObject.idLength;
|
||
psaOID = SafeArrayCreate(VT_VARIANT, 1, rgsaOID);
|
||
if (psaOID == NULL)
|
||
goto out;
|
||
for (ixOID[0] = 0; ixOID[0] < (long)rgsaOID[0].cElements ; ixOID[0]++){
|
||
hr = VariantClear(&v);
|
||
_ASSERTE (SUCCEEDED (hr));
|
||
v.vt = VT_I4;
|
||
v.lVal = asnReqObject.ids[ixOID[0]];
|
||
hr = SafeArrayPutElement(psaOID, ixOID, &v);
|
||
if (FAILED(hr))
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
//SafeArrayPutElement(psaOID, ixOID, &(asnReqObject.ids[ixOID[0]]));
|
||
}
|
||
|
||
hr = VariantClear(pvarOID);
|
||
_ASSERTE(hr);
|
||
pvarOID->vt = VT_ARRAY|VT_VARIANT;
|
||
pvarOID->parray = psaOID;
|
||
SnmpUtilOidFree(&asnReqObject);
|
||
return S_OK;
|
||
|
||
out:
|
||
SnmpUtilOidFree(&asnReqObject);
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
}
|
||
|
||
HRESULT
|
||
CSNMP::
|
||
VariantToRFC1157(
|
||
RFC1157VarBind * prfcvbValue,
|
||
VARIANT * pvarValue
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
if (!pvarValue) {
|
||
prfcvbValue->value.asnType = ASN_NULL;
|
||
} else
|
||
if (pvarValue->vt == VT_BSTR){
|
||
prfcvbValue->value.asnType = ASN_OCTETSTRING;
|
||
LPSTR pStr = MakeNarrow (pvarValue->bstrVal);
|
||
|
||
if (pStr) {
|
||
DWORD dwLen = strlen (pStr);
|
||
|
||
if (! (prfcvbValue->value.asnValue.string.stream = (BYTE *) SnmpUtilMemAlloc (dwLen + 1))) {
|
||
LocalFree (pStr);
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
}
|
||
memcpy (prfcvbValue->value.asnValue.string.stream, pStr, dwLen + 1);
|
||
prfcvbValue->value.asnValue.string.length = dwLen;
|
||
prfcvbValue->value.asnValue.string.dynamic = TRUE;
|
||
LocalFree (pStr);
|
||
}
|
||
else
|
||
hr = Error( IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY );
|
||
}
|
||
else {
|
||
VARIANT varTemp;
|
||
|
||
VariantInit (&varTemp);
|
||
hr = VariantChangeType (&varTemp, pvarValue, 0, VT_I4);
|
||
if (FAILED (hr))
|
||
hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
else {
|
||
prfcvbValue->value.asnType = ASN_INTEGER;
|
||
prfcvbValue->value.asnValue.number = pvarValue->lVal;
|
||
}
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
// ----------------------------------------------------
|
||
// Place a returned SNMP value in a variant
|
||
//
|
||
HRESULT
|
||
CSNMP::
|
||
RFC1157ToVariant(
|
||
VARIANT * pvarValue,
|
||
RFC1157VarBind * prfcvbValue
|
||
)
|
||
{
|
||
VariantInit(pvarValue);
|
||
switch (prfcvbValue->value.asnType){
|
||
case ASN_RFC1155_TIMETICKS:
|
||
case ASN_RFC1155_COUNTER:
|
||
case ASN_RFC1155_GAUGE:
|
||
case ASN_INTEGER:
|
||
case ASN_UNSIGNED32:
|
||
pvarValue->vt= VT_I4;
|
||
pvarValue->lVal = prfcvbValue->value.asnValue.number;
|
||
break;
|
||
|
||
case ASN_RFC1155_IPADDRESS:
|
||
case ASN_RFC1155_OPAQUE:
|
||
case ASN_BITS:
|
||
case ASN_SEQUENCE:
|
||
case ASN_OCTETSTRING:
|
||
pvarValue->vt = VT_BSTR;
|
||
LPWSTR pszUnicodeStr;
|
||
if (prfcvbValue->value.asnValue.string.length > 0 ){
|
||
LPSTR pszAnsiStr;
|
||
if (! (pszAnsiStr = (LPSTR )LocalAlloc(LPTR,
|
||
prfcvbValue->value.asnValue.string.length + 1)))
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
memcpy(pszAnsiStr, (LPSTR )prfcvbValue->value.asnValue.string.stream,
|
||
prfcvbValue->value.asnValue.string.length);
|
||
pszAnsiStr[prfcvbValue->value.asnValue.string.length] = 0;
|
||
pszUnicodeStr = MakeWide(pszAnsiStr);
|
||
LocalFree(pszAnsiStr);
|
||
}
|
||
else{
|
||
pszUnicodeStr = MakeWide("");
|
||
}
|
||
|
||
if (pszUnicodeStr == NULL)
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
|
||
pvarValue->bstrVal = SysAllocString(pszUnicodeStr);
|
||
|
||
LocalFree(pszUnicodeStr);
|
||
|
||
if (pvarValue->bstrVal == NULL) {
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
}
|
||
break;
|
||
|
||
case ASN_OBJECTIDENTIFIER:
|
||
LPSTR pszAnsiOid;
|
||
|
||
pszAnsiOid = NULL;
|
||
if (SnmpMgrOidToStr(& (prfcvbValue->value.asnValue.object), &pszAnsiOid)) {
|
||
LPWSTR pszUnicodeOid = MakeWide (pszAnsiOid);
|
||
|
||
SnmpUtilMemFree (pszAnsiOid);
|
||
|
||
if (pszUnicodeOid) {
|
||
pvarValue->vt = VT_BSTR;
|
||
pvarValue->bstrVal = SysAllocString(pszUnicodeOid);
|
||
LocalFree (pszUnicodeOid);
|
||
}
|
||
else
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
}
|
||
else
|
||
return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
break;
|
||
default:
|
||
pvarValue->vt = VT_EMPTY;
|
||
}
|
||
return S_OK;
|
||
}
|
||
|
||
// ----------------------------------------------------
|
||
// Place a returned SNMP value in a uint
|
||
//
|
||
HRESULT
|
||
CSNMP::
|
||
RFC1157ToUInt(
|
||
PUINT puValue,
|
||
RFC1157VarBind * prfcvbValue
|
||
)
|
||
{
|
||
switch (prfcvbValue->value.asnType){
|
||
case ASN_RFC1155_TIMETICKS:
|
||
case ASN_RFC1155_COUNTER:
|
||
case ASN_RFC1155_GAUGE:
|
||
case ASN_INTEGER:
|
||
case ASN_UNSIGNED32:
|
||
*puValue = prfcvbValue->value.asnValue.number;
|
||
break;
|
||
|
||
case ASN_RFC1155_OPAQUE:
|
||
case ASN_BITS:
|
||
case ASN_SEQUENCE:
|
||
case ASN_OCTETSTRING:
|
||
|
||
if (prfcvbValue->value.asnValue.string.length == 1 ){
|
||
*puValue = prfcvbValue->value.asnValue.string.stream[0];
|
||
}
|
||
else{
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
}
|
||
return S_OK;
|
||
}
|
||
|
||
// -----------------------------------------------------
|
||
// Add an OID to an SNMP get list
|
||
//
|
||
// Convert the UNICODE string to ANSI
|
||
// Convert it to a real OID (numbers)
|
||
// Add to the Array
|
||
HRESULT
|
||
CSNMP::
|
||
VarListAdd(
|
||
BSTR bstrOID,
|
||
RFC1157VarBindList * prfcList,
|
||
VARIANT *pvarValue
|
||
)
|
||
{
|
||
LPSTR pszOID;
|
||
BOOL bResult;
|
||
AsnObjectIdentifier asnReqObject;
|
||
|
||
if (! (pszOID = MakeNarrow(bstrOID)))
|
||
return SetScriptingError(CLSID_SNMP, IID_ISNMP, GetLastError());
|
||
|
||
bResult = SnmpMgrStrToOid(pszOID, &asnReqObject);
|
||
LocalFree(pszOID);
|
||
|
||
if (!bResult)
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
|
||
prfcList->len++;
|
||
|
||
if (! (prfcList->list = (RFC1157VarBind *) SNMP_realloc (prfcList->list,
|
||
sizeof(RFC1157VarBind) * prfcList->len)))
|
||
return Error(IDS_OUT_OF_MEMORY, IID_ISNMP, E_OUTOFMEMORY);
|
||
|
||
prfcList->list[prfcList->len - 1].name = asnReqObject;
|
||
|
||
return VariantToRFC1157(& (prfcList->list[prfcList->len -1]), pvarValue);
|
||
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: Set
|
||
*
|
||
* PURPOSE: Set a value of a SNMP oid
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* bstrOID: The SNMP Oid in BSTR
|
||
* varValue: The corresponding Oid
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid.
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
Set(
|
||
IN BSTR bstrOID,
|
||
IN VARIANT varValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
HRESULT hr = E_FAIL;
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
|
||
|
||
if (FAILED (hr = VarListAdd(bstrOID, &rfcVarList)))
|
||
{
|
||
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = VariantToRFC1157(&rfcVarList.list[0], &varValue);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
if (!SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_SETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex)) {
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (asniErrorStatus > 0) {
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = S_OK;
|
||
|
||
Cleanup:
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
return hr;
|
||
}
|
||
|
||
/*****************************************************************************\
|
||
* Function: SetList
|
||
*
|
||
* PURPOSE: Set a list of a SNMP oids
|
||
*
|
||
* ARGUMENTS:
|
||
*
|
||
* pvarList: The array of SNMP Oids. The type must be a 1D array of BSTRs
|
||
* pvarValue: The corresponding Oids, it must also b a 1D array of Variants
|
||
*
|
||
* RETURN VALUE:
|
||
* S_OK: If succeed.
|
||
* E_INVALIDARG: Invalid oid or the type of the variant is not a 1D array
|
||
* E_FAIL: If Open method has not been called before
|
||
* E_OUTOFMEMORY: Out of memory
|
||
* other: Returns the last error set by SnmpMgrRequest
|
||
*
|
||
\*****************************************************************************/
|
||
STDMETHODIMP
|
||
CSNMP::
|
||
SetList(
|
||
IN VARIANT * varName,
|
||
IN VARIANT * varValue
|
||
)
|
||
{
|
||
RFC1157VarBindList rfcVarList = {NULL, 0};
|
||
AsnInteger asniErrorStatus;
|
||
AsnInteger asniErrorIndex;
|
||
HRESULT hr = E_FAIL;
|
||
SAFEARRAY *psaName, *psaValue;
|
||
long lLowBound, lUpperBound;
|
||
long ix[1];
|
||
|
||
if (m_SNMPSession == NULL)
|
||
return Error(IDS_NO_SNMP_SESSION, IID_ISNMP, E_FAIL);
|
||
|
||
if (!(varName->vt & VT_ARRAY) || !(varValue->vt & VT_ARRAY))
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
|
||
if (varName->vt & VT_BYREF)
|
||
psaName = *(varName->pparray);
|
||
else
|
||
psaName = varName->parray;
|
||
|
||
if (varValue->vt & VT_BYREF)
|
||
psaValue = *(varValue->pparray);
|
||
else
|
||
psaValue = varValue->parray;
|
||
|
||
if (SafeArrayGetDim(psaName) != 1 || SafeArrayGetDim(psaValue) != 1)
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
|
||
SafeArrayGetLBound(psaName, 1, &lLowBound);
|
||
SafeArrayGetUBound(psaName, 1, &lUpperBound);
|
||
|
||
long lVal;
|
||
|
||
SafeArrayGetLBound(psaValue, 1, &lVal);
|
||
if (lVal != lLowBound)
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
SafeArrayGetUBound(psaValue, 1, &lVal);
|
||
if (lVal != lUpperBound)
|
||
return Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
|
||
for (ix[0] = lLowBound; ix[0] <= lUpperBound; ix[0]++) {
|
||
VARIANT varArgName, varArgValue;
|
||
|
||
VariantClear(&varArgName);
|
||
VariantClear(&varArgValue);
|
||
|
||
hr = SafeArrayGetElement(psaName, ix, &varArgName);
|
||
if (FAILED (hr)) {
|
||
hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (varArgName.vt != VT_BSTR) {
|
||
hr = Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = SafeArrayGetElement(psaValue, ix, &varArgValue);
|
||
if (FAILED (hr))
|
||
goto Cleanup;
|
||
|
||
if (FAILED (hr = VarListAdd(varArgName.bstrVal, &rfcVarList, &varArgValue)))
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (! SnmpMgrRequest(m_SNMPSession,
|
||
ASN_RFC1157_SETREQUEST,
|
||
&rfcVarList,
|
||
&asniErrorStatus,
|
||
&asniErrorIndex))
|
||
{
|
||
hr = SetWinSnmpApiError (GetLastError ());
|
||
goto Cleanup;
|
||
}
|
||
|
||
if (asniErrorStatus > 0) {
|
||
hr = SetSnmpScriptError(asniErrorStatus);
|
||
goto Cleanup;
|
||
}
|
||
|
||
hr = S_OK;
|
||
|
||
Cleanup:
|
||
SnmpUtilVarBindListFree(&rfcVarList);
|
||
return hr;
|
||
}
|
||
|
||
|
||
HRESULT
|
||
CSNMP::
|
||
SetSnmpScriptError(
|
||
IN DWORD dwError
|
||
)
|
||
{
|
||
static DWORD SnmpErrorMapping [] = {
|
||
IDS_SNMP_ERRORSTATUS_NOERROR,
|
||
IDS_SNMP_ERRORSTATUS_TOOBIG,
|
||
IDS_SNMP_ERRORSTATUS_NOSUCHNAME,
|
||
IDS_SNMP_ERRORSTATUS_BADVALUE,
|
||
IDS_SNMP_ERRORSTATUS_READONLY,
|
||
IDS_SNMP_ERRORSTATUS_GENERR,
|
||
IDS_SNMP_ERRORSTATUS_NOACCESS,
|
||
IDS_SNMP_ERRORSTATUS_WRONGTYPE,
|
||
IDS_SNMP_ERRORSTATUS_WRONGLENGTH,
|
||
IDS_SNMP_ERRORSTATUS_WRONGENCODING,
|
||
IDS_SNMP_ERRORSTATUS_WRONGVALUE,
|
||
IDS_SNMP_ERRORSTATUS_NOCREATION,
|
||
IDS_SNMP_ERRORSTATUS_INCONSISTENTVALUE,
|
||
IDS_SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE,
|
||
IDS_SNMP_ERRORSTATUS_COMMITFAILED,
|
||
IDS_SNMP_ERRORSTATUS_UNDOFAILED,
|
||
IDS_SNMP_ERRORSTATUS_AUTHORIZATIONERROR,
|
||
IDS_SNMP_ERRORSTATUS_NOTWRITABLE,
|
||
IDS_SNMP_ERRORSTATUS_INCONSISTENTNAME};
|
||
|
||
if ((int)dwError < 0 || dwError > sizeof (SnmpErrorMapping) / sizeof (DWORD))
|
||
dwError = SNMP_ERRORSTATUS_GENERR;
|
||
return Error(SnmpErrorMapping[dwError], IID_ISNMP, E_FAIL);
|
||
}
|
||
|
||
HRESULT
|
||
CSNMP::
|
||
SetWinSnmpApiError(
|
||
IN DWORD dwError
|
||
)
|
||
{
|
||
static DWORD WinSnmpApiErrorMapping [] = {
|
||
IDS_SNMPAPI_ALLOC_ERROR,
|
||
IDS_SNMPAPI_CONTEXT_INVALID,
|
||
IDS_SNMPAPI_CONTEXT_UNKNOWN,
|
||
IDS_SNMPAPI_ENTITY_INVALID,
|
||
IDS_SNMPAPI_ENTITY_UNKNOWN,
|
||
IDS_SNMPAPI_INDEX_INVALID,
|
||
IDS_SNMPAPI_NOOP,
|
||
IDS_SNMPAPI_OID_INVALID,
|
||
IDS_SNMPAPI_OPERATION_INVALID,
|
||
IDS_SNMPAPI_OUTPUT_TRUNCATED,
|
||
IDS_SNMPAPI_PDU_INVALID,
|
||
IDS_SNMPAPI_SESSION_INVALID,
|
||
IDS_SNMPAPI_SYNTAX_INVALID,
|
||
IDS_SNMPAPI_VBL_INVALID,
|
||
IDS_SNMPAPI_MODE_INVALID,
|
||
IDS_SNMPAPI_SIZE_INVALID,
|
||
IDS_SNMPAPI_NOT_INITIALIZED,
|
||
IDS_SNMPAPI_MESSAGE_INVALID,
|
||
IDS_SNMPAPI_HWND_INVALID,
|
||
IDS_SNMPAPI_OTHER_ERROR,
|
||
IDS_SNMPAPI_TL_NOT_INITIALIZED,
|
||
IDS_SNMPAPI_TL_NOT_SUPPORTED,
|
||
IDS_SNMPAPI_TL_NOT_AVAILABLE,
|
||
IDS_SNMPAPI_TL_RESOURCE_ERROR,
|
||
IDS_SNMPAPI_TL_UNDELIVERABLE,
|
||
IDS_SNMPAPI_TL_SRC_INVALID,
|
||
IDS_SNMPAPI_TL_INVALID_PARAM,
|
||
IDS_SNMPAPI_TL_IN_USE,
|
||
IDS_SNMPAPI_TL_TIMEOUT,
|
||
IDS_SNMPAPI_TL_PDU_TOO_BIG,
|
||
IDS_SNMPAPI_TL_OTHER
|
||
};
|
||
|
||
static DWORD WinSnmpApiError [] = {
|
||
SNMPAPI_ALLOC_ERROR,
|
||
SNMPAPI_CONTEXT_INVALID,
|
||
SNMPAPI_CONTEXT_UNKNOWN,
|
||
SNMPAPI_ENTITY_INVALID,
|
||
SNMPAPI_ENTITY_UNKNOWN,
|
||
SNMPAPI_INDEX_INVALID,
|
||
SNMPAPI_NOOP,
|
||
SNMPAPI_OID_INVALID,
|
||
SNMPAPI_OPERATION_INVALID,
|
||
SNMPAPI_OUTPUT_TRUNCATED,
|
||
SNMPAPI_PDU_INVALID,
|
||
SNMPAPI_SESSION_INVALID,
|
||
SNMPAPI_SYNTAX_INVALID,
|
||
SNMPAPI_VBL_INVALID,
|
||
SNMPAPI_MODE_INVALID,
|
||
SNMPAPI_SIZE_INVALID,
|
||
SNMPAPI_NOT_INITIALIZED,
|
||
SNMPAPI_MESSAGE_INVALID,
|
||
SNMPAPI_HWND_INVALID,
|
||
SNMPAPI_OTHER_ERROR,
|
||
SNMPAPI_TL_NOT_INITIALIZED,
|
||
SNMPAPI_TL_NOT_SUPPORTED,
|
||
SNMPAPI_TL_NOT_AVAILABLE,
|
||
SNMPAPI_TL_RESOURCE_ERROR,
|
||
SNMPAPI_TL_UNDELIVERABLE,
|
||
SNMPAPI_TL_SRC_INVALID,
|
||
SNMPAPI_TL_INVALID_PARAM,
|
||
SNMPAPI_TL_IN_USE,
|
||
SNMPAPI_TL_TIMEOUT,
|
||
SNMPAPI_TL_PDU_TOO_BIG,
|
||
SNMPAPI_TL_OTHER
|
||
};
|
||
|
||
for (int i = 0; i < sizeof (WinSnmpApiError); i++) {
|
||
if (dwError == WinSnmpApiError[i]) {
|
||
dwError = WinSnmpApiErrorMapping[i];
|
||
break;
|
||
}
|
||
}
|
||
return Error(dwError, IID_ISNMP, E_FAIL);
|
||
|
||
|