|
|
/*++
Copyright (c) 1996 Microsoft Corporation All rights reserved.
Module Name:
localspl.cxx
Abstract:
Localspl specific support routines for performance.
Author:
Albert Ting (AlbertT) 19-Dec-1996
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
//
// Define INDEX_FROM_PERFKEY if you want to retrieve the counter/help
// offsets from the registry instead of hardcoded values in ntprfctr.h.
//
#include "perf.hxx"
#include "lspldata.hxx"
#include "splapip.h"
#include "winsprlp.h"
#ifndef INDEX_FROM_PERFKEY
#include "ntprfctr.h"
#endif
/********************************************************************
Globals
********************************************************************/
LPCTSTR gszAppName = TEXT( "SpoolerCtrs" );
#ifdef INDEX_FROM_PERFKEY
LPCTSTR gszLocalsplPerformanceKey = TEXT( "SYSTEM\\CurrentControlSet\\Services\\spooler\\Performance" ); #endif
BOOL gbInitialized = FALSE; LPCWSTR gszTotal = L"_Total";
UINT gcbBufferHint = 0x800; const UINT kBufferHintPad = 0x200;
DWORD Pfp_dwBuildPrinterInstanceFromInfo( PPRINTER_INFO_STRESS pInfo, PBYTE* ppData, PDWORD pcbDataLeft, PLSPL_COUNTER_DATA *pplcd OPTIONAL );
DWORD Pfp_dwBuildPrinterInstanceFromLCD( LPCWSTR pszName, PLSPL_COUNTER_DATA plcdSource, PBYTE* ppData, PDWORD pcbDataLeft );
/********************************************************************
Required support routines
********************************************************************/
DWORD Pf_dwClientOpen( LPCWSTR pszDeviceNames, PPERF_DATA_DEFINITION *pppdd )
/*++
Routine Description:
Localspl specific intialization of the client data.
Arguments:
pszDeviceNames - Passed in from performance apis.
Return Value:
Status code.
--*/
{ DWORD Status = ERROR_SUCCESS; *pppdd = reinterpret_cast<PPERF_DATA_DEFINITION>( &LsplDataDefinition );
//
// If not initialized before,
//
if( !gbInitialized ) { //
// Fix up the indicies in our ObjectType and CounterDefinitions.
//
#ifdef INDEX_FROM_PERFKEY
Status = Pf_dwFixIndiciesFromPerfKey( gszLocalsplPerformanceKey, *pppdd ); #else
Pf_vFixIndiciesFromIndex( LSPL_FIRST_COUNTER_INDEX, LSPL_FIRST_HELP_INDEX, *pppdd ); Status = ERROR_SUCCESS; #endif
if( Status == ERROR_SUCCESS ) { gbInitialized = TRUE; } }
return Status; }
DWORD Pf_dwClientCollect( PBYTE *ppData, PDWORD pcbDataLeft, PDWORD pcNumInstances )
/*++
Routine Description:
Localspl specific collection of data.
Arguments:
Return Value:
Status code.
--*/
{ PPRINTER_INFO_STRESS pInfoBase; DWORD cbNeeded; DWORD cReturned; DWORD Error = ERROR_SUCCESS; BOOL bStatus; PBYTE pData = *ppData; DWORD cbDataLeft = *pcbDataLeft;
pInfoBase = static_cast<PPRINTER_INFO_STRESS>( LocalAlloc( LMEM_FIXED, gcbBufferHint ));
if( !pInfoBase ) { Error = GetLastError(); goto Cleanup; }
//
// Read the data via EnumPrinters(). We enumerate all the local printers and
// any cluster printers hosted by the local machine.
//
bStatus = EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME | PRINTER_ENUM_CLUSTER, NULL, STRESSINFOLEVEL, reinterpret_cast<PBYTE>( pInfoBase ), gcbBufferHint, &cbNeeded, &cReturned );
if( !bStatus && GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { //
// Reallocate the buffer and update the hint.
//
gcbBufferHint = cbNeeded + kBufferHintPad; LocalFree( static_cast<HLOCAL>( pInfoBase ));
pInfoBase = reinterpret_cast<PPRINTER_INFO_STRESS>( LocalAlloc( LMEM_FIXED, gcbBufferHint ));
if( !pInfoBase ) { Error = GetLastError(); goto Cleanup; }
bStatus = EnumPrinters( PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME | PRINTER_ENUM_CLUSTER, NULL, STRESSINFOLEVEL, reinterpret_cast<PBYTE>( pInfoBase ), gcbBufferHint, &cbNeeded, &cReturned ); }
if( !bStatus ) { Error = GetLastError(); goto Cleanup; }
//
// Update the hint.
//
gcbBufferHint = cbNeeded + kBufferHintPad;
UINT i; PPRINTER_INFO_STRESS pInfo; LSPL_COUNTER_DATA lcdTotal; PLSPL_COUNTER_DATA plcd;
ZeroMemory( &lcdTotal, sizeof( lcdTotal ));
for( i=0, pInfo = pInfoBase; i< cReturned; ++i, ++pInfo ) { Error = Pfp_dwBuildPrinterInstanceFromInfo( pInfo, &pData, &cbDataLeft, &plcd );
if( Error != ERROR_SUCCESS ){ goto Cleanup; }
//
// Add up the total.
//
lcdTotal.liTotalJobs.QuadPart += plcd->liTotalJobs.QuadPart; lcdTotal.liTotalBytes.QuadPart += plcd->liTotalBytes.QuadPart; lcdTotal.liTotalPagesPrinted.QuadPart+= plcd->liTotalPagesPrinted.QuadPart; lcdTotal.dwJobs += plcd->dwJobs; lcdTotal.dwMaxRef += plcd->dwMaxRef; lcdTotal.dwSpooling += plcd->dwSpooling; lcdTotal.dwMaxSpooling += plcd->dwMaxSpooling; lcdTotal.dwRef += plcd->dwRef; lcdTotal.dwErrorOutOfPaper += plcd->dwErrorOutOfPaper; lcdTotal.dwErrorNotReady += plcd->dwErrorNotReady; lcdTotal.dwJobError += plcd->dwJobError;
//
// Only include EnumerateNetworkPrinters and dwAddNetPrinters
// once,d since they are really globals (per-server not per-printer).
//
if( i == 0 ) { lcdTotal.dwEnumerateNetworkPrinters = plcd->dwEnumerateNetworkPrinters; lcdTotal.dwAddNetPrinters = plcd->dwAddNetPrinters; } }
//
// Add the last one.
//
Error = Pfp_dwBuildPrinterInstanceFromLCD( gszTotal, &lcdTotal, &pData, &cbDataLeft );
Cleanup:
if( pInfoBase ) { LocalFree( static_cast<HLOCAL>( pInfoBase )); }
if( Error == ERROR_SUCCESS ) { //
// Update the pointers. We will return cReturned+1 instances since
// we built an artifical "_Total" instance.
//
*ppData = pData; *pcbDataLeft = cbDataLeft; *pcNumInstances = cReturned + 1;
return ERROR_SUCCESS; }
return Error; }
VOID Pf_vClientClose( VOID )
/*++
Routine Description:
Localspl specific closure of data.
Arguments:
Return Value:
--*/
{ //
// Nothing to do since it is name based.
//
}
/********************************************************************
Helper functions.
********************************************************************/
DWORD Pfp_dwBuildPrinterInstanceFromInfo( IN PPRINTER_INFO_STRESS pInfo, IN OUT PBYTE* ppData, IN OUT PDWORD pcbDataLeft, OUT PLSPL_COUNTER_DATA *pplcd OPTIONAL )
/*++
Routine Description:
Add a single pInfo structure to the performance data block.
Arguments:
pInfo - Input data.
ppData - On entry, pointer to buffer. On exit, holds the next available space in buffer. If an error is returned, this value is random.
pcbDataLeft - On entry, size of buffer. On exit, remaining size of buffer. If an error is returned, this value is random.
pplcd - Optional; on success returns pointer to lcd.
Return Value:
ERROR_SUCCESS - Success, else failure code.
--*/
{ DWORD Error;
//
// Add the instance definitions
//
Error = Pf_dwBuildInstance( 0, 0, static_cast<DWORD>( PERF_NO_UNIQUE_ID ), pInfo->pPrinterName, ppData, pcbDataLeft );
if( Error != ERROR_SUCCESS ) { goto Fail; }
//
// Check if there's enough space for our counter data.
//
if( *pcbDataLeft < sizeof( LSPL_COUNTER_DATA )) { Error = ERROR_MORE_DATA; goto Fail; }
//
// Convert ppData to a LSPL_COUNTER_DATA and copy everything over.
//
PLSPL_COUNTER_DATA plcd;
plcd = reinterpret_cast<PLSPL_COUNTER_DATA>( *ppData ); plcd->CounterBlock.ByteLength = sizeof( LSPL_COUNTER_DATA );
plcd->liTotalJobs.HighPart = 0; plcd->liTotalBytes.HighPart = pInfo->dwHighPartTotalBytes; plcd->liTotalPagesPrinted.HighPart = 0;
plcd->liTotalJobs.LowPart = pInfo->cTotalJobs; plcd->liTotalBytes.LowPart = pInfo->cTotalBytes; plcd->liTotalPagesPrinted.LowPart = pInfo->cTotalPagesPrinted; plcd->dwJobs = pInfo->cJobs; plcd->dwMaxRef = pInfo->MaxcRef; plcd->dwSpooling = pInfo->cSpooling; plcd->dwMaxSpooling = pInfo->cMaxSpooling; plcd->dwRef = pInfo->cRef; plcd->dwErrorOutOfPaper = pInfo->cErrorOutOfPaper; plcd->dwErrorNotReady = pInfo->cErrorNotReady; plcd->dwJobError = pInfo->cJobError; plcd->dwEnumerateNetworkPrinters = pInfo->cEnumerateNetworkPrinters; plcd->dwAddNetPrinters = pInfo->cAddNetPrinters;
//
// Update the counters.
//
*ppData += sizeof( LSPL_COUNTER_DATA ); *pcbDataLeft -= sizeof( LSPL_COUNTER_DATA );
if( pplcd ) { *pplcd = plcd; }
Fail:
return Error; }
DWORD Pfp_dwBuildPrinterInstanceFromLCD( IN LPCWSTR pszName, IN PLSPL_COUNTER_DATA plcdSource, IN OUT PBYTE* ppData, IN OUT PDWORD pcbDataLeft )
/*++
Routine Description:
Add a single LCD structure to the performance data block.
Arguments:
pszName - Name of the block.
plcd - Pointer to the LCD block to copy.
ppData - On entry, pointer to buffer. On exit, holds the next available space in buffer. If an error is returned, this value is random.
pcbDataLeft - On entry, size of buffer. On exit, remaining size of buffer. If an error is returned, this value is random.
Return Value:
ERROR_SUCCESS - Success, else failure code.
--*/
{ DWORD Error;
//
// Add the instance definitions
//
Error = Pf_dwBuildInstance( 0, 0, static_cast<DWORD>( PERF_NO_UNIQUE_ID ), pszName, ppData, pcbDataLeft );
if( Error != ERROR_SUCCESS ) { goto Fail; }
//
// Check if there's enough space for our counter data.
//
if( *pcbDataLeft < sizeof( LSPL_COUNTER_DATA )) { Error = ERROR_MORE_DATA; goto Fail; }
//
// Convert ppData to a LSPL_COUNTER_DATA and copy everything over.
//
PLSPL_COUNTER_DATA plcd;
plcd = reinterpret_cast<PLSPL_COUNTER_DATA>( *ppData );
CopyMemory( plcd, plcdSource, sizeof( LSPL_COUNTER_DATA )); plcd->CounterBlock.ByteLength = sizeof( LSPL_COUNTER_DATA );
//
// Update the counters.
//
*ppData += sizeof( LSPL_COUNTER_DATA ); *pcbDataLeft -= sizeof( LSPL_COUNTER_DATA );
Fail:
return Error; }
|