|
|
/*
- PERFAPP.CPP - * Purpose: * Implements the GLOBCNTR object used by Apps to initialize, update, * and deinitialize the PerfMon counters. * * * References: *
*/ #include <windows.h>
#include <winperf.h>
#include <winerror.h>
#include <perfutil.h>
#include <perfapp.h>
#include <tchar.h>
static const DWORD g_cMaxInst = 128;
// ---------------------------------------------------------------------------
// Prototypes
// ---------------------------------------------------------------------------
static HRESULT HrLogEvent(HANDLE hEventLog, WORD wType, DWORD msgid);
//-----------------------------------------------------------------------------
// GLOBCNTR methods
//-----------------------------------------------------------------------------
HRESULT GLOBCNTR::HrInit(GLOBAL_CNTR cCounters, LPWSTR szGlobalSMName, LPWSTR szSvcName) { HRESULT hr = S_OK; HANDLE hEventLog = NULL; BOOL fExist;
if (0 == cCounters || NULL == szGlobalSMName || NULL == szSvcName || 128 < cCounters ) //We should not have more than 128 counters
{ return E_INVALIDARG; }
if (m_fInit) { return E_FAIL; }
m_cCounters = cCounters;
hEventLog = RegisterEventSource(NULL, szSvcName);
// This must be called before any calls to HrOpenSharedMemory()
hr = HrInitializeSecurityAttribute(&m_sa);
if (FAILED(hr)) { goto ret; }
// Open shared memory to the process wide Perf Counters. Our member
// variable m_ppc will be mapped onto this address space and counters are
// simply indexes into this address space.
hr = HrOpenSharedMemory(szGlobalSMName, (sizeof(DWORD) * m_cCounters), &m_sa, &m_hsm, (LPVOID *) &m_rgdwPerfData, &fExist);
if (FAILED(hr)) { goto ret; }
ZeroMemory(m_rgdwPerfData, (sizeof(DWORD) * m_cCounters));
// Open for business!
m_fInit = TRUE;
ret: if (hEventLog) DeregisterEventSource(hEventLog);
return hr; }
/*
- Shutdown - * Purpose: * Cleanup and shutdown the GLOBCNTR object */
void GLOBCNTR::Shutdown(void) { if (m_fInit) { m_fInit = FALSE;
if (m_rgdwPerfData) { // Set all counters to zero at shutdown time
ZeroMemory(m_rgdwPerfData, (sizeof(DWORD) * m_cCounters));
UnmapViewOfFile(m_rgdwPerfData); m_rgdwPerfData = NULL; }
if (m_hsm) { CloseHandle(m_hsm); m_hsm = NULL; } } }
//-----------------------------------------------------------------------------
// INSTCNTR methods
//-----------------------------------------------------------------------------
/*
- Destructor - * Purpose: * Object cleanup & verify consistency */
INSTCNTR::~INSTCNTR() { if(m_sa.lpSecurityDescriptor) LocalFree(m_sa.lpSecurityDescriptor); }
/*
- HrInit - * Purpose: * Setup shared memory blocks * Prep Admin & Counter blocks for use */
HRESULT INSTCNTR::HrInit(INST_CNTR cCounters, LPWSTR szInstSMName, LPWSTR szInstMutexName, LPWSTR szSvcName) { HRESULT hr = S_OK; DWORD cbAdm = 0; DWORD cbCntr = 0; WCHAR szAdmName[MAX_PATH]; // Admin SM Name
WCHAR szCntrName[MAX_PATH]; // Counter SM Name
LPVOID pv; HANDLE hEventLog; BOOL fExist; BOOL fInMutex = FALSE;
// Validate args
if (0 == cCounters || !szInstSMName || !szInstMutexName || !szSvcName) return E_INVALIDARG;
// Save Number of Counters
m_cCounters = cCounters;
if (m_fInit) { return E_FAIL; }
// Open Application Event Log
hEventLog = RegisterEventSource(NULL, szSvcName);
// This must be called before any calls to HrOpenSharedMemory() and
// HrCreatePerfMutex() and must only be called once!!!
hr = HrInitializeSecurityAttribute(&m_sa);
if (FAILED(hr)) { goto ret; }
// Obtain Mutex. If call returns okay, we hold the mutex.
hr = HrCreatePerfMutex(&m_sa, szInstMutexName, &m_hmtx); if (FAILED(hr)) { goto ret; }
fInMutex = TRUE;
// Calc required memory sizes
cbAdm = sizeof(INSTCNTR_DATA) + (sizeof(INSTREC) * g_cMaxInst); cbCntr = ((sizeof(DWORD) * cCounters) * g_cMaxInst);
// Build names for the two shared memory blocks
if(wcslen(szInstSMName) >= (MAX_PATH - 6)) // Enough space to wsprintf.
{ hr=E_FAIL; goto ret; } wsprintf(szAdmName, L"%s_ADM", szInstSMName); wsprintf(szCntrName,L"%s_CNTR", szInstSMName);
// Open Admin Shared Memory Block
hr = HrOpenSharedMemory(szAdmName, cbAdm, &m_sa, &m_hsmAdm, (LPVOID *) &pv, &fExist); if (FAILED(hr)) { goto ret; }
// Fixup Pointers
m_picd = (INSTCNTR_DATA *) pv; m_rgInstRec = (INSTREC *) ((char *) pv + sizeof(INSTCNTR_DATA));
if (!fExist) { ZeroMemory(pv, cbAdm); m_picd->cMaxInstRec = g_cMaxInst; m_picd->cInstRecInUse = 0; }
// Open Counters Shared Memory Block
hr = HrOpenSharedMemory(szCntrName, cbCntr, &m_sa, &m_hsmCntr, (LPVOID *) &m_rgdwCntr, &fExist);
if (FAILED(hr)) { goto ret; }
if ( !fExist) { ZeroMemory(m_rgdwCntr, cbCntr); }
// Open for business!
m_fInit = TRUE;
ret:
if (hEventLog) DeregisterEventSource(hEventLog);
if (m_hmtx && fInMutex) ReleaseMutex(m_hmtx);
return hr; }
/*
- Shutdown - * Purpose: * Cleanup and shutdown the INSTCNTR object */
void INSTCNTR::Shutdown(BOOL fWipeOut) { if (m_fInit) { m_fInit = FALSE;
if (m_rgdwCntr) { // Zero out this shared memory block too. All counters should
// start at zero.
if ( fWipeOut ) { ZeroMemory(m_rgdwCntr, (sizeof(DWORD) * m_cCounters) * g_cMaxInst); } UnmapViewOfFile(m_rgdwCntr); m_rgdwCntr = NULL; }
// NOTE: m_picd points at the head of the
// Admin shared memory block. Do not UnmapViewOfFile on
// the m_rgInstRec pointer!
if (m_picd) { // Zero out the shared memory block
if ( fWipeOut ) { ZeroMemory(m_picd, sizeof(INSTCNTR_DATA) + (sizeof(INSTREC) * g_cMaxInst)); m_picd->cMaxInstRec = g_cMaxInst; m_picd->cInstRecInUse = 0; } UnmapViewOfFile(m_picd); m_picd = NULL; m_rgInstRec = NULL; }
if (m_hsmAdm) { CloseHandle(m_hsmAdm); m_hsmAdm = NULL; }
if (m_hsmCntr) {
CloseHandle(m_hsmCntr); m_hsmCntr = NULL; }
if (m_hmtx) { CloseHandle(m_hmtx); m_hmtx = NULL; } }
}
/*
- HrCreateOrGetInstance - * Purpose: * Return a token corresponding to an Instance Counter Block * Returns: * S_OK ID Found; picid contains a valid INSTCNTR_ID * E_FAIL Object not initialized *OR* ID not found * E_INVALIDARG Bad parameter/NULL pointer */
HRESULT INSTCNTR::HrCreateOrGetInstance(LPCWSTR wszInstName, INSTCNTR_ID *picid) { HRESULT hr = S_OK;
if (!m_fInit) return E_FAIL;
// Validate args
if (!picid || !wszInstName) return E_INVALIDARG;
*picid = INVALID_INST_ID;
// Obtain exclusive access to SM blocks
DWORD dwWait = WaitForSingleObject(m_hmtx, INFINITE); if (WAIT_OBJECT_0 != dwWait) { // No simple way to translate the return into an HRESULT
return E_FAIL; }
// We have the mutex; we must release before leaving
// Linear probe through list looking for a matching or open slot
for (unsigned int i = 0; i < m_picd->cMaxInstRec; i++) { if ( m_rgInstRec[i].fInUse && (0 == wcscmp(m_rgInstRec[i].szInstName, wszInstName)) ) { // Found first instance with matching name.
*picid = (INSTCNTR_ID) i; break; } else if (!m_rgInstRec[i].fInUse && (INVALID_INST_ID == *picid)) { // Found the first free slot -- remember its number
*picid = (INSTCNTR_ID) i; } }
if (INVALID_INST_ID == *picid) { // No matching or free slots found
hr = E_FAIL; goto Cleanup; } else if (!m_rgInstRec[*picid].fInUse) { // Found no matching slot, but found a free slot -- mark as
// in use and set instance name
wcsncpy(m_rgInstRec[*picid].szInstName, wszInstName, min((wcslen(wszInstName) + 1),MAX_PATH)); m_rgInstRec[*picid].fInUse = TRUE; m_picd->cInstRecInUse++;
// Zero out corresponding counter block
ZeroMemory(&m_rgdwCntr[(m_cCounters * (*picid))], (sizeof(DWORD) * m_cCounters)); }
Cleanup: ReleaseMutex(m_hmtx);
return hr; }
/*
- HrDestroyInstance - * Purpose: * Release Instance Counter Block associated with the token icid. */
HRESULT INSTCNTR::HrDestroyInstance(INSTCNTR_ID icid) { HRESULT hr = S_OK;
if (!m_fInit) return E_FAIL;
// Get exclusive access to SM blocks
DWORD dwWait = WaitForSingleObject(m_hmtx, INFINITE); if (WAIT_OBJECT_0 != dwWait) { // No simple way to translate the return into an HRESULT
return E_FAIL; }
if (m_rgInstRec[icid].fInUse) { // Mark the block as Not In Use
m_rgInstRec[icid].fInUse = FALSE;
// Zero out corresponding counter block
ZeroMemory(&m_rgdwCntr[(m_cCounters * (icid))], (sizeof(DWORD) * m_cCounters));
//Assert(m_picd->cInstRecInUse != 0);
m_picd->cInstRecInUse--; } else { hr = E_FAIL; }
ReleaseMutex(m_hmtx);
return hr; }
/*
- HrLogEvent - * Purpose: * Wrap up the call to ReportEvent to make things look nicer. */ HRESULT HrLogEvent(HANDLE hEventLog, WORD wType, DWORD msgid) { if (hEventLog) return ReportEvent(hEventLog, wType, (WORD)0,//facPerfMonDll,
msgid, NULL, 0, 0, NULL, NULL);
else return E_FAIL; }
|