/*++ Copyright (c) 1992-1996 Microsoft Corporation Module Name: prnt_lm.c Abstract: This file contains the routines which actually call Lan Manager and retrieve the contents of the print queue table, including cacheing. Environment: User Mode - Win32 Revision History: 10-May-1996 DonRyan Removed banner from Technology Dynamics, Inc. --*/ //--------------------------- WINDOWS DEPENDENCIES -------------------------- //--------------------------- STANDARD DEPENDENCIES -- #include ---- #ifdef WIN32 #include #include #endif #include #include #include #include #include //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ #include "mib.h" #include "mibfuncs.h" #include "prnt_tbl.h" #include "lmcache.h" //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- //--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- //--------------------------- PRIVATE CONSTANTS ----------------------------- #define SafeBufferFree(x) if(NULL != x) NetApiBufferFree( x ) #define SafeFree(x) if(NULL != x) SnmpUtilMemFree( x ) //--------------------------- PRIVATE STRUCTS ------------------------------- //--------------------------- PRIVATE VARIABLES ----------------------------- //--------------------------- PRIVATE PROTOTYPES ---------------------------- //--------------------------- PRIVATE PROCEDURES ---------------------------- int __cdecl prnt_entry_cmp( IN const PRINTQ_ENTRY *A, IN const PRINTQ_ENTRY *B ) ; void build_prnt_entry_oids( ); //--------------------------- PUBLIC PROCEDURES ----------------------------- // // MIB_prnt_lmget // Retrieve print queue table information from Lan Manager. // If not cached, sort it and then // cache it. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // SNMPAPI MIB_prntq_lmget( ) { DWORD entriesread = 0; // init number of table entries read DWORD bytesNeeded = 0; // init size needed DWORD dwLastError = ERROR_SUCCESS; // init last error to no error LPBYTE bufptr; unsigned lmCode; unsigned i; PRINTER_INFO_2 *DataTable; PRINTQ_ENTRY *MIB_PrintQTableElement ; int First_of_this_block; time_t curr_time ; BOOL result; SNMPAPI nResult = SNMPAPI_NOERROR; time(&curr_time); // get the time // // // If cached, return piece of info. // // if((NULL != cache_table[C_PRNT_TABLE].bufptr) && (curr_time < (cache_table[C_PRNT_TABLE].acquisition_time + cache_expire[C_PRNT_TABLE] ) ) ) { // it has NOT expired! goto Exit ; // the global table is valid } // // remember to free the existing data // MIB_PrintQTableElement = MIB_PrintQTable.Table ; // iterate over the whole table for(i=0; iOid)); SafeFree(MIB_PrintQTableElement->svPrintQName.stream); MIB_PrintQTableElement ++ ; // increment table entry } SafeFree(MIB_PrintQTable.Table) ; // free the base Table MIB_PrintQTable.Table = NULL ; // just for safety MIB_PrintQTable.Len = 0 ; // just for safety // // // Do network call to gather information and put it in a nice array // // // call it with zero length buffer to get the size // result = EnumPrinters( PRINTER_ENUM_SHARED | PRINTER_ENUM_LOCAL, // what type to enum NULL, // local server 2, // level NULL, // where to put it 0, // max of above &bytesNeeded, // additional bytes req'd &entriesread ); // how many we got this time if (result) { // When there is no table entries from spooler *and* spooler is // running, we'll be here. SNMPDBG(( SNMP_LOG_TRACE, "SNMP: LMMIB2: EnumPrinters returns TRUE, bytesNeeded=0x%08lx\n", bytesNeeded )); goto Exit; // get out with 0 entries in the table } // Assert: result == FALSE dwLastError = GetLastError(); // save last error SNMPDBG(( SNMP_LOG_TRACE, "SNMP: LMMIB2: EnumPrinters returns FALSE, bytesNeeded=0x%08lx, dwLastError=0x%08lx\n", bytesNeeded, dwLastError )); if (ERROR_INSUFFICIENT_BUFFER != dwLastError) { // // EnumPrinters Failed and the last error is not // ERROR_INSUFFICIENT_BUFFER, we'll bail out with 0 entries in the // table. // For example, if spooler service was down, we will be here. // SNMPDBG(( SNMP_LOG_TRACE, "SNMP: LMMIB2: EnumPrinters failed, lasterror != ERROR_INSUFFICIENT_BUFFER, bytesNeeded=%d\n", bytesNeeded )); goto Exit; // get out with 0 entries in the table, so getnext will work } // Assert: dwLastError == ERROR_INSUFFICIENT_BUFFER bufptr = SnmpUtilMemAlloc(bytesNeeded); // SnmpUtilMemAlloc the buffer if(NULL==bufptr) { nResult = SNMPAPI_ERROR; goto Exit ; // can't allocate memory, error out } // then read the rest of it // call it again result = EnumPrinters( PRINTER_ENUM_SHARED | PRINTER_ENUM_LOCAL, // what type to enum NULL, // local server 2, // level bufptr, // where to put it bytesNeeded, // max of above &bytesNeeded, // additional bytes req'd &entriesread ); // how many we got this time if (!result) { // Signal error SafeFree( bufptr ); nResult = SNMPAPI_ERROR; goto Exit; } DataTable = (PRINTER_INFO_2 *) bufptr ; if(0 == MIB_PrintQTable.Len) { // 1st time, alloc the whole table // alloc the table space MIB_PrintQTable.Table = SnmpUtilMemAlloc(entriesread * sizeof(PRINTQ_ENTRY) ); // prefix bug 445181 if (MIB_PrintQTable.Table == NULL) { // free the table SafeFree( bufptr ) ; // Signal error nResult = SNMPAPI_ERROR; goto Exit; } } MIB_PrintQTableElement = MIB_PrintQTable.Table ; for(i=0; isvPrintQName.dynamic = TRUE; #ifdef UNICODE if (SnmpUtilUnicodeToUTF8( &MIB_PrintQTableElement->svPrintQName.stream, DataTable->pPrinterName, TRUE)) { MIB_PrintQTableElement->svPrintQName.stream = NULL; MIB_PrintQTableElement->svPrintQName.length = 0; } else { MIB_PrintQTableElement->svPrintQName.length = strlen (MIB_PrintQTableElement->svPrintQName.stream); } #else MIB_PrintQTableElement->svPrintQName.stream = SnmpUtilMemAlloc ( strlen( DataTable->pPrinterName ) + 1 ) ; MIB_PrintQTableElement->svPrintQName.length = strlen( DataTable->pPrinterName ) ; memcpy( MIB_PrintQTableElement->svPrintQName.stream, DataTable->pPrinterName, strlen( DataTable->pPrinterName ) ) ; #endif // number of connections MIB_PrintQTableElement->svPrintQNumJobs = DataTable->cJobs; MIB_PrintQTableElement ++ ; // and table entry DataTable ++ ; // advance pointer to next sess entry in buffer } // for each entry in the data table // free all of the printer enum data if(NULL!=bufptr) // free the table SnmpUtilMemFree( bufptr ) ; // iterate over the table populating the Oid field build_prnt_entry_oids(); // Sort the table information using MSC QuickSort routine qsort( &MIB_PrintQTable.Table[0], MIB_PrintQTable.Len, sizeof(PRINTQ_ENTRY), prnt_entry_cmp ); // // // Cache table // // if(0 != MIB_PrintQTable.Len) { cache_table[C_PRNT_TABLE].acquisition_time = curr_time ; cache_table[C_PRNT_TABLE].bufptr = bufptr ; } // // // Return piece of information requested in global table // // Exit: return nResult; } // MIB_prnt_get // // MIB_prnt_cmp // Routine for sorting the session table. // // Notes: // // Return Codes: // SNMPAPI_NOERROR // SNMPAPI_ERROR // // Error Codes: // None. // int __cdecl prnt_entry_cmp( IN const PRINTQ_ENTRY *A, IN const PRINTQ_ENTRY *B ) { // Compare the OID's return SnmpUtilOidCmp( (AsnObjectIdentifier *)&A->Oid, (AsnObjectIdentifier *)&B->Oid ); } // MIB_prnt_cmp // // None. // void build_prnt_entry_oids( ) { AsnOctetString OSA ; PRINTQ_ENTRY *PrintQEntry ; unsigned i; // start pointer at 1st guy in the table PrintQEntry = MIB_PrintQTable.Table ; // now iterate over the table, creating an oid for each entry for( i=0; isvPrintQName.stream ; OSA.length = PrintQEntry->svPrintQName.length ; OSA.dynamic = TRUE; // Make the entry's OID from string index MakeOidFromStr( &OSA, &PrintQEntry->Oid ); PrintQEntry++; // point to the next guy in the table } // for } // build_prnt_entry_oids //-------------------------------- END --------------------------------------