Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

488 lines
11 KiB

/*
- 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;
}