//*************************************************************************** // // File: // // Module: MS SNMP Provider // // Purpose: // // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include "precomp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include CMapToEvent::CMapToEvent() : m_vbdefn(NULL), m_vbs(NULL, 0) { m_btriedGeneric = FALSE; m_btryGeneric = FALSE; m_bCheckedVersion = FALSE; m_object = NULL; m_nspace = NULL; } CMapToEvent::~CMapToEvent() { if (m_vbs.vbs) { delete [] m_vbs.vbs; } if (m_vbdefn) { m_vbdefn->Release(); } } void CMapToEvent::ResetData() { m_btriedGeneric = FALSE; m_btryGeneric = FALSE; m_bCheckedVersion = FALSE; m_class.Empty(); if(m_vbs.vbs) { delete [] m_vbs.vbs; m_vbs.vbs = NULL; m_vbs.length = 0; } if (m_object) { m_object->Release(); m_object = NULL; } } void CMapToEvent::SetTryGeneric() { m_btriedGeneric = TRUE; m_btryGeneric = TRUE; } BOOL CMapToEvent::IsSNMPv1() { if (!m_bCheckedVersion) { m_bCheckedVersion = TRUE; m_bSNMPv1 = FALSE; //is v1 if the last varbind has objid = snmpTrapEnterprise.0 //and the trapOID truncated by it last sub-id equals the last //varbind's value with a .0 appended. //Get the last varbind's oid and make sure it's the enterpriseOid const SnmpObjectIdentifier& id = m_vbs.vbs[m_vbs.length - 1].pVarBind->GetInstance(); const SnmpValue& snmp_val = m_vbs.vbs[m_vbs.length - 1].pVarBind->GetValue(); if ((id != SNMP_ENT_OID) || (typeid(SnmpObjectIdentifier) != typeid(snmp_val))) { return FALSE; } //create the trapoid and truncate the last subid SnmpObjectIdentifierType trapid(m_oid); SnmpObjectIdentifier trunctrapid(trapid.GetValue(), trapid.GetValueLength() - 1); //now add .0 to the value of the enterpriseOid ULONG val[1] = {0}; SnmpObjectIdentifier zeroid(val, 1); SnmpObjectIdentifier extendoid((const SnmpObjectIdentifier&)snmp_val + zeroid); m_bSNMPv1 = (extendoid == trunctrapid); } return m_bSNMPv1; } void CMapToEvent::SetData(const char* sender_addr, const char* security_Context, const char* snmpTrapOid, const char* transport, SnmpVarBindList& vbList, CWbemServerWrap* nspace) { m_nspace = nspace; m_addr = sender_addr; m_ctxt = security_Context; m_oid = snmpTrapOid; m_transport = transport; UINT length = vbList.GetLength(); if (length >= 2) //must have at least two varbinds! { m_vbs.vbs = new VarBindObjectStruct[length]; m_vbs.length = length; vbList.Reset(); for (UINT i=0; i < length; i++) { vbList.Next () ; m_vbs.vbs[i].fDone = FALSE; m_vbs.vbs[i].pVarBind = (SnmpVarBind*) vbList.Get(); } } else { m_vbs.vbs = NULL; m_vbs.length = 0; } } void CMapToEvent::GetClassInstance(IWbemClassObject **ppObj) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClassInstance getting class object\r\n"); ) if (m_object != NULL) { *ppObj = m_object; return; } if (m_class.IsEmpty()) { if (!GetClass() || m_class.IsEmpty()) { *ppObj = NULL; DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClassInstance failed to get class name\r\n"); ) return; } } BSTR path = m_class.AllocSysString(); if (SUCCEEDED(m_nspace->GetObject(path, NULL, ppObj ))) { if (FAILED((*ppObj)->SpawnInstance(0, &m_object))) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClassInstance failed to spawn instance\r\n"); ) m_object = NULL; } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClassInstance got instance\r\n"); ) } (*ppObj)->Release(); } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClassInstance failed to get class definition\r\n"); ) } SysFreeString(path); *ppObj = m_object; } HRESULT CMapToEvent::GetPropertyValue(long lNumElements, MYWBEM_NAME_ELEMENT *aElements, long lFlags, VARIANT *pvValue) { VariantInit(pvValue); if ((lNumElements == 0) || (NULL == aElements) || (NULL == pvValue) || (pvValue->vt != VT_EMPTY)) { return E_INVALIDARG; } if (m_vbs.length == 0) { return WBEM_E_FAILED; } //try the standard properties first HRESULT result = GetStandardProperty(lNumElements, aElements, lFlags, pvValue); if (SUCCEEDED(result)) { return result; } if (m_class.IsEmpty()) { if (!GetClass() || m_class.IsEmpty()) { return WBEM_E_FAILED; } } if (TriedGeneric()) { //if we are generic, check the varbind properties return GetVBProperty(lNumElements, aElements, lFlags, pvValue); } else { //else check the specific properties... return GetSpecificPropertyValue(lNumElements, aElements, lFlags, pvValue); } return WBEM_E_FAILED; } HRESULT CMapToEvent::GetStandardProperty(long lNumElements, MYWBEM_NAME_ELEMENT *aElements, long lFlags, VARIANT *pvValue) { if ((lNumElements == 1) && (0 == aElements[0].m_nType)) //the property name! { if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, WBEMS_CLASS_PROP)) { if (m_class.IsEmpty()) { if (!GetClass() || m_class.IsEmpty()) { return E_FAIL; } } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_class.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_SOID_PROP)) { if (m_oid.IsEmpty()) { return E_FAIL; } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_oid.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_ADDR_PROP)) { if (m_addr.IsEmpty()) { return E_FAIL; } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_addr.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_TADDR_PROP)) { if (m_addr.IsEmpty()) { return E_FAIL; } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_addr.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_TRANS_PROP)) { if (m_transport.IsEmpty()) { return E_FAIL; } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_transport.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_COMM_PROP)) { if (m_ctxt.IsEmpty()) { return E_FAIL; } pvValue->vt = VT_BSTR; pvValue->bstrVal = m_ctxt.AllocSysString(); } else if (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_TIME_PROP)) { const SnmpObjectIdentifier& id = m_vbs.vbs[0].pVarBind->GetInstance(); if (id != SNMP_SYS_UP_OID) { return E_FAIL; } const SnmpValue& val = m_vbs.vbs[0].pVarBind->GetValue(); if (typeid(SnmpTimeTicks) == typeid(val)) { pvValue->vt = VT_I4; pvValue->lVal = ((const SnmpTimeTicks&)val).GetValue(); } else { return E_FAIL; } } else { return E_FAIL; } } else { return E_FAIL; //no standard property has more than one element to its name } return S_OK; //got the property! } HRESULT CMapToEvent::GetVBProperty(long lNumElements, MYWBEM_NAME_ELEMENT *aElements, long lFlags, VARIANT *pvValue) { if ((lNumElements <= 0) || (NULL == aElements) || (NULL == pvValue)) { return E_INVALIDARG; } HRESULT status = E_FAIL; if ((0 == aElements[0].m_nType) && (m_vbs.length > 2) && (0 == _wcsicmp(aElements[0].Element.m_wszPropertyName, EVENT_VBL_PROP)) ) { //the property name is correct... if (lNumElements == 1) { //all the varbinds except 1 and 2... //create the classobjects stick 'em in a safearray and send 'em back! SAFEARRAYBOUND rgsabound[1]; SAFEARRAY* psa; rgsabound[0].lLbound = 0; rgsabound[0].cElements = m_vbs.length - 2; psa = SafeArrayCreate(VT_UNKNOWN, 1, rgsabound); LONG ix; BOOL berror = FALSE; for (UINT i = 2; i < m_vbs.length; i++) { IWbemClassObject* vbobj = GetVBClassObjectByIndex(i); if (NULL != vbobj) { ix = i-2; if ( S_OK != SafeArrayPutElement(psa, &ix, (IUnknown *)vbobj)) { vbobj->Release (); berror = TRUE; break; } vbobj->Release (); } else { berror = TRUE; break; } } if (berror) { SafeArrayDestroy(psa); } else { status = WBEM_NO_ERROR; pvValue->vt = VT_ARRAY | VT_UNKNOWN; pvValue->parray = psa; } } else if ((1 == aElements[1].m_nType) && (m_vbs.length > (aElements[1].Element.m_lArrayIndex + 2))) { if (lNumElements == 2) { //get the n(= aElements[1].Element.m_lArrayIndex + 2)th varbind //create a classobject with it and send back the class object IWbemClassObject* vbobj = GetVBClassObjectByIndex(aElements[1].Element.m_lArrayIndex + 2); if (NULL != vbobj) { status = WBEM_NO_ERROR; pvValue->vt = VT_UNKNOWN; pvValue->punkVal = (IUnknown*) vbobj; } } else if (0 == aElements[2].m_nType) { if (lNumElements == 3) { //get the single property value int cmpval = _wcsicmp(aElements[2].Element.m_wszPropertyName, VB_OBJID_PROP2); if (0 == cmpval) { //get the objectid if (GetVBPropOIDByIndex((aElements[1].Element.m_lArrayIndex + 2), *pvValue)) { status = WBEM_NO_ERROR; } } else if ((cmpval > 0) && (0 == _wcsicmp(aElements[2].Element.m_wszPropertyName, VB_ENCODING_PROP1))) { //get the ASNType (Encoding < ObjectIdentifier) CString t; if (GetVBPropValueByIndex((aElements[1].Element.m_lArrayIndex + 2), t, *pvValue)) { VariantClear(pvValue); status = WBEM_NO_ERROR; pvValue->vt = VT_BSTR; pvValue->bstrVal = t.AllocSysString(); } } else if (0 == _wcsicmp(aElements[2].Element.m_wszPropertyName, VB_VALUE_PROP3)) { //get the Value (Value < ObjectID) CString t; if (GetVBPropValueByIndex((aElements[1].Element.m_lArrayIndex + 2), t, *pvValue)) { status = WBEM_NO_ERROR; } } } else if ((lNumElements == 4) && (1 == aElements[3].m_nType) && (0 == _wcsicmp(aElements[2].Element.m_wszPropertyName, VB_VALUE_PROP3)) ) { //get the byte value of Value[x] CString t; VARIANT v; if (GetVBPropValueByIndex((aElements[1].Element.m_lArrayIndex + 2), t, v)) { if ((VT_ARRAY | VT_UI1) == v.vt) { LONG ix = aElements[3].Element.m_lArrayIndex; UCHAR datum; if (S_OK == SafeArrayGetElement(v.parray, &ix, (void*)&datum)) { status = WBEM_NO_ERROR; pvValue->vt = VT_UI1; pvValue->bVal = datum; } } VariantClear(&v); } } } } } return status; } IWbemClassObject* CMapToEvent::GetVBClassDefn() { if (NULL == m_vbdefn) { BSTR path = SysAllocString(VB_CLASS_PATH); m_nspace->GetObject(path, NULL, &m_vbdefn ) ; SysFreeString(path); } return m_vbdefn; } IWbemClassObject* CMapToEvent::GetVBClassObjectByIndex(UINT index) { IWbemClassObject* ret = NULL; if (NULL != GetVBClassDefn()) { if (SUCCEEDED(m_vbdefn->SpawnInstance(0, &ret))) { CString type; VARIANT vV; if (GetVBPropValueByIndex(index, type, vV)) { BSTR asntypeprop = SysAllocString(VB_ENCODING_PROP1); VARIANT vT; vT.vt = VT_BSTR; vT.bstrVal = type.AllocSysString(); //set the type and value. if (SUCCEEDED(ret->Put(asntypeprop, 0, &vT, 0))) { BSTR valueprop = SysAllocString(VB_VALUE_PROP3); VARIANT* pV = &vV; VARTYPE Vtype = 0; if ((VT_EMPTY == vV.vt) || (VT_EMPTY == vV.vt)) { Vtype = VT_ARRAY|VT_UI1; //default type pV = NULL; } if (SUCCEEDED(ret->Put(valueprop, 0, pV, Vtype))) { VARIANT vID; //get the oid if(GetVBPropOIDByIndex(index, vID)) { BSTR oidprop = SysAllocString(VB_OBJID_PROP2); //set the oid if (FAILED(ret->Put(oidprop, 0, &vID, 0))) { ret->Release(); ret = NULL; } SysFreeString(oidprop); VariantClear(&vID); } else { ret->Release(); ret = NULL; } } else { ret->Release(); ret = NULL; } SysFreeString(valueprop); } else //failed to put the type property { ret->Release(); ret = NULL; } VariantClear(&vT); SysFreeString(asntypeprop); VariantClear(&vV); } else //failed to SpawnInstance { ret->Release(); ret = NULL; } } } return ret; } //index assumed to be in valid range BOOL CMapToEvent::GetVBPropValueByIndex(UINT index, CString& type, VARIANT& vval) { const SnmpValue& val = m_vbs.vbs[index].pVarBind->GetValue(); //the data is an array of bytes... SAFEARRAYBOUND rgsabound[1]; SAFEARRAY* psa; rgsabound[0].lLbound = 0; VariantInit(&vval); if (typeid(SnmpNull) == typeid(val)) { type = ASN_NULL; } else if (typeid(SnmpNoSuchObject) == typeid(val)) { type = ASN_NSO; } else if (typeid(SnmpNoSuchInstance) == typeid(val)) { type = ASN_NSI; } else if (typeid(SnmpEndOfMibView) == typeid(val)) { type = ASN_EOMV; } else if (typeid(SnmpInteger) == typeid(val)) { type = ASN_INTEGER; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpInteger&)val).GetValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpGauge) == typeid(val)) { type = ASN_GUAGE; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpGauge&)val).GetValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpCounter) == typeid(val)) { type = ASN_COUNTER; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpCounter&)val).GetValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpTimeTicks) == typeid(val)) { type = ASN_TIME; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpTimeTicks&)val).GetValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpOctetString) == typeid(val)) { type = ASN_OCTET; UCHAR* pdata; UINT datalen = (((const SnmpOctetString&)val).GetValueLength()) * sizeof(UCHAR); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UCHAR* data = ((const SnmpOctetString&)val).GetValue(); memcpy((void *)pdata, (void *)data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpOpaque) == typeid(val)) { type = ASN_OPAQUE; UCHAR* pdata; UINT datalen = (((const SnmpOpaque&)val).GetValueLength()) * sizeof(UCHAR); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UCHAR* data = ((const SnmpOpaque&)val).GetValue(); memcpy((void *)pdata, (void *)data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpObjectIdentifier) == typeid(val)) { type = ASN_OID; UCHAR* pdata; UINT datalen = (((const SnmpObjectIdentifier&)val).GetValueLength()) * sizeof(ULONG); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } ULONG* data = ((const SnmpObjectIdentifier&)val).GetValue(); memcpy((void *)pdata, (void *)data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpIpAddress) == typeid(val)) { type = ASN_ADDR; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = htonl(((const SnmpIpAddress&)val).GetValue()); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpUInteger32) == typeid(val)) { type = ASN_UINT32; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = datalen; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpUInteger32&)val).GetValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else if(typeid(SnmpCounter64) == typeid(val)) { type = ASN_COUNTER64; UCHAR* pdata; UINT datalen = sizeof(UINT); rgsabound[0].cElements = (datalen * 2); psa = SafeArrayCreate(VT_UI1, 1, rgsabound); if (NULL == psa) { return FALSE; //out of memory!!! } if (FAILED(SafeArrayAccessData(psa, (void HUGEP* FAR*)&pdata))) { return FALSE; } UINT data = ((const SnmpCounter64&)val).GetHighValue(); memcpy((void *)pdata, (void *)&data, datalen); pdata += datalen; data = ((const SnmpCounter64&)val).GetLowValue(); memcpy((void *)pdata, (void *)&data, datalen); SafeArrayUnaccessData(psa); vval.vt = VT_ARRAY|VT_UI1; vval.parray = psa; } else { //should not get here! return FALSE; } return TRUE; } //index assumed to be in valid range BOOL CMapToEvent::GetVBPropOIDByIndex(UINT index, VARIANT& vOid) { const SnmpObjectIdentifier& id = m_vbs.vbs[index].pVarBind->GetInstance(); char * oid = id.GetAllocatedString(); if (NULL != oid) { VariantInit(&vOid); CString oidstr(oid); delete [] oid; vOid.vt = VT_BSTR; vOid.bstrVal = oidstr.AllocSysString(); return TRUE; } return FALSE; } //sets the m_class variable. if btryGeneric is set gets the generic class. //if m_btryGeneric is not set and a generic class is returned m_btriedGeneric //must be set to true. BOOL CMapToEvent::GetClass() { if (!m_btryGeneric) { if (GetSpecificClass()) { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClass got specific class\r\n"); ) return TRUE; } } SetTryGeneric(); if (IsSNMPv1()) { m_class = GetV1Class(); DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClass getting V1 class\r\n"); ) } else { DebugMacro9( SnmpDebugLog :: s_SnmpDebugLog->WriteFileAndLine ( __FILE__,__LINE__, L"CMapToEvent::GetClass getting V2 class\r\n"); ) m_class = GetV2Class(); } return TRUE; }