|
|
/*++
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<xxxxx.h> ----
#ifdef WIN32
#include <windows.h>
#include <winspool.h>
#endif
#include <tchar.h>
#include <string.h>
#include <search.h>
#include <stdlib.h>
#include <time.h>
//--------------------------- 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; i<MIB_PrintQTable.Len ;i++) { // free any alloc'ed elements of the structure
SnmpUtilOidFree(&(MIB_PrintQTableElement->Oid)); 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; i<entriesread; i++) { // once for each entry in the buffer
// increment the entry number
MIB_PrintQTable.Len ++; // Stuff the data into each item in the table
// client name
MIB_PrintQTableElement->svPrintQName.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; i<MIB_PrintQTable.Len ; i++) { // for each entry in the session table
OSA.stream = PrintQEntry->svPrintQName.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 --------------------------------------
|