237 lines
8.7 KiB
C
237 lines
8.7 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
perfexpr.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file implements an Performance Object that presents
|
|||
|
Extended Process performance object data
|
|||
|
|
|||
|
Created:
|
|||
|
|
|||
|
Bob Watson 22-Oct-1996
|
|||
|
|
|||
|
Revision History
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
//
|
|||
|
// Include Files
|
|||
|
//
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <winperf.h>
|
|||
|
#include <ntprfctr.h>
|
|||
|
#include <perfutil.h>
|
|||
|
#include "perfsprc.h"
|
|||
|
#include "perfmsg.h"
|
|||
|
#include "dataexpr.h"
|
|||
|
|
|||
|
DWORD APIENTRY
|
|||
|
CollectExProcessObjectData (
|
|||
|
IN OUT LPVOID *lppData,
|
|||
|
IN OUT LPDWORD lpcbTotalBytes,
|
|||
|
IN OUT LPDWORD lpNumObjectTypes
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will return the data for the processor object
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
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
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
0 if successful, else Win 32 error code of failure
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD TotalLen; // Length of the total return block
|
|||
|
DWORD NumExProcessInstances;
|
|||
|
|
|||
|
PPROCESS_VA_INFO pThisProcess; // pointer to current process
|
|||
|
PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
|
|||
|
EXPROCESS_DATA_DEFINITION *pExProcessDataDefinition;
|
|||
|
|
|||
|
PEXPROCESS_COUNTER_DATA pECD;
|
|||
|
|
|||
|
if (pProcessVaInfo) { // process only if a buffer is available
|
|||
|
pExProcessDataDefinition = (EXPROCESS_DATA_DEFINITION *)*lppData;
|
|||
|
|
|||
|
// check for sufficient space in buffer for at least one entry
|
|||
|
|
|||
|
TotalLen = sizeof(EXPROCESS_DATA_DEFINITION) +
|
|||
|
sizeof(PERF_INSTANCE_DEFINITION) +
|
|||
|
(MAX_PROCESS_NAME_LENGTH + 1) * sizeof (WCHAR) +
|
|||
|
sizeof(EXPROCESS_COUNTER_DATA);
|
|||
|
|
|||
|
if (*lpcbTotalBytes < TotalLen) {
|
|||
|
*lpcbTotalBytes = 0;
|
|||
|
*lpNumObjectTypes = 0;
|
|||
|
return ERROR_MORE_DATA;
|
|||
|
}
|
|||
|
|
|||
|
// copy process data block to buffer
|
|||
|
|
|||
|
memcpy (pExProcessDataDefinition,
|
|||
|
&ExProcessDataDefinition,
|
|||
|
sizeof(EXPROCESS_DATA_DEFINITION));
|
|||
|
|
|||
|
NumExProcessInstances = 0;
|
|||
|
|
|||
|
pThisProcess = pProcessVaInfo;
|
|||
|
|
|||
|
TotalLen = sizeof(EXPROCESS_DATA_DEFINITION);
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
&pExProcessDataDefinition[1];
|
|||
|
|
|||
|
while (pThisProcess) {
|
|||
|
|
|||
|
// see if this instance will fit
|
|||
|
|
|||
|
TotalLen += sizeof (PERF_INSTANCE_DEFINITION) +
|
|||
|
(MAX_PROCESS_NAME_LENGTH + 1) * sizeof (WCHAR) +
|
|||
|
sizeof (DWORD) +
|
|||
|
sizeof (EXPROCESS_COUNTER_DATA);
|
|||
|
|
|||
|
if (*lpcbTotalBytes < TotalLen) {
|
|||
|
*lpcbTotalBytes = 0;
|
|||
|
*lpNumObjectTypes = 0;
|
|||
|
return ERROR_MORE_DATA;
|
|||
|
}
|
|||
|
|
|||
|
MonBuildInstanceDefinition (pPerfInstanceDefinition,
|
|||
|
(PVOID *) &pECD,
|
|||
|
0,
|
|||
|
0,
|
|||
|
(DWORD)-1,
|
|||
|
pThisProcess->pProcessName->Buffer);
|
|||
|
|
|||
|
NumExProcessInstances++;
|
|||
|
|
|||
|
pECD->CounterBlock.ByteLength = sizeof (EXPROCESS_COUNTER_DATA);
|
|||
|
|
|||
|
// load counters from the process va data structure
|
|||
|
|
|||
|
pECD->ProcessId = pThisProcess->dwProcessId;
|
|||
|
pECD->ImageReservedBytes = pThisProcess->ImageReservedBytes;
|
|||
|
pECD->ImageFreeBytes = pThisProcess->ImageFreeBytes;
|
|||
|
pECD->ReservedBytes = pThisProcess->ReservedBytes;
|
|||
|
pECD->FreeBytes = pThisProcess->FreeBytes;
|
|||
|
|
|||
|
pECD->CommitNoAccess = pThisProcess->MappedCommit[NOACCESS];
|
|||
|
pECD->CommitReadOnly = pThisProcess->MappedCommit[READONLY];
|
|||
|
pECD->CommitReadWrite = pThisProcess->MappedCommit[READWRITE];
|
|||
|
pECD->CommitWriteCopy = pThisProcess->MappedCommit[WRITECOPY];
|
|||
|
pECD->CommitExecute = pThisProcess->MappedCommit[EXECUTE];
|
|||
|
pECD->CommitExecuteRead = pThisProcess->MappedCommit[EXECUTEREAD];
|
|||
|
pECD->CommitExecuteWrite = pThisProcess->MappedCommit[EXECUTEREADWRITE];
|
|||
|
pECD->CommitExecuteWriteCopy = pThisProcess->MappedCommit[EXECUTEWRITECOPY];
|
|||
|
|
|||
|
pECD->ReservedNoAccess = pThisProcess->PrivateCommit[NOACCESS];
|
|||
|
pECD->ReservedReadOnly = pThisProcess->PrivateCommit[READONLY];
|
|||
|
pECD->ReservedReadWrite = pThisProcess->PrivateCommit[READWRITE];
|
|||
|
pECD->ReservedWriteCopy = pThisProcess->PrivateCommit[WRITECOPY];
|
|||
|
pECD->ReservedExecute = pThisProcess->PrivateCommit[EXECUTE];
|
|||
|
pECD->ReservedExecuteRead = pThisProcess->PrivateCommit[EXECUTEREAD];
|
|||
|
pECD->ReservedExecuteWrite = pThisProcess->PrivateCommit[EXECUTEREADWRITE];
|
|||
|
pECD->ReservedExecuteWriteCopy = pThisProcess->PrivateCommit[EXECUTEWRITECOPY];
|
|||
|
|
|||
|
pECD->UnassignedNoAccess = pThisProcess->OrphanTotals.CommitVector[NOACCESS];
|
|||
|
pECD->UnassignedReadOnly = pThisProcess->OrphanTotals.CommitVector[READONLY];
|
|||
|
pECD->UnassignedReadWrite = pThisProcess->OrphanTotals.CommitVector[READWRITE];
|
|||
|
pECD->UnassignedWriteCopy = pThisProcess->OrphanTotals.CommitVector[WRITECOPY];
|
|||
|
pECD->UnassignedExecute = pThisProcess->OrphanTotals.CommitVector[EXECUTE];
|
|||
|
pECD->UnassignedExecuteRead = pThisProcess->OrphanTotals.CommitVector[EXECUTEREAD];
|
|||
|
pECD->UnassignedExecuteWrite = pThisProcess->OrphanTotals.CommitVector[EXECUTEREADWRITE];
|
|||
|
pECD->UnassignedExecuteWriteCopy = pThisProcess->OrphanTotals.CommitVector[EXECUTEWRITECOPY];
|
|||
|
|
|||
|
pECD->ImageTotalNoAccess = pThisProcess->MemTotals.CommitVector[NOACCESS];
|
|||
|
pECD->ImageTotalReadOnly = pThisProcess->MemTotals.CommitVector[READONLY];
|
|||
|
pECD->ImageTotalReadWrite = pThisProcess->MemTotals.CommitVector[READWRITE];
|
|||
|
pECD->ImageTotalWriteCopy = pThisProcess->MemTotals.CommitVector[WRITECOPY];
|
|||
|
pECD->ImageTotalExecute = pThisProcess->MemTotals.CommitVector[EXECUTE];
|
|||
|
pECD->ImageTotalExecuteRead = pThisProcess->MemTotals.CommitVector[EXECUTEREAD];
|
|||
|
pECD->ImageTotalExecuteWrite = pThisProcess->MemTotals.CommitVector[EXECUTEREADWRITE];
|
|||
|
pECD->ImageTotalExecuteWriteCopy = pThisProcess->MemTotals.CommitVector[EXECUTEWRITECOPY];
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)&pECD[1];
|
|||
|
|
|||
|
pThisProcess = pThisProcess->pNextProcess; // point to next process
|
|||
|
} // end while not at end of list
|
|||
|
|
|||
|
} // end if valid process info buffer
|
|||
|
else {
|
|||
|
// pProcessVaInfo is NULL. Initialize the DataDef and return
|
|||
|
// with no data
|
|||
|
pExProcessDataDefinition = (EXPROCESS_DATA_DEFINITION *)*lppData;
|
|||
|
|
|||
|
TotalLen = sizeof(EXPROCESS_DATA_DEFINITION) +
|
|||
|
sizeof (PERF_INSTANCE_DEFINITION) +
|
|||
|
(MAX_PROCESS_NAME_LENGTH + 1) * sizeof (WCHAR) +
|
|||
|
sizeof (DWORD) +
|
|||
|
sizeof (EXPROCESS_COUNTER_DATA);
|
|||
|
|
|||
|
if (*lpcbTotalBytes < TotalLen) {
|
|||
|
*lpcbTotalBytes = 0;
|
|||
|
*lpNumObjectTypes = 0;
|
|||
|
return ERROR_MORE_DATA;
|
|||
|
}
|
|||
|
|
|||
|
// copy process data block to buffer
|
|||
|
|
|||
|
memcpy (pExProcessDataDefinition,
|
|||
|
&ExProcessDataDefinition,
|
|||
|
sizeof(EXPROCESS_DATA_DEFINITION));
|
|||
|
|
|||
|
NumExProcessInstances = 0;
|
|||
|
|
|||
|
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
|||
|
&pExProcessDataDefinition[1];
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pExProcessDataDefinition->ExProcessObjectType.NumInstances =
|
|||
|
NumExProcessInstances;
|
|||
|
|
|||
|
*lpcbTotalBytes =
|
|||
|
pExProcessDataDefinition->ExProcessObjectType.TotalByteLength =
|
|||
|
(DWORD)((PCHAR) pPerfInstanceDefinition -
|
|||
|
(PCHAR) pExProcessDataDefinition);
|
|||
|
|
|||
|
*lppData = (LPVOID) pPerfInstanceDefinition;
|
|||
|
|
|||
|
*lpNumObjectTypes = 1;
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|