/***************************************************************************** * * $Workfile: TcpMib.cpp $ * * Copyright (C) 1997 Hewlett-Packard Company. * Copyright (C) 1997 Microsoft Corporation. * All rights reserved. * * 11311 Chinden Blvd. * Boise, Idaho 83714 * *****************************************************************************/ #include "precomp.h" #include "snmpmgr.h" #include "stdmib.h" #include "pingicmp.h" #include "tcpmib.h" #include "status.h" /////////////////////////////////////////////////////////////////////////////// // Global definitions/declerations CTcpMib *g_pTcpMib = 0; int g_cntGlobalAlloc=0; // used for debugging purposes int g_csGlobalCount=0; // to ensure that the CTCPMib is not being deleted improperly, perform usage count on the DLL int g_cntUsage = 0; /////////////////////////////////////////////////////////////////////////////// // GetDLLInterfacePtr -- returns the pointer to the DLL interface extern "C" CTcpMibABC* GetTcpMibPtr( void ) { return (g_pTcpMib); } // GetDLLInterfacePtr() /////////////////////////////////////////////////////////////////////////////// // Ping -- pings the given device // Return Codes: // NO_ERROR if ping is successfull // DEVICE_NOT_FOUND if device is not found extern "C" DWORD Ping( LPCSTR in pHost ) { DWORD dwRetCode = NO_ERROR; // do icmpPing CPingICMP *pPingICMP = new CPingICMP(pHost); if ( !pPingICMP ) return (dwRetCode = GetLastError()) ? dwRetCode : ERROR_OUTOFMEMORY; if ( !pPingICMP->Ping() ) { dwRetCode = ERROR_DEVICE_NOT_FOUND; } delete pPingICMP; return (dwRetCode); } // Ping() /////////////////////////////////////////////////////////////////////////////// // DllMain // BOOL APIENTRY DllMain ( HANDLE in hInst, DWORD in dwReason, LPVOID in lpReserved ) { switch (dwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hInst ); g_cntUsage++; // DLL usage count if ( !g_pTcpMib) { g_pTcpMib = new CTcpMib(); // create the port manager object if (!g_pTcpMib) { return FALSE; } } return TRUE; case DLL_PROCESS_DETACH: g_cntUsage--; // DLL usage count if (g_cntUsage == 0) { if (g_pTcpMib) { delete g_pTcpMib; // FIX! do we need to worry about usage count here?? g_pTcpMib = NULL; } } return TRUE; } return FALSE; } // DllMain() /***************************************************************************** * * CTcpMib implementation * *****************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // static functions & member initialization /////////////////////////////////////////////////////////////////////////////// // CTcpMib::CTcpMib() CTcpMib::CTcpMib( ) { InitializeCriticalSection(&m_critSect); } // ::CTcpMib() /////////////////////////////////////////////////////////////////////////////// // CTcpMib::~CTcpMib() CTcpMib::~CTcpMib( ) { DeleteCriticalSection(&m_critSect); } // ::~CTcpMib() /////////////////////////////////////////////////////////////////////////////// // EnterCSection -- enters the critical section void CTcpMib::EnterCSection( ) { EnterCriticalSection(&m_critSect); // enter critical section } // ::EnterCSection() /////////////////////////////////////////////////////////////////////////////// // ExitCSection -- enters the critical section void CTcpMib::ExitCSection( ) { LeaveCriticalSection(&m_critSect); // exit critical section } // ::ExitCSection() /////////////////////////////////////////////////////////////////////////////// // SupportsPrinterMib -- // BOOL CTcpMib:: SupportsPrinterMib( IN LPCSTR pHost, IN LPCSTR pCommunity, IN DWORD dwDevIndex, OUT PBOOL pbSupported ) { BOOL bRet = FALSE; DWORD dwLastError = ERROR_SUCCESS; EnterCSection(); if ( (dwLastError = Ping(pHost)) == NO_ERROR ) { CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { *pbSupported = pStdMib->TestPrinterMIB(); bRet = TRUE; delete pStdMib; } } ExitCSection(); if (!bRet) SetLastError (dwLastError); return bRet; } // ::SupportsPrinterMib() /////////////////////////////////////////////////////////////////////////////// // GetDeviceDescription -- // // Returns: // NO_ERROR - // ERROR_DEVICE_NOT_FOUND - // SUCCESS_DEVICE_UNKNOWN DWORD CTcpMib:: GetDeviceDescription( IN LPCSTR pHost, IN LPCSTR pCommunity, IN DWORD dwDevIndex, OUT LPTSTR pszPortDesc, IN DWORD dwDescLen ) { DWORD dwRet = NO_ERROR; EnterCSection(); if ( Ping(pHost) == NO_ERROR ) { CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { if ( !pStdMib->GetDeviceDescription(pszPortDesc, dwDescLen)){ dwRet = SUCCESS_DEVICE_UNKNOWN; } delete pStdMib; } } else { dwRet = ERROR_DEVICE_NOT_FOUND; } ExitCSection(); return dwRet; } // ::GetDeviceDescription() /////////////////////////////////////////////////////////////////////////////// // GetDeviceStatus -- // Error Codes: // Returns the mapped printer error code to the spooler error code DWORD CTcpMib::GetDeviceStatus( LPCSTR in pHost, LPCSTR pCommunity, DWORD dwDevIndex ) { DWORD dwRetCode = NO_ERROR; EnterCSection(); // instantiate the CStdMib::GetDeviceType() CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { dwRetCode = pStdMib->GetDeviceStatus(); delete pStdMib; } else { dwRetCode = ERROR_OUTOFMEMORY; } ExitCSection(); return (dwRetCode); } // ::GetDeviceStatus() /////////////////////////////////////////////////////////////////////////////// // GetJobStatus -- // Error Codes: // Returns the mapped printer error code to the spooler error code DWORD CTcpMib::GetJobStatus( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { dwRetCode = pStdMib->GetJobStatus(); delete pStdMib; } else { dwRetCode = ERROR_OUTOFMEMORY; } ExitCSection(); return (dwRetCode); } // ::GetJobType() /////////////////////////////////////////////////////////////////////////////// // GetDeviceAddress -- gets the hardware address of the device // 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() DWORD CTcpMib::GetDeviceHWAddress( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, DWORD in dwSize, // Size in characters of the HWAddress returned LPTSTR out psztHWAddress ) { DWORD dwRetCode = NO_ERROR; EnterCSection(); // instantiate the CStdMib::GetDeviceAddress() CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { dwRetCode = pStdMib->GetDeviceHWAddress(psztHWAddress, dwSize); delete pStdMib; } else { dwRetCode = ERROR_OUTOFMEMORY; } ExitCSection(); return (dwRetCode); } // ::GetDeviceAddress() /////////////////////////////////////////////////////////////////////////////// // GetDeviceInfo -- gets the device description // 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() DWORD CTcpMib::GetDeviceName( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, DWORD in dwSize, // Size in characters of the description returned LPTSTR out psztDescription) { DWORD dwRetCode = NO_ERROR; EnterCSection(); // instantiate the CStdMib::GetDeviceInfo() CStdMib *pStdMib = new CStdMib(pHost, pCommunity, dwDevIndex, this); if ( pStdMib ) { dwRetCode = pStdMib->GetDeviceName(psztDescription, dwSize); delete pStdMib; } else { dwRetCode = ERROR_OUTOFMEMORY; } ExitCSection(); return (dwRetCode); } // ::GetDeviceAddress() /////////////////////////////////////////////////////////////////////////////// // SnmpGet -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpGet. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpGet( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, AsnObjectIdentifier in *pMibObjId, RFC1157VarBindList out *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex, pMibObjId, pVarBindList); if ( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->Get(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if ( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpGet() /////////////////////////////////////////////////////////////////////////////// // SnmpGet -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpGet. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpGet( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, RFC1157VarBindList inout *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex); if ( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->Get(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpGet() /////////////////////////////////////////////////////////////////////////////// // SnmpGetNext -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpGetNext. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpGetNext( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, AsnObjectIdentifier in *pMibObjId, RFC1157VarBindList out *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex, pMibObjId, pVarBindList); if( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->GetNext(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if ( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpGetNext() /////////////////////////////////////////////////////////////////////////////// // SnmpGetNext -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpGetNext. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpGetNext( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, RFC1157VarBindList inout *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex); if ( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->GetNext(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if ( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpGetNext() /////////////////////////////////////////////////////////////////////////////// // SnmpWalk -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpWalk. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpWalk( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, AsnObjectIdentifier in *pMibObjId, RFC1157VarBindList out *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex, pMibObjId, pVarBindList); if( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->Walk(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if ( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpWalk() /////////////////////////////////////////////////////////////////////////////// // SnmpWalk -- given a set of OIDs & a buffer to get the results in, it returns // the results of the SnmpWalk. // // Note: This calls directly into the SnmpMgr APIs DWORD CTcpMib::SnmpWalk( LPCSTR in pHost, LPCSTR in pCommunity, DWORD in dwDevIndex, RFC1157VarBindList inout *pVarBindList) { DWORD dwRetCode = NO_ERROR; EnterCSection(); CSnmpMgr *pSnmpMgr = new CSnmpMgr(pHost, pCommunity, dwDevIndex); if( pSnmpMgr ) { if ( (dwRetCode = pSnmpMgr->GetLastError()) != SNMPAPI_NOERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } if ( (dwRetCode = pSnmpMgr->Walk(pVarBindList)) != NO_ERROR ) { dwRetCode = ERROR_SNMPAPI_ERROR; goto cleanup; } } else { dwRetCode = ERROR_OUTOFMEMORY; } cleanup: if ( pSnmpMgr ) delete pSnmpMgr; ExitCSection(); return (dwRetCode); } // ::SnmpWalk() /////////////////////////////////////////////////////////////////////////////// // SNMPToPrinterStatus -- Maps the received device error to the printer // error codes. // Return Values: // Spooler device error codes DWORD CTcpMib::SNMPToPrinterStatus( const DWORD in dwStatus) { DWORD dwRetCode = NO_ERROR; switch (dwStatus) { case ASYNCH_STATUS_UNKNOWN: dwRetCode = PRINTER_STATUS_NOT_AVAILABLE; break; case ASYNCH_PRINTER_ERROR: dwRetCode = PRINTER_STATUS_ERROR; break; case ASYNCH_DOOR_OPEN: dwRetCode = PRINTER_STATUS_DOOR_OPEN; break; case ASYNCH_WARMUP: dwRetCode = PRINTER_STATUS_WARMING_UP; break; case ASYNCH_RESET: case ASYNCH_INITIALIZING: dwRetCode = PRINTER_STATUS_INITIALIZING; break; case ASYNCH_OUTPUT_BIN_FULL: dwRetCode = PRINTER_STATUS_OUTPUT_BIN_FULL; break; case ASYNCH_PAPER_JAM: dwRetCode = PRINTER_STATUS_PAPER_JAM; break; case ASYNCH_TONER_GONE: dwRetCode = PRINTER_STATUS_NO_TONER; break; case ASYNCH_MANUAL_FEED: dwRetCode = PRINTER_STATUS_MANUAL_FEED; break; case ASYNCH_PAPER_OUT: dwRetCode = PRINTER_STATUS_PAPER_OUT; break; case ASYNCH_OFFLINE: dwRetCode = PRINTER_STATUS_OFFLINE; break; case ASYNCH_INTERVENTION: dwRetCode = PRINTER_STATUS_USER_INTERVENTION; break; case ASYNCH_TONER_LOW: dwRetCode = PRINTER_STATUS_TONER_LOW; break; case ASYNCH_PRINTING: dwRetCode = PRINTER_STATUS_PRINTING; break; case ASYNCH_BUSY: dwRetCode = PRINTER_STATUS_BUSY; break; case ASYNCH_ONLINE: dwRetCode = NO_ERROR; break; default: dwRetCode = PRINTER_STATUS_NOT_AVAILABLE; } return dwRetCode; } // SNMPToPrinterStatus() /////////////////////////////////////////////////////////////////////////////// // SNMPToPortStatus -- Maps the received device error to the printer // error codes. // Return Values: // Spooler device error codes BOOL CTcpMib::SNMPToPortStatus( const DWORD in dwStatus, PPORT_INFO_3 pPortInfo ) { DWORD dwRetCode = NO_ERROR; pPortInfo->dwStatus = 0; pPortInfo->pszStatus = NULL; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; switch (dwStatus) { case ASYNCH_DOOR_OPEN: pPortInfo->dwStatus = PORT_STATUS_DOOR_OPEN; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; break; case ASYNCH_WARMUP: pPortInfo->dwStatus = PORT_STATUS_WARMING_UP; pPortInfo->dwSeverity = PORT_STATUS_TYPE_INFO; break; case ASYNCH_OUTPUT_BIN_FULL: pPortInfo->dwStatus = PORT_STATUS_OUTPUT_BIN_FULL; pPortInfo->dwSeverity = PORT_STATUS_TYPE_WARNING; break; case ASYNCH_PAPER_JAM: pPortInfo->dwStatus = PORT_STATUS_PAPER_JAM; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; break; case ASYNCH_TONER_GONE: pPortInfo->dwStatus = PORT_STATUS_NO_TONER; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; break; case ASYNCH_MANUAL_FEED: pPortInfo->dwStatus = PORT_STATUS_PAPER_PROBLEM; pPortInfo->dwSeverity = PORT_STATUS_TYPE_WARNING; break; case ASYNCH_PAPER_OUT: pPortInfo->dwStatus = PORT_STATUS_PAPER_OUT; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; break; case ASYNCH_PRINTER_ERROR: case ASYNCH_INTERVENTION: case ASYNCH_OFFLINE: pPortInfo->dwStatus = PORT_STATUS_OFFLINE; pPortInfo->dwSeverity = PORT_STATUS_TYPE_ERROR; break; case ASYNCH_TONER_LOW: pPortInfo->dwStatus = PORT_STATUS_TONER_LOW; pPortInfo->dwSeverity = PORT_STATUS_TYPE_WARNING; break; case ASYNCH_STATUS_UNKNOWN: case ASYNCH_POWERSAVE_MODE: case ASYNCH_RESET: case ASYNCH_INITIALIZING: case ASYNCH_PRINTING: case ASYNCH_BUSY: case ASYNCH_ONLINE: default: pPortInfo->dwStatus = 0; pPortInfo->dwSeverity = PORT_STATUS_TYPE_INFO; break; } return dwRetCode; } // ::SNMPStatusToPortStatus()