windows-nt/Source/XPSP1/NT/printscan/print/spooler/oleprn/olesnmp.cpp

1221 lines
35 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************\
* 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);
}
// Convert part of the the variant array to
// RFC1157VarBindList used in SnmpMgrRequest call
HRESULT
CSNMP::
VarToRfcVarList(
long lbound,
long ubound,
SAFEARRAY *psa,
RFC1157VarBindList * prfcVarList
)
{
long ix[1];
VARIANT var;
HRESULT hr = S_OK;
for (ix[0] = lbound; ix[0] <= ubound; ix[0]++) {
VariantClear(&var);
hr = SafeArrayGetElement(psa, ix, &var);
if (FAILED (hr) || var.vt != VT_BSTR) {
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
break;
}
hr = VarListAdd(var.bstrVal, prfcVarList);
if (FAILED (hr)) {
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
break;
}
}
return hr;
}
// Append RFC1157VarBindList used in SnmpMgrRequest call at the
// end of the variant array
HRESULT
CSNMP::
RfcToVarList(
long lbound,
RFC1157VarBindList *prfcVarList,
SAFEARRAY * psaOut
)
{
long ix[1];
DWORD i;
VARIANT var;
HRESULT hr = S_OK;
for(ix[0] = lbound, i = 0; i < prfcVarList->len; i++, ix[0]++) {
hr = RFC1157ToVariant(&var, & prfcVarList->list[i]);
if (FAILED (hr))
break;
hr = SafeArrayPutElement(psaOut, ix, &var);
if (FAILED (hr)) {
Error(IDS_INVALIDARG, IID_ISNMP, E_INVALIDARG);
break;
}
}
return hr;
}