409 lines
10 KiB
C++
409 lines
10 KiB
C++
|
/*----------------------------------------------------------------------------
|
||
|
Cpsmon.cpp
|
||
|
|
||
|
Implementation of pbsmon.dll -- the perfmon DLL for counting the number of
|
||
|
times the phone book server was accessed
|
||
|
since it started
|
||
|
|
||
|
Copyright (c) 1997-1998 Microsoft Corporation
|
||
|
All rights reserved.
|
||
|
|
||
|
Authors:
|
||
|
t-geetat Geeta Tarachandani
|
||
|
|
||
|
History:
|
||
|
6/2/97 t-geetat Created
|
||
|
--------------------------------------------------------------------------*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#include "cpsmon.h"
|
||
|
#include "CpsSym.h"
|
||
|
#include "LoadData.h"
|
||
|
|
||
|
BOOL g_bOpenOK =FALSE; // TRUE if Open went OK, FALSE otherwise
|
||
|
DWORD g_dwNumOpens =0; // Active "opens" reference counts
|
||
|
|
||
|
CPSMON_DATA_DEFINITION g_CpsMonDataDef;
|
||
|
HANDLE g_hSharedFileMapping=NULL; // Handle to shared file map
|
||
|
CCpsCounter *g_pCpsCounter=NULL; // Pointer to the shared object
|
||
|
HANDLE g_hSemaphore=NULL; // Handle to semaphore for shared file
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetSemaphore
|
||
|
//
|
||
|
// Synopsis: This function gets hold of the semaphore for accessing shared file.
|
||
|
//
|
||
|
// Arguments: None.
|
||
|
//
|
||
|
// Returns: TRUE if succeeds, FALSE if fails.
|
||
|
//
|
||
|
// History: 06/02/97 t-geetat Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL GetSemaphore()
|
||
|
{
|
||
|
DWORD WaitRetValue = WaitForSingleObject( g_hSemaphore, INFINITE );
|
||
|
|
||
|
switch( WaitRetValue )
|
||
|
{
|
||
|
|
||
|
case WAIT_OBJECT_0 : return TRUE ;
|
||
|
case WAIT_ABANDONED : return TRUE;
|
||
|
default : return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OpenPerfMon
|
||
|
//
|
||
|
// Synopsis: This function opens & maps the shared memory used to pass
|
||
|
// counter-values between the phone-book server & perfmon.dll
|
||
|
// It also initializes the data-structures used to pass data back
|
||
|
// to the registry
|
||
|
//
|
||
|
// Arguments: lpDeviceName -- Pointer to object ID of the device to be opened
|
||
|
// --> Should be NULL.
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS if succeeds, GetLastError() if fails.
|
||
|
//
|
||
|
// History: 06/02/97 t-geetat Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD OpenPerfMon( LPWSTR lpDeviceName )
|
||
|
{
|
||
|
|
||
|
if ( g_bOpenOK )
|
||
|
{
|
||
|
g_dwNumOpens ++;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------
|
||
|
* Open the semaphore
|
||
|
*-------------------*/
|
||
|
if(g_hSemaphore == NULL)
|
||
|
{
|
||
|
g_hSemaphore = OpenSemaphore(
|
||
|
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, // Desired for sync
|
||
|
FALSE, // Inheritance not desired
|
||
|
SEMAPHORE_OBJECT ); // Semaphore name -- from "cpsmon.h"
|
||
|
}
|
||
|
if ( NULL == g_hSemaphore )
|
||
|
{
|
||
|
//
|
||
|
// the phone book server DLL should create this Semaphore. So we can assume
|
||
|
// the server has not been loaded yet. Just return silently.
|
||
|
//
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------
|
||
|
* Open shared memory ( if exists )
|
||
|
*------------------------------------*/
|
||
|
g_hSharedFileMapping = OpenFileMapping(
|
||
|
FILE_MAP_READ, // Read only access desired
|
||
|
FALSE, // Don't want to inherit
|
||
|
SHARED_OBJECT); // from "cpsmon.h"
|
||
|
|
||
|
if ( NULL == g_hSharedFileMapping )
|
||
|
{
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------
|
||
|
* Map the shared-file into memory
|
||
|
*---------------------------------*/
|
||
|
g_pCpsCounter = (CCpsCounter *)MapViewOfFileEx(
|
||
|
g_hSharedFileMapping, // File mapping handle
|
||
|
FILE_MAP_READ, // Read only access desired
|
||
|
0, // |_ File Offset
|
||
|
0, // |
|
||
|
sizeof( CCpsCounter ), // no. of bytes to map
|
||
|
NULL ); // Any address
|
||
|
|
||
|
if ( NULL == g_pCpsCounter )
|
||
|
{
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------------------------
|
||
|
* Initialize the data-structure g_CpsMonDataDef
|
||
|
*-----------------------------------------------*/
|
||
|
InitializeDataDef();
|
||
|
|
||
|
|
||
|
/*-----------------------------------------------------------------
|
||
|
* Update static data strucutures g_CpsMonDataDef by adding base to
|
||
|
* the offset value in the structure.
|
||
|
*-----------------------------------------------------------------*/
|
||
|
if (!UpdateDataDefFromRegistry())
|
||
|
{
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------
|
||
|
* Success :)
|
||
|
*-------------*/
|
||
|
g_bOpenOK = TRUE;
|
||
|
g_dwNumOpens ++;
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
|
||
|
CleanUp :
|
||
|
/*-------------
|
||
|
* Failure :(
|
||
|
*-------------*/
|
||
|
|
||
|
if ( NULL != g_hSemaphore )
|
||
|
{
|
||
|
CloseHandle( g_hSemaphore );
|
||
|
g_hSemaphore = NULL;
|
||
|
}
|
||
|
|
||
|
if ( NULL != g_hSharedFileMapping )
|
||
|
{
|
||
|
CloseHandle( g_hSharedFileMapping );
|
||
|
g_hSharedFileMapping = NULL;
|
||
|
}
|
||
|
|
||
|
if ( NULL != g_pCpsCounter )
|
||
|
{
|
||
|
g_pCpsCounter = NULL;
|
||
|
}
|
||
|
|
||
|
return GetLastError();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CollectPerfMon
|
||
|
//
|
||
|
// Synopsis: This function opens & maps the shared memory used to pass
|
||
|
// counter-values between the phone-book server & perfmon.dll
|
||
|
// It also initializes the data-structures used to pass data back
|
||
|
// to the registry
|
||
|
//
|
||
|
// Arguments:
|
||
|
// lpwszValue Pointer to wide character string passed by registry
|
||
|
//
|
||
|
// lppData IN : Pointer to address of buffer to receive completed
|
||
|
// PerfDataBlock and subordinate structures This routine
|
||
|
// appends its data to the buffer starting at *lppData.
|
||
|
// OUT : Points to the first byte after the data structure added
|
||
|
// by this routine.
|
||
|
//
|
||
|
// lpcbTotalBytes IN : Address of DWORD that tells the size in bytes
|
||
|
// of the buffer *lppData.
|
||
|
// OUT : The number of bytes added by this routine is
|
||
|
// written to the DWORD pointed to by this arg.
|
||
|
//
|
||
|
// lpcObjectTypes IN : Address of DWORD to receive the number of
|
||
|
// objects added by this routine
|
||
|
// OUT : The number of objs. added by this routine.
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS if succeeds, GetLastError() if fails.
|
||
|
//
|
||
|
// History: 06/02/97 t-geetat Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD CollectPerfMon(
|
||
|
IN LPWSTR lpwszValue,
|
||
|
IN OUT LPVOID *lppData,
|
||
|
IN OUT LPDWORD lpcbTotalBytes,
|
||
|
IN OUT LPDWORD lpcObjectTypes
|
||
|
)
|
||
|
{
|
||
|
DWORD dwQueryType;
|
||
|
CPSMON_DATA_DEFINITION *pCpsMonDataDef;
|
||
|
CPSMON_COUNTERS *pCpsMonCounters;
|
||
|
DWORD SpaceNeeded = 0;
|
||
|
|
||
|
//See if the semaphore was created after the intial OpenPerfmon.
|
||
|
|
||
|
if(g_hSemaphore == NULL)
|
||
|
{
|
||
|
g_hSemaphore = OpenSemaphore(
|
||
|
SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, // Desired for sync
|
||
|
FALSE, // Inheritance not desired
|
||
|
SEMAPHORE_OBJECT ); // Semaphore name -- from "cpsmon.h"
|
||
|
if(g_hSemaphore)
|
||
|
{
|
||
|
OpenPerfMon(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( NULL == g_hSemaphore )
|
||
|
{
|
||
|
//
|
||
|
// the phone book server DLL should create this Semaphore. So we can assume
|
||
|
// the server has not been loaded yet. Just return silently.
|
||
|
//
|
||
|
*lpcbTotalBytes = (DWORD) 0;
|
||
|
*lpcObjectTypes = (DWORD) 0;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*------------------------
|
||
|
* Check if Open went OK
|
||
|
*------------------------*/
|
||
|
if ( !g_bOpenOK )
|
||
|
{
|
||
|
/*-----------------------------------------
|
||
|
* Unable to continue because open failed
|
||
|
*-----------------------------------------*/
|
||
|
*lpcbTotalBytes = (DWORD) 0;
|
||
|
*lpcObjectTypes = (DWORD) 0;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------------
|
||
|
* Retrieve the TYPE of the request
|
||
|
*------------------------------------*/
|
||
|
dwQueryType = GetQueryType( lpwszValue );
|
||
|
|
||
|
if ( QUERY_FOREIGN == dwQueryType )
|
||
|
{
|
||
|
/*-------------------------------------
|
||
|
* Unable to service non-NT requests
|
||
|
*------------------------------------*/
|
||
|
*lpcbTotalBytes = (DWORD) 0;
|
||
|
*lpcObjectTypes = (DWORD) 0;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( QUERY_ITEMS == dwQueryType )
|
||
|
{
|
||
|
/*-----------------------------------------------
|
||
|
* The registry is asking for specifis objects.
|
||
|
* Check if we're one of the chosen
|
||
|
*-----------------------------------------------*/
|
||
|
if ( !IsNumberInUnicodeList(
|
||
|
g_CpsMonDataDef.m_CpsMonObjectType.ObjectNameTitleIndex,
|
||
|
lpwszValue ) )
|
||
|
{
|
||
|
*lpcbTotalBytes = (DWORD) 0;
|
||
|
*lpcObjectTypes = (DWORD) 0;
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------
|
||
|
* We need space for header and the counters
|
||
|
* Let's see if there's enough space
|
||
|
*-------------------------------------------*/
|
||
|
SpaceNeeded = sizeof(CPSMON_DATA_DEFINITION) + sizeof( CPSMON_COUNTERS );
|
||
|
|
||
|
if ( SpaceNeeded > *lpcbTotalBytes )
|
||
|
{
|
||
|
*lpcbTotalBytes = (DWORD) 0;
|
||
|
*lpcObjectTypes = (DWORD) 0;
|
||
|
return ERROR_MORE_DATA;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------
|
||
|
* Copy the initialized Object Type & the Counter Definitions
|
||
|
* into the caller's data buffer
|
||
|
*-------------------------------------------------------------*/
|
||
|
pCpsMonDataDef = (CPSMON_DATA_DEFINITION *) *lppData;
|
||
|
|
||
|
memmove( pCpsMonDataDef, &g_CpsMonDataDef, sizeof(CPSMON_DATA_DEFINITION) );
|
||
|
|
||
|
|
||
|
/*--------------------------------
|
||
|
* Now try to retrieve the data
|
||
|
*-------------------------------*/
|
||
|
pCpsMonCounters = (CPSMON_COUNTERS *)(pCpsMonDataDef + 1);
|
||
|
|
||
|
if ( GetSemaphore() )
|
||
|
{
|
||
|
|
||
|
CPSMON_COUNTERS CpsMonCounters = {
|
||
|
// The PERF_COUNTER_BLOCK structure
|
||
|
{ { sizeof( CPSMON_COUNTERS )}, 0},
|
||
|
// The RAW counters
|
||
|
g_pCpsCounter->m_dwTotalHits,
|
||
|
g_pCpsCounter->m_dwNoUpgradeHits,
|
||
|
g_pCpsCounter->m_dwDeltaUpgradeHits,
|
||
|
g_pCpsCounter->m_dwFullUpgradeHits,
|
||
|
g_pCpsCounter->m_dwErrors,
|
||
|
// The RATE counters
|
||
|
g_pCpsCounter->m_dwTotalHits,
|
||
|
g_pCpsCounter->m_dwNoUpgradeHits,
|
||
|
g_pCpsCounter->m_dwDeltaUpgradeHits,
|
||
|
g_pCpsCounter->m_dwFullUpgradeHits,
|
||
|
g_pCpsCounter->m_dwErrors,
|
||
|
|
||
|
};
|
||
|
memmove( pCpsMonCounters, &CpsMonCounters, sizeof(CPSMON_COUNTERS) );
|
||
|
}
|
||
|
|
||
|
ReleaseSemaphore( g_hSemaphore, 1, NULL );
|
||
|
|
||
|
|
||
|
|
||
|
/*-------------------------------
|
||
|
* Update arguements for return
|
||
|
*------------------------------*/
|
||
|
*lppData = (LPBYTE)(*lppData) + SpaceNeeded;
|
||
|
*lpcObjectTypes = 1;
|
||
|
*lpcbTotalBytes = SpaceNeeded;
|
||
|
|
||
|
|
||
|
/*--------------------
|
||
|
* Success at last :)
|
||
|
*-------------------*/
|
||
|
return ERROR_SUCCESS;
|
||
|
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ClosePerfMon
|
||
|
//
|
||
|
// Synopsis: This function closes the open handles to the shared file and semaphore
|
||
|
//
|
||
|
// Arguments: None
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS
|
||
|
//
|
||
|
// History: 06/03/97 t-geetat Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD ClosePerfMon()
|
||
|
{
|
||
|
g_dwNumOpens --;
|
||
|
|
||
|
if ( NULL != g_hSharedFileMapping )
|
||
|
{
|
||
|
CloseHandle( g_hSharedFileMapping );
|
||
|
}
|
||
|
|
||
|
if ( NULL != g_hSemaphore )
|
||
|
{
|
||
|
CloseHandle(g_hSemaphore);
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|