/***************************************************************************** * * $Workfile: StdMib.cpp $ * * Copyright (C) 1997 Hewlett-Packard Company. * All rights reserved. * * 11311 Chinden Blvd. * Boise, Idaho 83714 * *****************************************************************************/ #include "precomp.h" #include "snmpmgr.h" #include "stdoids.h" #include "status.h" #include "stdmib.h" #include "tcpmib.h" /////////////////////////////////////////////////////////////////////////////// // CStdMib::CStdMib() CStdMib::CStdMib( CTcpMib in *pParent ) : m_dwDevIndex( 1 ),m_pParent(pParent) { m_VarBindList.len = 0; m_VarBindList.list = NULL; *m_szAgent = '\0'; strncpyn(m_szCommunity, DEFAULT_SNMP_COMMUNITYA, sizeof( m_szCommunity)); } // ::CStdMib() /////////////////////////////////////////////////////////////////////////////// // CStdMib::CStdMib() CStdMib::CStdMib(const char in *pHost, const char in *pCommunity, DWORD dwDevIndex, CTcpMib in *pParent ) : m_dwDevIndex( dwDevIndex ),m_pParent(pParent) { m_VarBindList.len = 0; m_VarBindList.list = NULL; strncpyn(m_szAgent, pHost, sizeof( m_szAgent )); strncpyn(m_szCommunity, pCommunity, sizeof( m_szCommunity )); } // ::CStdMib() /////////////////////////////////////////////////////////////////////////////// // CStdMib::~CStdMib() CStdMib::~CStdMib() { m_pParent = NULL; } // ::~CStdMib() /////////////////////////////////////////////////////////////////////////////// // GetDeviceDescription // BOOL CStdMib::GetDeviceDescription( OUT LPTSTR pszPortDescription, IN DWORD dwDescLen ) { BOOL bRet = FALSE; DWORD dwLen; LPSTR psz; m_VarBindList.list = NULL; m_VarBindList.len = 0; if ( NO_ERROR != OIDQuery(OT_DEVICE_SYSDESCR, SNMP_GET) ) goto cleanup; // // If we got the device description successfully, allocate memory and // return this back in a UNICODE string. Caller is responsible for // freeing it using free() // psz = (LPSTR)m_VarBindList.list[0].value.asnValue.string.stream; dwLen = (DWORD)m_VarBindList.list[0].value.asnValue.string.length; if ( bRet = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, psz, dwLen, pszPortDescription, dwDescLen) ) pszPortDescription[dwDescLen-1] = TEXT('\0'); cleanup: SnmpUtilVarBindListFree(&m_VarBindList); return bRet; } // ::GetDeviceDescription() /////////////////////////////////////////////////////////////////////////////// // GetDeviceStatus -- gets the device status DWORD CStdMib::GetDeviceStatus( ) { DWORD dwRetCode = NO_ERROR; dwRetCode = StdMibGetPeripheralStatus( m_szAgent, m_szCommunity, m_dwDevIndex); return dwRetCode; } // ::GetDeviceStatus() /////////////////////////////////////////////////////////////////////////////// // GetJobStatus -- gets the device status, and maps it to the spooler // error codes -- see JOB_INFO_2 // Error Codes: // Spooler error codes DWORD CStdMib::GetJobStatus( ) { DWORD dwRetCode = NO_ERROR; DWORD dwStatus = NO_ERROR; dwRetCode = StdMibGetPeripheralStatus( m_szAgent, m_szCommunity, m_dwDevIndex ); if (dwRetCode != NO_ERROR) { dwStatus = MapJobErrorToSpooler( dwRetCode ); } return dwStatus; } // ::GetJobStatus() /////////////////////////////////////////////////////////////////////////////// // GetDeviceAddress -- gets the device hardware address // Error Codes: // NO_ERROR if successful // ERROR_NOT_ENOUGH_MEMORY if memory allocation failes // ERROR_INVALID_HANDLE if can't build the variable bindings // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported // SNMP_ERRORSTATUS_BADVALUE // SNMP_ERRORSTATUS_READONLY // SNMP_ERRORSTATUS_GENERR // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError() // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError() // SNMPAPI_ERROR if open fails -- set by GetLastError() DWORD CStdMib::GetDeviceHWAddress( LPTSTR out psztHWAddress, DWORD dwSize ) // Size of in characters in of HW address { DWORD dwRetCode = NO_ERROR; UINT i = 0; char szTmpHWAddr[256]; // Process the variableBinding m_VarBindList.list = NULL; m_VarBindList.len = 0; // get the hardware address dwRetCode = OIDQuery(OT_DEVICE_ADDRESS, SNMP_GETNEXT); // query the first entry in the table if (dwRetCode != NO_ERROR) { goto cleanup; } while (1) // instead of walking the tree, do a get next, until we filled up the HW address -- saves on the network communications { i = 0; // process the variableBinding if ( IS_ASN_INTEGER(m_VarBindList, i) ) // check the ifType { if ( GET_ASN_NUMBER(m_VarBindList, i) == IFTYPE_ETHERNET) { StringCchPrintfA (szTmpHWAddr, COUNTOF (szTmpHWAddr), "%02X%02X%02X%02X%02X%02X", GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 0), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 1), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 2), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 3), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 4), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 5) ); MBCS_TO_UNICODE(psztHWAddress, dwSize, szTmpHWAddr); dwRetCode = NO_ERROR; break; } else if ( GET_ASN_NUMBER(m_VarBindList, i) == IFTYPE_OTHER) // apperently, XEROX encodes their HW address w/ ifType = other { // check if the HWAddress is NULL if ( GET_ASN_STRING_LEN(m_VarBindList, i+1) != 0) { StringCchPrintfA (szTmpHWAddr, COUNTOF (szTmpHWAddr), "%02X%02X%02X%02X%02X%02X", GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 0), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 1), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 2), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 3), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 4), GET_ASN_OCTETSTRING_CHAR(m_VarBindList, i+1, 5) ); MBCS_TO_UNICODE(psztHWAddress, dwSize, szTmpHWAddr); dwRetCode = NO_ERROR; break; } } } // didn't get what we were looking for, so copy the address over & do a another GetNext() if( !OIDVarBindCpy(&m_VarBindList) ) { dwRetCode = GetLastError(); goto cleanup; } if ( !SnmpUtilOidNCmp( &m_VarBindList.list[0].name, &OID_Mib2_ifTypeTree, OID_Mib2_ifTypeTree.idLength) ) { break; // end of the tree } dwRetCode = OIDQuery(&m_VarBindList, SNMP_GETNEXT); // query the next entry in the table if (dwRetCode != NO_ERROR) { goto cleanup; } } // end while() cleanup: SnmpUtilVarBindListFree(&m_VarBindList); return dwRetCode; } // ::GetDeviceHWAddress() /////////////////////////////////////////////////////////////////////////////// // GetDeviceInfo -- gets the device description, such as the manufacturer string // Error Codes: // NO_ERROR if successful // ERROR_NOT_ENOUGH_MEMORY if memory allocation failes // ERROR_INVALID_HANDLE if can't build the variable bindings // SNMP_ERRORSTATUS_TOOBIG if the packet returned is big // SNMP_ERRORSTATUS_NOSUCHNAME if the OID isn't supported // SNMP_ERRORSTATUS_BADVALUE // SNMP_ERRORSTATUS_READONLY // SNMP_ERRORSTATUS_GENERR // SNMP_MGMTAPI_TIMEOUT -- set by GetLastError() // SNMP_MGMTAPI_SELECT_FDERRORS -- set by GetLastError() // SNMPAPI_ERROR if Open() for session fails DWORD CStdMib::GetDeviceName( LPTSTR out psztDescription, DWORD in dwSize ) //Size in characters of the psztDescription { DWORD dwRetCode = NO_ERROR; // Process the variableBinding m_VarBindList.list = NULL; m_VarBindList.len = 0; // 1st test for the support of Printer MIB -- note if Printer MIB supported, so is HR MIB BOOL bTestPrtMIB = TestPrinterMIB(); char szTmpDescr[MAX_DEVICEDESCRIPTION_STR_LEN]; UINT i=0; // process the bindings if (bTestPrtMIB) // parse the data from the HR MIB device entry { while (1) // instead of walking the tree, do a get next, until we filled up the HW address -- saves on the network communications { i = 0; dwRetCode = OIDQuery(OT_DEVICE_DESCRIPTION, SNMP_GETNEXT); if (dwRetCode != NO_ERROR) { goto cleanup; } // process the variableBinding if ( IS_ASN_OBJECTIDENTIFIER(m_VarBindList, i) ) // check the hrDeviceType { // compare it to hrDevicePrinter if (SnmpUtilOidCmp(GET_ASN_OBJECT(&m_VarBindList, i), &HRMIB_hrDevicePrinter) == 0) { // found the printer description, get the hrDeviceDescr if ( IS_ASN_OCTETSTRING(m_VarBindList, i) ) { if (GET_ASN_OCTETSTRING(szTmpDescr, sizeof(szTmpDescr), m_VarBindList, i)) { MBCS_TO_UNICODE(psztDescription, dwSize, szTmpDescr); dwRetCode = NO_ERROR; break; } else { dwRetCode = SNMP_ERRORSTATUS_TOOBIG; break; } } else { dwRetCode = SNMP_ERRORSTATUS_NOSUCHNAME; break; } } } // didn't get what we were looking for, so copy the address over & do a another GetNext() if( !OIDVarBindCpy(&m_VarBindList) ) { dwRetCode = GetLastError(); goto cleanup; } } // end while() } // if TestPrinterMIB() TRUE else { dwRetCode = OIDQuery(OT_DEVICE_SYSDESCR, SNMP_GET); if (dwRetCode != NO_ERROR) { goto cleanup; } // process the variables if (GET_ASN_OCTETSTRING(szTmpDescr, sizeof(szTmpDescr), m_VarBindList, i)) { MBCS_TO_UNICODE(psztDescription, dwSize, szTmpDescr); dwRetCode = NO_ERROR; } } // if TestPrinterMIB() FALSE cleanup: SnmpUtilVarBindListFree(&m_VarBindList); return dwRetCode; } // ::GetDeviceStatus() /////////////////////////////////////////////////////////////////////////////// // TestPrinterMIB -- tests if the device supports Printer MIB BOOL CStdMib::TestPrinterMIB( ) { DWORD dwRetCode = NO_ERROR; BOOL bRetCode = FALSE; // Process the variableBinding m_VarBindList.list = NULL; m_VarBindList.len = 0; dwRetCode = OIDQuery(OT_TEST_PRINTER_MIB, SNMP_GETNEXT); if (dwRetCode != NO_ERROR) { bRetCode = FALSE; goto cleanup; } // compare the resulting value w/ the Printer MIB tree value if (SnmpUtilOidNCmp(GET_ASN_OID_NAME(&m_VarBindList, 0), &PrtMIB_OidPrefix, PrtMIB_OidPrefix.idLength) == 0) { bRetCode = TRUE; goto cleanup; } cleanup: SnmpUtilVarBindListFree(&m_VarBindList); return (bRetCode); } // ::TestPrinterMIB() /////////////////////////////////////////////////////////////////////////////// // OIDQuery -- calls into the CTcpMib class to query the OIDs passed in DWORD CStdMib::OIDQuery( AsnObjectIdentifier in *pMibObjId, SNMPCMD in eSnmpCmd ) { DWORD dwRetCode = NO_ERROR; if( m_pParent == NULL ) { dwRetCode = ERROR_INVALID_HANDLE; goto cleanup; } switch (eSnmpCmd) { case SNMP_GET: dwRetCode = m_pParent->SnmpGet(m_szAgent, m_szCommunity, m_dwDevIndex, pMibObjId, &m_VarBindList); goto cleanup; break; case SNMP_WALK: dwRetCode = m_pParent->SnmpWalk(m_szAgent, m_szCommunity, m_dwDevIndex, pMibObjId, &m_VarBindList); goto cleanup; break; case SNMP_GETNEXT: dwRetCode = m_pParent->SnmpGetNext(m_szAgent, m_szCommunity, m_dwDevIndex, pMibObjId, &m_VarBindList); goto cleanup; break; case SNMP_SET: default: dwRetCode = ERROR_NOT_SUPPORTED; goto cleanup; } cleanup: if (dwRetCode != NO_ERROR) { SnmpUtilVarBindListFree(&m_VarBindList); } return (dwRetCode); } // ::OIDQuery() /////////////////////////////////////////////////////////////////////////////// // OIDQuery -- calls into the CTcpMib class to query the OIDs passed in DWORD CStdMib::OIDQuery( RFC1157VarBindList inout *pVarBindList, SNMPCMD in eSnmpCmd ) { DWORD dwRetCode = NO_ERROR; if( m_pParent == NULL ) { dwRetCode = ERROR_INVALID_HANDLE; goto cleanup; } switch (eSnmpCmd) { case SNMP_GET: dwRetCode = m_pParent->SnmpGet(m_szAgent, m_szCommunity, m_dwDevIndex, pVarBindList); goto cleanup; break; case SNMP_WALK: dwRetCode = m_pParent->SnmpWalk(m_szAgent, m_szCommunity, m_dwDevIndex, pVarBindList); goto cleanup; break; case SNMP_GETNEXT: dwRetCode = m_pParent->SnmpGetNext(m_szAgent, m_szCommunity, m_dwDevIndex, pVarBindList); goto cleanup; break; case SNMP_SET: default: dwRetCode = ERROR_NOT_SUPPORTED; goto cleanup; } cleanup: if (dwRetCode != NO_ERROR) { SnmpUtilVarBindListFree(pVarBindList); } return (dwRetCode); } // ::OIDQuery() /////////////////////////////////////////////////////////////////////////////// // OIDVarBindCpy -- BOOL CStdMib::OIDVarBindCpy( RFC1157VarBindList inout *pVarBindList ) { UINT i=0; AsnObjectIdentifier tempOid; for (i=0; i< PRFC1157_VARBINDLIST_LEN(pVarBindList); i++) { if( SnmpUtilOidCpy( &tempOid, &(PGET_ASN_OID_NAME(pVarBindList, i)))) { SnmpUtilVarBindFree(&(pVarBindList->list[i])); if ( SnmpUtilOidCpy(&(PGET_ASN_OID_NAME(pVarBindList, i)), &tempOid)) { PGET_ASN_TYPE(pVarBindList, i) = ASN_NULL; SnmpUtilOidFree(&tempOid); } else { return(FALSE); } } else { return(FALSE); } } return( TRUE ); } // ::OIDVarBindCpy() /////////////////////////////////////////////////////////////////////////////// // MapJobErrorToSpooler -- Maps the received device error to the spooler // error codes. // Return Values: // Spooler device error codes DWORD CStdMib::MapJobErrorToSpooler( const DWORD in dwStatus) { DWORD dwRetCode = NO_ERROR; switch (dwStatus) { case ASYNCH_WARMUP: case ASYNCH_INITIALIZING: dwRetCode = JOB_STATUS_OFFLINE; break; case ASYNCH_DOOR_OPEN: case ASYNCH_PRINTER_ERROR: case ASYNCH_TONER_LOW: case ASYNCH_OUTPUT_BIN_FULL: case ASYNCH_STATUS_UNKNOWN: case ASYNCH_RESET: case ASYNCH_MANUAL_FEED: case ASYNCH_BUSY: case ASYNCH_PAPER_JAM: case ASYNCH_TONER_GONE: dwRetCode = JOB_STATUS_ERROR; break; case ASYNCH_PAPER_OUT: dwRetCode = JOB_STATUS_PAPEROUT; break; case ASYNCH_OFFLINE: dwRetCode = JOB_STATUS_OFFLINE; break; case ASYNCH_INTERVENTION: dwRetCode = JOB_STATUS_USER_INTERVENTION; break; case ASYNCH_PRINTING: dwRetCode = JOB_STATUS_PRINTING; break; case ASYNCH_ONLINE: dwRetCode = NO_ERROR; break; default: dwRetCode = JOB_STATUS_PRINTING; } return dwRetCode; } // ::MapJobErrorToSpooler() BOOL CStdMib::GetAsnOctetString( char *pszStr, DWORD dwCount, RFC1157VarBindList *pVarBindList, UINT i) { _ASSERTE( pszStr && pVarBindList ); DWORD dwSize = GET_ASN_STRING_LEN( *pVarBindList, i); return dwCount >= dwSize ? memcpy(pszStr, pVarBindList->list[i].value.asnValue.string.stream, dwSize) != NULL : FALSE; }