/*---------------------------------------------------------------------------- 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 "pbsmaster.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 PERF_COUNTERS * g_pCpsCounter = NULL; // Pointer to the shared object //---------------------------------------------------------------------------- // // 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 ) { OutputDebugString("OpenPerfMon - entering\n"); if ( g_bOpenOK ) { g_dwNumOpens ++; OutputDebugString("OpenPerfMon - already open\n"); return ERROR_SUCCESS; } // ------------------------------------- // Validate parameter (should be NULL) // ------------------------------------- if (lpDeviceName) { OutputDebugString("OpenPerfMon - param is not null, should be null"); return ERROR_INVALID_PARAMETER; } // ------------------------------------- // 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 ) { // // the phone book server DLL should create this Shared File. So we can assume // the server has not been loaded yet. Just return silently. // OutputDebugString("OpenPerfMon - OpenFileMapping returned NULL\n"); return ERROR_SUCCESS; } // ------------------------------------- // Map the shared-file into memory // ------------------------------------- g_pCpsCounter = (PERF_COUNTERS *)MapViewOfFileEx( g_hSharedFileMapping, // File mapping handle FILE_MAP_READ, // Read only access desired 0, // |_ File Offset 0, // | sizeof(PERF_COUNTERS), // no. of bytes to map NULL ); // Any address if ( NULL == g_pCpsCounter ) { OutputDebugString("OpenPerfMon - MapViewOfFileEx is null\n"); goto CleanUp; } // ------------------------------------------------ // Initialize the data-structure g_CpsMonDataDef // ------------------------------------------------ InitializeDataDef(); OutputDebugString("OpenPerfMon - past IntializeDataDef\n"); // ----------------------------------------------------------------- // Update static data structures g_CpsMonDataDef by adding base to // the offset value in the structure. // ----------------------------------------------------------------- if (!UpdateDataDefFromRegistry()) { goto CleanUp; } // ------------- // Success :) // ------------- g_bOpenOK = TRUE; g_dwNumOpens ++; OutputDebugString("OpenPerfMon - exit success\n"); return ERROR_SUCCESS; CleanUp : // ------------- // Failure :( // ------------- if ( NULL != g_hSharedFileMapping ) { CloseHandle( g_hSharedFileMapping ); g_hSharedFileMapping = NULL; } if ( NULL != g_pCpsCounter ) { g_pCpsCounter = NULL; } OutputDebugString("OpenPerfMon - exit failure\n"); 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; OutputDebugString("CollectPerfMon - entering\n"); // parameter validation: // lpwszValue can be NULL. // other params must be non null at least if (!lppData || !lpcbTotalBytes || !lpcObjectTypes) { return ERROR_INVALID_PARAMETER; } // ------------------------ // Check if Open went OK //------------------------- if ( !g_bOpenOK ) { // ----------------------------------------- // Unable to continue because open failed // ----------------------------------------- *lpcbTotalBytes = (DWORD) 0; *lpcObjectTypes = (DWORD) 0; OutputDebugString("CollectPerfMon - exit success actually open failed\n"); 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; OutputDebugString("CollectPerfMon - exit success query_foreign\n"); 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; OutputDebugString("CollectPerfMon - exit success not our objects\n"); 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; OutputDebugString("CollectPerfMon - ran out of space\n"); 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); CPSMON_COUNTERS CpsMonCounters = { // The PERF_COUNTER_BLOCK structure { { sizeof( CPSMON_COUNTERS )}, 0}, // The RAW counters g_pCpsCounter->dwTotalHits, g_pCpsCounter->dwNoUpgradeHits, g_pCpsCounter->dwDeltaUpgradeHits, g_pCpsCounter->dwFullUpgradeHits, g_pCpsCounter->dwErrors, // The RATE counters g_pCpsCounter->dwTotalHits, g_pCpsCounter->dwNoUpgradeHits, g_pCpsCounter->dwDeltaUpgradeHits, g_pCpsCounter->dwFullUpgradeHits, g_pCpsCounter->dwErrors, }; memmove( pCpsMonCounters, &CpsMonCounters, sizeof(CPSMON_COUNTERS) ); // ------------------------------- // Update arguements for return // ------------------------------- *lppData = (LPBYTE)(*lppData) + SpaceNeeded; *lpcObjectTypes = 1; *lpcbTotalBytes = SpaceNeeded; // -------------------- // Success at last :) // -------------------- OutputDebugString("CollectPerfMon - exit success\n"); return ERROR_SUCCESS; } //---------------------------------------------------------------------------- // // Function: ClosePerfMon // // Synopsis: This function closes the open handles to the shared file // // Arguments: None // // Returns: ERROR_SUCCESS // // History: 06/03/97 t-geetat Created // //---------------------------------------------------------------------------- DWORD ClosePerfMon() { g_dwNumOpens --; OutputDebugString("ClosePerfMon - entering\n"); if ( NULL != g_hSharedFileMapping ) { CloseHandle( g_hSharedFileMapping ); g_hSharedFileMapping = NULL; if ( g_dwNumOpens != 0 ) { OutputDebugString("ClosePerfMon - strange, g_dwNumOpens should be zero...\n"); } } OutputDebugString("ClosePerfMon - exit success\n"); return ERROR_SUCCESS; }