PERFMEM.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:
Windows编程
开发平台:
Visual C++
- /*++
- Copyright (c) 1995-1997 Microsoft Corporation
- Module Name:
- perfmem.c
- Abstract:
- This file implements the Extensible Objects for the application
- memory object
- Created:
- Bob Watson 24 august 1995
- Revision History
- None
- --*/
- //
- // Include Files
- //
- #include <windows.h>
- #include <string.h>
- #include <winperf.h>
- #include "..incappmemi.h" // definitions shared with the app. dll
- #include "memctrs.h" // error message definition
- #include "perfmsg.h" // message utilities
- #include "perfutil.h" // perf data utilities
- #include "datamem.h" // perf data structure definitions
- //
- // References to constants which initialize the Object type definitions
- //
- extern APPMEM_DATA_DEFINITION AppMemDataDefinition;
- static DWORD dwOpenCount = 0; // count of "Open" threads
- static BOOL bInitOK = FALSE; // true = DLL initialized OK
- //
- // App Mem counter data structures
- //
- static HANDLE hAppMemSharedMemory = NULL; // Handle of counter Shared Memory
- static HANDLE hAppMemMutex = NULL; // sync mutex for memory
- static PAPPMEM_DATA_HEADER pDataHeader = NULL; // pointer to header of shared mem
- //
- // Function Prototypes
- //
- // these are used to insure that the data collection functions
- // accessed by Perflib will have the correct calling format.
- //
- PM_OPEN_PROC OpenAppMemPerformanceData;
- PM_COLLECT_PROC CollectAppMemPerformanceData;
- PM_CLOSE_PROC CloseAppMemPerformanceData;
- DWORD APIENTRY
- OpenAppMemPerformanceData(
- LPWSTR lpDeviceNames
- )
- /*++
- Routine Description:
- This routine will open and map the memory used by the App Mem DLL to
- pass performance data in. This routine also initializes the data
- structures used to pass data back to the registry
- Arguments:
- Pointer to object ID of each device to be opened
- Return Value:
- None.
- --*/
- {
- LONG status;
- HKEY hKeyDriverPerf;
- BOOL bFreeMutex;
- DWORD size;
- DWORD type;
- DWORD dwFirstCounter;
- DWORD dwFirstHelp;
- DWORD dwInstance;
- PAPPMEM_INSTANCE pLastItem;
- PAPPMEM_INSTANCE pAppData;
- APPMEM_COUNTERS ac;
- //
- // Since WINLOGON is multi-threaded and will call this routine in
- // order to service remote performance queries, this library
- // must keep track of how many times it has been opened (i.e.
- // how many threads have accessed it). the registry routines will
- // limit access to the initialization routine to only one thread
- // at a time so synchronization (i.e. reentrancy) should not be
- // a problem
- //
- if (dwOpenCount == 0) { // do this only on the first instance of the DLL
- // open Eventlog interface
- hEventLog = MonOpenEventLog();
- // open/create shared memory used by the application to pass performance values
- status = GetSharedMemoryDataHeader (
- &hAppMemSharedMemory, &hAppMemMutex, &pDataHeader,
- TRUE); // only read access is required
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (status, LOG_USER, NULL, 0);
- goto OpenExitPoint;
- }
- // get counter and help index base values from registry
- // Open key to registry entry
- // read First Counter and First Help values
- // update static data strucutures by adding base to
- // offset value in structure.
- status = RegOpenKeyEx (
- HKEY_LOCAL_MACHINE,
- "SYSTEM\CurrentControlSet\Services\AppMem\Performance",
- 0L,
- KEY_ALL_ACCESS,
- &hKeyDriverPerf);
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (APPMEM_UNABLE_OPEN_DRIVER_KEY, LOG_USER,
- &status, sizeof(status));
- // this is fatal, if we can't get the base values of the
- // counter or help names, then the names won't be available
- // to the requesting application so there's not much
- // point in continuing.
- goto OpenExitPoint;
- }
- size = sizeof (DWORD);
- status = RegQueryValueEx(
- hKeyDriverPerf,
- "First Counter",
- 0L,
- &type,
- (LPBYTE)&dwFirstCounter,
- &size);
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (APPMEM_UNABLE_READ_FIRST_COUNTER, LOG_USER,
- &status, sizeof(status));
- // this is fatal, if we can't get the base values of the
- // counter or help names, then the names won't be available
- // to the requesting application so there's not much
- // point in continuing.
- goto OpenExitPoint;
- }
- size = sizeof (DWORD);
- status = RegQueryValueEx(
- hKeyDriverPerf,
- "First Help",
- 0L,
- &type,
- (LPBYTE)&dwFirstHelp,
- &size);
- if (status != ERROR_SUCCESS) {
- REPORT_ERROR_DATA (APPMEM_UNABLE_READ_FIRST_HELP, LOG_USER,
- &status, sizeof(status));
- // this is fatal, if we can't get the base values of the
- // counter or help names, then the names won't be available
- // to the requesting application so there's not much
- // point in continuing.
- goto OpenExitPoint;
- }
- //
- // NOTE: the initialization program could also retrieve
- // LastCounter and LastHelp if they wanted to do
- // bounds checking on the new number. e.g.
- //
- // counter->CounterNameTitleIndex += dwFirstCounter;
- // if (counter->CounterNameTitleIndex > dwLastCounter) {
- // LogErrorToEventLog (INDEX_OUT_OF_BOUNDS);
- // }
- AppMemDataDefinition.AppMemObjectType.ObjectNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemObjectType.ObjectHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemBytesAllocated.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemBytesAllocated.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemBytesAllocated.CounterOffset +=
- (DWORD)((LPBYTE)&ac.dwAppMemBytesAllocated - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemAllocs.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemAllocs.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemAllocs.CounterOffset =
- (DWORD)((LPBYTE)&ac.dwAppMemAllocs - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemAllocsSec.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemAllocsSec.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemAllocsSec.CounterOffset =
- (DWORD)((LPBYTE)&ac.dwAppMemAllocsSec - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemReAllocs.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemReAllocs.CounterHelpTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemReAllocs.CounterOffset=
- (DWORD)((LPBYTE)&ac.dwAppMemReAllocs - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemReAllocsSec.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemReAllocsSec.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemReAllocsSec.CounterOffset =
- (DWORD)((LPBYTE)&ac.dwAppMemReAllocsSec - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemFrees.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemFrees.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemFrees.CounterOffset =
- (DWORD)((LPBYTE)&ac.dwAppMemFrees - (LPBYTE)&ac);
- AppMemDataDefinition.AppMemFreesSec.CounterNameTitleIndex += dwFirstCounter;
- AppMemDataDefinition.AppMemFreesSec.CounterHelpTitleIndex += dwFirstHelp;
- AppMemDataDefinition.AppMemFreesSec.CounterOffset =
- (DWORD)((LPBYTE)&ac.dwAppMemFreesSec - (LPBYTE)&ac);
- RegCloseKey (hKeyDriverPerf); // close key to registry
- bInitOK = TRUE; // ok to use this function
- }
- dwOpenCount++; // increment OPEN counter
- status = ERROR_SUCCESS; // for successful exit
- OpenExitPoint:
- return status;
- }
- DWORD APIENTRY
- CollectAppMemPerformanceData(
- IN LPWSTR lpValueName,
- IN OUT LPVOID *lppData,
- IN OUT LPDWORD lpcbTotalBytes,
- IN OUT LPDWORD lpNumObjectTypes
- )
- /*++
- Routine Description:
- This routine will return the data for the Application memory counters
- Arguments:
- IN LPWSTR lpValueName
- pointer to a wide character string passed by registry.
- IN OUT LPVOID *lppData
- IN: pointer to the address of the buffer to receive the completed
- PerfDataBlock and subordinate structures. This routine will
- append its data to the buffer starting at the point referenced
- by *lppData.
- OUT: points to the first byte after the data structure added by this
- routine. This routine updated the value at lppdata after appending
- its data.
- IN OUT LPDWORD lpcbTotalBytes
- IN: the address of the DWORD that tells the size in bytes of the
- buffer referenced by the lppData argument
- OUT: the number of bytes added by this routine is writted to the
- DWORD pointed to by this argument
- IN OUT LPDWORD NumObjectTypes
- IN: the address of the DWORD to receive the number of objects added
- by this routine
- OUT: the number of objects added by this routine is writted to the
- DWORD pointed to by this argument
- Return Value:
- ERROR_MORE_DATA if buffer passed is too small to hold data
- any error conditions encountered are reported to the event log if
- event logging is enabled.
- ERROR_SUCCESS if success or any other error. Errors, however are
- also reported to the event log.
- --*/
- {
- // Variables for reformating the data
- ULONG SpaceNeeded;
- PERF_COUNTER_BLOCK *pPerfCounterBlock;
- PERF_INSTANCE_DEFINITION *pPerfInstanceDef;
- APPMEM_DATA_DEFINITION *pAppMemDataDefinition;
- DWORD dwQueryType;
- DWORD dwInstanceIndex;
- PAPPMEM_INSTANCE pThisAppInstanceData = NULL;
- BOOL bFreeMutex;
- PAPPMEM_COUNTERS pAC;
- //
- // before doing anything else, see if Open went OK
- //
- if ((!bInitOK) || (pDataHeader == NULL)) {
- // unable to continue because open failed.
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_SUCCESS; // yes, this is a successful exit
- }
- // see if this is a foreign (i.e. non-NT) computer data request
- //
- dwQueryType = GetQueryType (lpValueName);
- if (dwQueryType == QUERY_FOREIGN) {
- // this routine does not service requests for data from
- // Non-NT computers
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_SUCCESS;
- }
- if (dwQueryType == QUERY_ITEMS){
- if ( !(IsNumberInUnicodeList (AppMemDataDefinition.AppMemObjectType.ObjectNameTitleIndex, lpValueName))) {
- // request received for data object not provided by this routine
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_SUCCESS;
- }
- }
- // if here, then this must be one for us so load data structures
- pAppMemDataDefinition = (APPMEM_DATA_DEFINITION *) *lppData;
- if (hAppMemMutex != NULL) {
- if (WaitForSingleObject (hAppMemMutex, SHARED_MEMORY_MUTEX_TIMEOUT) == WAIT_FAILED) {
- // unable to obtain a lock
- bFreeMutex = FALSE;
- } else {
- bFreeMutex = TRUE;
- }
- } else {
- bFreeMutex = FALSE;
- }
- // always return an "instance sized" buffer after the definition blocks
- // to prevent perfmon from reading bogus data. This is strictly a hack
- // to accomodate how PERFMON handles the "0" instance case.
- // By doing this, perfmon won't choke when there are no instances
- // and the counter object & counters will be displayed in the
- // list boxes, even though no instances will be listed.
- SpaceNeeded = sizeof(APPMEM_DATA_DEFINITION) +
- ((pDataHeader->dwInstanceCount > 0 ? pDataHeader->dwInstanceCount : 1) * (
- sizeof(PERF_INSTANCE_DEFINITION) +
- MAX_SIZEOF_INSTANCE_NAME +
- sizeof(APPMEM_COUNTERS)));
- if ( *lpcbTotalBytes < SpaceNeeded ) {
- // not enough room so return nothing.
- *lpcbTotalBytes = (DWORD) 0;
- *lpNumObjectTypes = (DWORD) 0;
- return ERROR_MORE_DATA;
- }
- // copy the object & counter definition information
- memmove(pAppMemDataDefinition,
- &AppMemDataDefinition,
- sizeof(APPMEM_DATA_DEFINITION));
- // prepare to read the instance data
- pPerfInstanceDef = (PERF_INSTANCE_DEFINITION *) &pAppMemDataDefinition[1];
- // point to the first instance structure in the shared buffer
- pThisAppInstanceData = FIRST_INUSE(pDataHeader);
- // process each of the instances in the shared memory buffer
- dwInstanceIndex = 0;
- while ((dwInstanceIndex < pDataHeader->dwInstanceCount) &&
- (pThisAppInstanceData != NULL)){
- // initialize this instance
- MonBuildInstanceDefinition (
- pPerfInstanceDef,
- &pAC, // pointer to first byte after instance def
- 0, // no parent
- 0, // object to reference
- (DWORD)PERF_NO_UNIQUE_ID,
- pThisAppInstanceData->wcszInstanceName);
- //
- // collect and format app memory perf data from shared memory
- //
- pAC->CounterBlock.ByteLength = sizeof(APPMEM_COUNTERS);
- // set pointer to first counter data field
- pAC->dwAppMemBytesAllocated = pThisAppInstanceData->dwApplicationBytes;
- pAC->dwAppMemAllocs = pThisAppInstanceData->dwAllocCalls;
- pAC->dwAppMemAllocsSec = pThisAppInstanceData->dwAllocCalls;
- pAC->dwAppMemReAllocs = pThisAppInstanceData->dwReAllocCalls;
- pAC->dwAppMemReAllocsSec = pThisAppInstanceData->dwReAllocCalls;
- pAC->dwAppMemFrees = pThisAppInstanceData->dwFreeCalls;
- pAC->dwAppMemFreesSec = pThisAppInstanceData->dwFreeCalls;
- // setup for the next instance
- dwInstanceIndex++;
- pThisAppInstanceData =
- APPMEM_INST(pDataHeader, pThisAppInstanceData->dwOffsetOfNext);
- pPerfInstanceDef =
- (PERF_INSTANCE_DEFINITION *)((LPBYTE)pAC + sizeof(APPMEM_COUNTERS));
- }
- if (dwInstanceIndex == 0) {
- // zero fill one instance sized block of data if there are no
- // data instances
- memset (pPerfInstanceDef, 0,
- (sizeof(PERF_INSTANCE_DEFINITION) +
- MAX_SIZEOF_INSTANCE_NAME +
- sizeof(APPMEM_COUNTERS)));
- // adjust pointer to point to end of zeroed block
- (BYTE *)pPerfInstanceDef += (sizeof(PERF_INSTANCE_DEFINITION) +
- MAX_SIZEOF_INSTANCE_NAME +
- sizeof(APPMEM_COUNTERS));
- }
- // done with the shared memory so free the mutex if one was
- // acquired
- if (bFreeMutex) {
- ReleaseMutex (hAppMemMutex);
- }
- *lppData = (PVOID)pPerfInstanceDef;
- // update arguments for return
- *lpNumObjectTypes = 1;
- pAppMemDataDefinition->AppMemObjectType.NumInstances = dwInstanceIndex;
- pAppMemDataDefinition->AppMemObjectType.TotalByteLength =
- *lpcbTotalBytes = (DWORD)((PBYTE)pPerfInstanceDef -
- (PBYTE) pAppMemDataDefinition);
- return ERROR_SUCCESS;
- }
- DWORD APIENTRY
- CloseAppMemPerformanceData(
- )
- /*++
- Routine Description:
- This routine closes the open handles to Application Memory
- usage performance counters
- Arguments:
- None.
- Return Value:
- ERROR_SUCCESS
- --*/
- {
- if ((--dwOpenCount) == 0) { // when this is the last thread...
- if (hAppMemSharedMemory != NULL) CloseHandle(hAppMemSharedMemory);
- if (hAppMemMutex != NULL) CloseHandle(hAppMemMutex);
- pDataHeader = NULL;
- MonCloseEventLog();
- }
- return ERROR_SUCCESS;
- }