987 lines
28 KiB
C
987 lines
28 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (C) 1995-1999 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
vbfuncs.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Visual Basic interface functions exposed in pdh.dll
|
|||
|
|
|||
|
--*/
|
|||
|
#include <windows.h>
|
|||
|
#include <winperf.h>
|
|||
|
#include <pdh.h>
|
|||
|
#include "pdhidef.h"
|
|||
|
#include "pdhmsg.h"
|
|||
|
#include "strings.h"
|
|||
|
|
|||
|
#define INITIAL_VB_LIST_SIZE (4096 * 4)
|
|||
|
#define EXTEND_VB_LIST_SIZE (4096 * 2)
|
|||
|
|
|||
|
typedef struct _VB_STRING_LIST {
|
|||
|
LPSTR mszList; // pointer to buffer containing strings
|
|||
|
LPSTR szTermChar; // pointer to "next" char to use
|
|||
|
DWORD dwNumEntries; // number of strings
|
|||
|
DWORD dwSize; // max size (in chars) of buffer
|
|||
|
DWORD dwRemaining; // # of chars left
|
|||
|
DWORD dwLastEntryRead; // index of last string read indicating index of....
|
|||
|
DWORD dwLastItemLength; // length of last item read
|
|||
|
LPSTR szLastItemRead; // pointer to START of last item read
|
|||
|
} VB_STRING_LIST, FAR * LPVB_STRING_LIST;
|
|||
|
|
|||
|
VB_STRING_LIST PdhivbList = {NULL, NULL, 0, 0, 0};
|
|||
|
void PdhiDialogCallBack( IN DWORD_PTR dwArg );
|
|||
|
|
|||
|
BOOL
|
|||
|
PdhiAddStringToVbList (
|
|||
|
IN LPSTR szString
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PdhiAddStringToVbList (
|
|||
|
IN LPSTR szString
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwSize1, dwSize2;
|
|||
|
VB_STRING_LIST *pVbList;
|
|||
|
|
|||
|
dwSize1 = lstrlen(szString) + 1;
|
|||
|
pVbList = &PdhivbList;
|
|||
|
if (dwSize1 > pVbList->dwRemaining) {
|
|||
|
dwSize2 = (DWORD)(pVbList->szTermChar - pVbList->mszList);
|
|||
|
pVbList->dwSize += EXTEND_VB_LIST_SIZE;
|
|||
|
pVbList->mszList = G_REALLOC (pVbList->mszList, pVbList->dwSize);
|
|||
|
if (pVbList->mszList == NULL) {
|
|||
|
memset(pVbList, 0, sizeof(VB_STRING_LIST));
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
// update values
|
|||
|
pVbList->szLastItemRead = pVbList->mszList;
|
|||
|
pVbList->szTermChar = pVbList->mszList + dwSize2;
|
|||
|
pVbList->dwRemaining += EXTEND_VB_LIST_SIZE;
|
|||
|
}
|
|||
|
}
|
|||
|
// copy new string
|
|||
|
lstrcpy (pVbList->szTermChar, szString);
|
|||
|
pVbList->dwNumEntries++;
|
|||
|
pVbList->szTermChar += dwSize1;
|
|||
|
pVbList->dwRemaining -= dwSize1;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
PdhiDialogCallBack(
|
|||
|
IN DWORD_PTR dwArg
|
|||
|
)
|
|||
|
{
|
|||
|
// add strings in buffer to list boxpfdh
|
|||
|
LPTSTR NewCounterName;
|
|||
|
LPTSTR NewCounterName2;
|
|||
|
LPTSTR szExpandedPath;
|
|||
|
DWORD dwSize1, dwSize2;
|
|||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|||
|
PPDH_BROWSE_DLG_CONFIG pDlgConfig;
|
|||
|
|
|||
|
pDlgConfig = (PPDH_BROWSE_DLG_CONFIG)dwArg;
|
|||
|
|
|||
|
if (pDlgConfig->CallBackStatus == PDH_MORE_DATA) {
|
|||
|
// transfer buffer is too small for selection so extend it and
|
|||
|
// try again.
|
|||
|
if (pDlgConfig->szReturnPathBuffer != NULL) {
|
|||
|
G_FREE (pDlgConfig->szReturnPathBuffer);
|
|||
|
}
|
|||
|
pDlgConfig->cchReturnPathLength += EXTEND_VB_LIST_SIZE;
|
|||
|
pDlgConfig->szReturnPathBuffer =
|
|||
|
G_ALLOC ((pDlgConfig->cchReturnPathLength * sizeof (CHAR)));
|
|||
|
|
|||
|
if (pDlgConfig->szReturnPathBuffer != NULL) {
|
|||
|
pdhStatus = PDH_RETRY;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
for (NewCounterName = pDlgConfig->szReturnPathBuffer;
|
|||
|
(*NewCounterName != 0) && (pdhStatus == ERROR_SUCCESS);
|
|||
|
NewCounterName += (lstrlen(NewCounterName) + 1)) {
|
|||
|
if (strstr (NewCounterName, caszSplat) == NULL) {
|
|||
|
// this is a regular path entry so add it to the VB List
|
|||
|
if (!PdhiAddStringToVbList (NewCounterName)) {
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
szExpandedPath = G_ALLOC (INITIAL_VB_LIST_SIZE);
|
|||
|
if (szExpandedPath != NULL) {
|
|||
|
// there's a wild card path character so expand it then enter them
|
|||
|
// clear the list buffer
|
|||
|
*(LPDWORD)szExpandedPath = 0;
|
|||
|
dwSize1 = dwSize2 = INITIAL_VB_LIST_SIZE;
|
|||
|
PdhExpandCounterPath (NewCounterName, szExpandedPath, &dwSize2);
|
|||
|
if (dwSize2 < dwSize1) {
|
|||
|
// then the returned buffer fit
|
|||
|
for (NewCounterName2 = szExpandedPath;
|
|||
|
*NewCounterName2 != 0;
|
|||
|
NewCounterName2 += (lstrlen(NewCounterName2) + 1)) {
|
|||
|
|
|||
|
if (!PdhiAddStringToVbList (NewCounterName2)) {
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
break; //out of loop
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
G_FREE (szExpandedPath);
|
|||
|
} else {
|
|||
|
SetLastError (PDH_MEMORY_ALLOCATION_FAILURE);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// clear buffer
|
|||
|
memset (pDlgConfig->szReturnPathBuffer, 0,
|
|||
|
(pDlgConfig->cchReturnPathLength * sizeof(CHAR)));
|
|||
|
}
|
|||
|
pDlgConfig->CallBackStatus = pdhStatus;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
double
|
|||
|
PdhVbGetDoubleCounterValue (
|
|||
|
IN HCOUNTER hCounter,
|
|||
|
IN LPDWORD pdwCounterStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
retrieves the current value of the specified counter and returns the
|
|||
|
formatted version to the caller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN HCOUNTER hCounter
|
|||
|
pointer to the counter to get the data for
|
|||
|
|
|||
|
IN LPDWORD pdwCounterStatus
|
|||
|
status value of this counter. This value should be checked to
|
|||
|
insure the data is valid. If the status is not successful, then
|
|||
|
the data returned cannot be trusted and should not be used
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
a double precesion floating point value of the current counter value
|
|||
|
formatted and computed as required by the counter type.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
PDH_FMT_COUNTERVALUE pdhValue;
|
|||
|
DWORD dwCounterType;
|
|||
|
double dReturn;
|
|||
|
|
|||
|
pdhStatus = PdhGetFormattedCounterValue (
|
|||
|
hCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &dwCounterType, &pdhValue);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// the function was successful so return the counter status
|
|||
|
// and the returned value
|
|||
|
pdhStatus = pdhValue.CStatus;
|
|||
|
dReturn = pdhValue.doubleValue;
|
|||
|
} else {
|
|||
|
// the function returned an error so return the
|
|||
|
// error in the status field & 0.0 for a value
|
|||
|
dReturn = 0.0f;
|
|||
|
}
|
|||
|
|
|||
|
if (pdwCounterStatus != NULL) {
|
|||
|
__try {
|
|||
|
*pdwCounterStatus = pdhStatus;
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
// unable to write to status variable
|
|||
|
// don't worry about it, since it's optional and there's not much
|
|||
|
// we can do here anyway.
|
|||
|
}
|
|||
|
}
|
|||
|
return dReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbGetOneCounterPath (
|
|||
|
IN LPSTR szPathBuffer,
|
|||
|
IN DWORD cchBufferLength,
|
|||
|
IN DWORD dwDetailLevel,
|
|||
|
IN LPCSTR szCaption
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves one path string from the buffer of stored counter paths
|
|||
|
assembled by the most recent call to PdhVbCreateCounterPathList
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LPSTR szPathBuffer
|
|||
|
string buffer to return selected counter path in
|
|||
|
|
|||
|
DWORD cchBufferLength
|
|||
|
size of string buffer in characters
|
|||
|
|
|||
|
DWORD dwDetailLevel
|
|||
|
detail level to filter the counters by
|
|||
|
|
|||
|
LPCSTR szCaption
|
|||
|
string to display in the caption bar
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
returns the length of the path string in characters returned
|
|||
|
to the caller.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDH_BROWSE_DLG_CONFIG_A BrowseConfig;
|
|||
|
PDH_STATUS PdhStatus = ERROR_SUCCESS;
|
|||
|
DWORD dwReturn = 0;
|
|||
|
|
|||
|
// test access to caller supplied buffer
|
|||
|
__try {
|
|||
|
CHAR cChar;
|
|||
|
if ((cchBufferLength > 0) && (szPathBuffer != NULL)) {
|
|||
|
cChar = szPathBuffer[0];
|
|||
|
szPathBuffer[0] = 0;
|
|||
|
szPathBuffer[0] = cChar;
|
|||
|
|
|||
|
cChar = szPathBuffer[cchBufferLength - 1];
|
|||
|
szPathBuffer[cchBufferLength - 1] = 0;
|
|||
|
szPathBuffer[cchBufferLength - 1] = cChar;
|
|||
|
} else {
|
|||
|
PdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
|
|||
|
if (szCaption != NULL) {
|
|||
|
cChar = *((CHAR volatile *)szCaption);
|
|||
|
}
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
PdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
memset (&BrowseConfig, 0, sizeof(BrowseConfig));
|
|||
|
BrowseConfig.bIncludeInstanceIndex = FALSE;
|
|||
|
BrowseConfig.bSingleCounterPerAdd = TRUE;
|
|||
|
BrowseConfig.bSingleCounterPerDialog = TRUE;
|
|||
|
BrowseConfig.bLocalCountersOnly = FALSE;
|
|||
|
BrowseConfig.bWildCardInstances = FALSE;
|
|||
|
BrowseConfig.bDisableMachineSelection = FALSE;
|
|||
|
BrowseConfig.bHideDetailBox = (dwDetailLevel > 0 ? TRUE : FALSE);
|
|||
|
|
|||
|
BrowseConfig.hWndOwner = NULL; // there should be some way to get this
|
|||
|
|
|||
|
BrowseConfig.szReturnPathBuffer = szPathBuffer;
|
|||
|
BrowseConfig.cchReturnPathLength = cchBufferLength;
|
|||
|
|
|||
|
BrowseConfig.pCallBack = NULL;
|
|||
|
BrowseConfig.dwCallBackArg = 0;
|
|||
|
|
|||
|
// default is to show ALL counters
|
|||
|
BrowseConfig.dwDefaultDetailLevel = (dwDetailLevel > 0 ?
|
|||
|
dwDetailLevel : PERF_DETAIL_WIZARD);
|
|||
|
|
|||
|
BrowseConfig.szDialogBoxCaption = (LPSTR)szCaption;
|
|||
|
|
|||
|
PdhStatus = PdhBrowseCountersA (&BrowseConfig);
|
|||
|
}
|
|||
|
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
dwReturn = lstrlenA (szPathBuffer);
|
|||
|
} else {
|
|||
|
dwReturn = 0;
|
|||
|
}
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbCreateCounterPathList (
|
|||
|
IN DWORD dwDetailLevel,
|
|||
|
IN LPCSTR szCaption
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Displays the counter browsing dialog box and allows the user to select
|
|||
|
multiple counter paths. As the paths are selected, they are stored
|
|||
|
in an internal buffer for later retrieval by the caller.
|
|||
|
|
|||
|
NOTE, that calling this function will clear any previous selections.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DWORD dwDetailLevel
|
|||
|
detail level to filter the counters by
|
|||
|
|
|||
|
LPCSTR szCaption
|
|||
|
string to display in the caption bar
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
returns the number of path strings selected by the user that must
|
|||
|
be retrieved by the caller.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDH_STATUS PdhStatus = ERROR_SUCCESS;
|
|||
|
PDH_BROWSE_DLG_CONFIG_A BrowseConfig;
|
|||
|
DWORD dwReturn = 0;
|
|||
|
|
|||
|
// test access to caller supplied buffer
|
|||
|
__try {
|
|||
|
CHAR cChar;
|
|||
|
if (szCaption != NULL) {
|
|||
|
cChar = *((CHAR volatile *)szCaption);
|
|||
|
}
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
PdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
if (PdhivbList.mszList != NULL) {
|
|||
|
G_FREE (PdhivbList.mszList);
|
|||
|
memset ((LPVOID)&PdhivbList, 0, sizeof (VB_STRING_LIST));
|
|||
|
}
|
|||
|
|
|||
|
PdhivbList.mszList = G_ALLOC (INITIAL_VB_LIST_SIZE);
|
|||
|
if (PdhivbList.mszList != NULL) {
|
|||
|
PdhivbList.szLastItemRead =
|
|||
|
PdhivbList.szTermChar = PdhivbList.mszList;
|
|||
|
PdhivbList.dwRemaining =
|
|||
|
PdhivbList.dwSize = INITIAL_VB_LIST_SIZE;
|
|||
|
PdhivbList.dwLastEntryRead = 0;
|
|||
|
PdhivbList.dwLastItemLength = 0;
|
|||
|
} else {
|
|||
|
PdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
memset (&BrowseConfig, 0, sizeof(BrowseConfig));
|
|||
|
BrowseConfig.bIncludeInstanceIndex = FALSE;
|
|||
|
BrowseConfig.bSingleCounterPerAdd = FALSE;
|
|||
|
BrowseConfig.bSingleCounterPerDialog = FALSE;
|
|||
|
BrowseConfig.bLocalCountersOnly = FALSE;
|
|||
|
BrowseConfig.bWildCardInstances = FALSE;
|
|||
|
BrowseConfig.bDisableMachineSelection = FALSE;
|
|||
|
BrowseConfig.bHideDetailBox = (dwDetailLevel > 0 ? TRUE : FALSE);
|
|||
|
|
|||
|
BrowseConfig.hWndOwner = NULL; // there should be some way to get this
|
|||
|
|
|||
|
BrowseConfig.szReturnPathBuffer = G_ALLOC (INITIAL_VB_LIST_SIZE);
|
|||
|
if (BrowseConfig.szReturnPathBuffer != NULL) {
|
|||
|
BrowseConfig.cchReturnPathLength = (BrowseConfig.szReturnPathBuffer != NULL ?
|
|||
|
INITIAL_VB_LIST_SIZE : 0);
|
|||
|
|
|||
|
BrowseConfig.pCallBack = (CounterPathCallBack)PdhiDialogCallBack;
|
|||
|
BrowseConfig.dwCallBackArg = (DWORD_PTR)&BrowseConfig;
|
|||
|
|
|||
|
// default is to show ALL counters
|
|||
|
BrowseConfig.dwDefaultDetailLevel = (dwDetailLevel > 0 ?
|
|||
|
dwDetailLevel : PERF_DETAIL_WIZARD);
|
|||
|
|
|||
|
BrowseConfig.szDialogBoxCaption = (LPSTR)szCaption;
|
|||
|
|
|||
|
PdhStatus = PdhBrowseCountersA (&BrowseConfig);
|
|||
|
|
|||
|
if (BrowseConfig.szReturnPathBuffer != NULL) {
|
|||
|
G_FREE (BrowseConfig.szReturnPathBuffer);
|
|||
|
}
|
|||
|
dwReturn = PdhivbList.dwNumEntries;
|
|||
|
} else {
|
|||
|
SetLastError (PDH_MEMORY_ALLOCATION_FAILURE);
|
|||
|
dwReturn = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbGetCounterPathFromList (
|
|||
|
IN DWORD dwIndex, // starting at 1 for VB types
|
|||
|
IN LPSTR szBuffer, // return buffer
|
|||
|
IN DWORD dwBufferSize // size in chars of buffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Displays the counter browsing dialog box and allows the user to select
|
|||
|
multiple counter paths. As the paths are selected, they are stored
|
|||
|
in an internal buffer for later retrieval by the caller.
|
|||
|
|
|||
|
NOTE, that calling this function will clear any previous selections.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DWORD dwIndex
|
|||
|
The "1-based" index of the counter path to retrieve from
|
|||
|
the list of selected counter paths generated by the previous
|
|||
|
call to PdhVbCreateCounterPathList.
|
|||
|
|
|||
|
LPSTR szBuffer
|
|||
|
string buffer to return the selected string in
|
|||
|
|
|||
|
DWORD dwBufferSize
|
|||
|
size of the szBuffer in characters
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the number of characters copied to the calling function
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD dwBuffIndex; // 0-based index for "c"
|
|||
|
DWORD dwThisIndex;
|
|||
|
DWORD dwCharsCopied; // size of string not counting term NULL
|
|||
|
BOOL bContinue = TRUE;
|
|||
|
|
|||
|
dwBuffIndex = dwIndex - 1;
|
|||
|
dwCharsCopied = 0;
|
|||
|
|
|||
|
// validate the arguments
|
|||
|
|
|||
|
__try {
|
|||
|
if (dwBufferSize > 0) {
|
|||
|
// try writing to ouput buffer
|
|||
|
szBuffer[0] = 0;
|
|||
|
szBuffer[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
bContinue = FALSE;
|
|||
|
}
|
|||
|
if (dwBuffIndex >= PdhivbList.dwNumEntries) {
|
|||
|
bContinue = FALSE;
|
|||
|
}
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
bContinue = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (bContinue) {
|
|||
|
if (PdhivbList.szLastItemRead == NULL) {
|
|||
|
PdhivbList.szLastItemRead = PdhivbList.mszList;
|
|||
|
PdhivbList.dwLastEntryRead = 0;
|
|||
|
PdhivbList.dwLastItemLength = 0;
|
|||
|
}
|
|||
|
if (PdhivbList.szLastItemRead != NULL) {
|
|||
|
if (PdhivbList.dwLastItemLength == 0) {
|
|||
|
PdhivbList.dwLastItemLength =
|
|||
|
lstrlen(PdhivbList.szLastItemRead) + 1;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
bContinue = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (bContinue) {
|
|||
|
// see if this is the next entry
|
|||
|
if (dwBuffIndex == (PdhivbList.dwLastEntryRead + 1)) {
|
|||
|
PdhivbList.szLastItemRead += PdhivbList.dwLastItemLength;
|
|||
|
PdhivbList.dwLastItemLength = lstrlen(PdhivbList.szLastItemRead) + 1;
|
|||
|
PdhivbList.dwLastEntryRead++;
|
|||
|
if (PdhivbList.dwLastItemLength < dwBufferSize) {
|
|||
|
lstrcpy (szBuffer, PdhivbList.szLastItemRead);
|
|||
|
dwCharsCopied = PdhivbList.dwLastItemLength -1;
|
|||
|
}
|
|||
|
} else if (dwBuffIndex == PdhivbList.dwLastEntryRead) {
|
|||
|
// it's this one (again)
|
|||
|
if (PdhivbList.dwLastItemLength < dwBufferSize) {
|
|||
|
lstrcpy (szBuffer, PdhivbList.szLastItemRead);
|
|||
|
dwCharsCopied = PdhivbList.dwLastItemLength -1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// walk the list to the desired entry (ugh!)
|
|||
|
PdhivbList.szLastItemRead = PdhivbList.mszList;
|
|||
|
for (dwThisIndex = 0; dwThisIndex < dwBuffIndex; dwThisIndex++) {
|
|||
|
PdhivbList.szLastItemRead += lstrlen (PdhivbList.szLastItemRead) + 1;
|
|||
|
}
|
|||
|
PdhivbList.dwLastItemLength = lstrlen(PdhivbList.szLastItemRead) + 1;
|
|||
|
PdhivbList.dwLastEntryRead = dwThisIndex;
|
|||
|
if (PdhivbList.dwLastItemLength < dwBufferSize) {
|
|||
|
lstrcpy (szBuffer, PdhivbList.szLastItemRead);
|
|||
|
dwCharsCopied = PdhivbList.dwLastItemLength -1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return dwCharsCopied;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbGetCounterPathElements (
|
|||
|
IN LPCSTR szPathString,
|
|||
|
IN LPSTR szMachineName,
|
|||
|
IN LPSTR szObjectName,
|
|||
|
IN LPSTR szInstanceName,
|
|||
|
IN LPSTR szParentInstance,
|
|||
|
IN LPSTR szCounterName,
|
|||
|
IN DWORD dwBufferSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
breaks the counter path provided in the szPathString argument and
|
|||
|
returns the components in the buffers provided by the caller.
|
|||
|
The buffers must be at least "dwBufferSize" in length.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LPCSTR szPathString
|
|||
|
pointer to the full counter path that is to be parsed into
|
|||
|
component strings
|
|||
|
|
|||
|
LPSTR szMachineName
|
|||
|
caller supplied buffer that is to receive the machine name.
|
|||
|
The buffer must be at least dwBufferSize in length.
|
|||
|
|
|||
|
LPSTR szObjectName
|
|||
|
caller supplied buffer that is to receive the object name.
|
|||
|
The buffer must be at least dwBufferSize in length.
|
|||
|
|
|||
|
LPSTR szInstanceName
|
|||
|
caller supplied buffer that is to receive the Instance name.
|
|||
|
The buffer must be at least dwBufferSize in length.
|
|||
|
|
|||
|
LPSTR szParentInstance
|
|||
|
caller supplied buffer that is to receive the parent instance name.
|
|||
|
The buffer must be at least dwBufferSize in length.
|
|||
|
|
|||
|
LPSTR szCounterName
|
|||
|
caller supplied buffer that is to receive the counter name.
|
|||
|
The buffer must be at least dwBufferSize in length.
|
|||
|
|
|||
|
DWORD dwBufferSize
|
|||
|
The buffer size of the caller supplied string buffers in characters
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if the counter string is successfully parsed, otherwise
|
|||
|
a PDH error if not.
|
|||
|
|
|||
|
PDH_INVALID_ARGUMENT if one or more of the string buffers is not
|
|||
|
the correct size
|
|||
|
PDH_INSUFFICIENT_BUFFER if one or more of the counter path elements
|
|||
|
is too large for the return buffer length.
|
|||
|
PDH_MEMORY_ALLOCATION_FAILURE if a temporary memory buffer could not
|
|||
|
be allocated.
|
|||
|
--*/
|
|||
|
{
|
|||
|
PPDH_COUNTER_PATH_ELEMENTS_A pInfo;
|
|||
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|||
|
DWORD dwSize;
|
|||
|
|
|||
|
// validate the return arguments
|
|||
|
__try {
|
|||
|
CHAR cChar;
|
|||
|
if (szPathString != NULL) {
|
|||
|
cChar = *((CHAR volatile *)szPathString);
|
|||
|
if (cChar == 0) {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS){
|
|||
|
if (szMachineName != NULL) {
|
|||
|
szMachineName[0] = 0;
|
|||
|
szMachineName[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS){
|
|||
|
if (szObjectName != NULL) {
|
|||
|
szObjectName[0] = 0;
|
|||
|
szObjectName[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS){
|
|||
|
if (szInstanceName != NULL) {
|
|||
|
szInstanceName[0] = 0;
|
|||
|
szInstanceName[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS){
|
|||
|
if (szParentInstance != NULL) {
|
|||
|
szParentInstance[0] = 0;
|
|||
|
szParentInstance[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS){
|
|||
|
if (szCounterName != NULL) {
|
|||
|
szCounterName[0] = 0;
|
|||
|
szCounterName[dwBufferSize-1] = 0;
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// allocate temp buffer for component strings
|
|||
|
dwSize = (5 * dwBufferSize) + sizeof (PDH_COUNTER_INFO_A);
|
|||
|
pInfo = G_ALLOC (dwSize);
|
|||
|
if (pInfo != NULL) {
|
|||
|
pdhStatus = PdhParseCounterPathA (
|
|||
|
szPathString,
|
|||
|
pInfo,
|
|||
|
&dwSize,
|
|||
|
0);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// move from local structure to user args if the strings will fit
|
|||
|
if (pInfo->szMachineName != NULL) {
|
|||
|
if ((DWORD)lstrlenA(pInfo->szMachineName) < dwBufferSize) {
|
|||
|
lstrcpyA (szMachineName, pInfo->szMachineName);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pInfo->szObjectName != NULL) {
|
|||
|
if ((DWORD)lstrlenA(pInfo->szObjectName) < dwBufferSize) {
|
|||
|
lstrcpyA (szObjectName, pInfo->szObjectName);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pInfo->szInstanceName != NULL) {
|
|||
|
if ((DWORD)lstrlenA(pInfo->szInstanceName) < dwBufferSize) {
|
|||
|
lstrcpyA (szInstanceName, pInfo->szInstanceName);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pInfo->szParentInstance != NULL) {
|
|||
|
if ((DWORD)lstrlenA(pInfo->szParentInstance) < dwBufferSize) {
|
|||
|
lstrcpyA (szParentInstance, pInfo->szParentInstance);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pInfo->szCounterName != NULL) {
|
|||
|
if ((DWORD)lstrlenA(pInfo->szCounterName) < dwBufferSize) {
|
|||
|
lstrcpyA (szCounterName, pInfo->szCounterName);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
}
|
|||
|
} // else pass error to caller
|
|||
|
G_FREE (pInfo);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
} // else pass error to caller
|
|||
|
|
|||
|
return pdhStatus;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbAddCounter (
|
|||
|
IN HQUERY hQuery,
|
|||
|
IN LPCSTR szFullCounterPath,
|
|||
|
IN HCOUNTER *hCounter
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates and initializes a counter structure and attaches it to the
|
|||
|
specified query by calling the C function.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN HQUERY hQuery
|
|||
|
handle of the query to attach this counter to once the counter
|
|||
|
entry has been successfully created.
|
|||
|
|
|||
|
IN LPCSTR szFullCounterPath
|
|||
|
pointer to the path string that describes the counter to add to
|
|||
|
the query referenced above. This string must specify a single
|
|||
|
counter. Wildcard path strings are not permitted.
|
|||
|
|
|||
|
IN HCOUNTER *phCounter
|
|||
|
pointer to the buffer that will get the handle value of the
|
|||
|
successfully created counter entry.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns ERROR_SUCCESS if a new query was created and initialized,
|
|||
|
and a PDH_ error value if not.
|
|||
|
|
|||
|
PDH_INVALID_ARGUMENT is returned when one or more of the arguements
|
|||
|
is invalid or incorrect.
|
|||
|
PDH_MEMORY_ALLOCATION_FAILURE is returned when a memory buffer could
|
|||
|
not be allocated.
|
|||
|
PDH_INVALID_HANDLE is returned if the query handle is not valid.
|
|||
|
PDH_CSTATUS_NO_COUNTER is returned if the specified counter was
|
|||
|
not found
|
|||
|
PDH_CSTATUS_NO_OBJECT is returned if the specified object could
|
|||
|
not be found
|
|||
|
PDH_CSTATUS_NO_MACHINE is returned if a machine entry could not
|
|||
|
be created.
|
|||
|
PDH_CSTATUS_BAD_COUNTERNAME is returned if the counter name path
|
|||
|
string could not be parsed or interpreted
|
|||
|
PDH_CSTATUS_NO_COUNTERNAME is returned if an empty counter name
|
|||
|
path string is passed in
|
|||
|
PDH_FUNCTION_NOT_FOUND is returned if the calculation function
|
|||
|
for this counter could not be determined.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD dwReturn = ERROR_SUCCESS;
|
|||
|
HCOUNTER hLocalCounter = NULL;
|
|||
|
|
|||
|
if ((hCounter == NULL) || (szFullCounterPath == NULL)) {
|
|||
|
dwReturn = PDH_INVALID_ARGUMENT;
|
|||
|
} else {
|
|||
|
dwReturn = PdhAddCounterA (hQuery, szFullCounterPath, 0, &hLocalCounter);
|
|||
|
}
|
|||
|
|
|||
|
if (dwReturn == ERROR_SUCCESS) {
|
|||
|
__try {
|
|||
|
* hCounter = hLocalCounter;
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
dwReturn = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbOpenQuery (
|
|||
|
IN HQUERY *phQuery
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
allocates a new query structure for a VB app by calling the "C"
|
|||
|
function with the rest of the arguments supplied
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN HQUERY *phQuery
|
|||
|
pointer to the buffer that will receive the query handle opened.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns ERROR_SUCCESS if a new query was created and initialized,
|
|||
|
and a PDH_ error value if not.
|
|||
|
|
|||
|
PDH_INVALID_ARGUMENT is returned when one or more of the arguements
|
|||
|
is invalid or incorrect.
|
|||
|
PDH_MEMORY_ALLOCATION_FAILURE is returned when a memory buffer could
|
|||
|
not be allocated.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD dwReturn = ERROR_SUCCESS;
|
|||
|
HQUERY hLocalQuery = NULL;
|
|||
|
|
|||
|
if (phQuery == NULL) {
|
|||
|
dwReturn = PDH_INVALID_ARGUMENT;
|
|||
|
} else {
|
|||
|
dwReturn = PdhOpenQuery(NULL, 0, &hLocalQuery);
|
|||
|
}
|
|||
|
|
|||
|
if (dwReturn == ERROR_SUCCESS) {
|
|||
|
__try {
|
|||
|
* phQuery = hLocalQuery;
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
dwReturn = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbIsGoodStatus (
|
|||
|
IN LONG lStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Checks the status severity of the PDH status value
|
|||
|
passed into the function as a binary Good (TRUE)/Bad (FALSE)
|
|||
|
value.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LONG lStatus
|
|||
|
Status code to test
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the status code is Success or Informational severity
|
|||
|
FALSE if the status code is Error or Warning severity
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL bReturn;
|
|||
|
|
|||
|
if (lStatus == ERROR_SUCCESS) {
|
|||
|
bReturn = TRUE;
|
|||
|
} else if (IsSuccessSeverity(lStatus)) {
|
|||
|
bReturn = TRUE;
|
|||
|
} else if (IsInformationalSeverity(lStatus)) {
|
|||
|
bReturn = TRUE;
|
|||
|
} else {
|
|||
|
bReturn = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return (DWORD)bReturn;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbOpenLog (
|
|||
|
IN LPCSTR szLogFileName,
|
|||
|
IN DWORD dwAccessFlags,
|
|||
|
IN LPDWORD lpdwLogType,
|
|||
|
IN HQUERY hQuery,
|
|||
|
IN DWORD dwMaxSize,
|
|||
|
IN LPCSTR szUserCaption,
|
|||
|
IN HLOG *phLog
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN LPCSTR szLogFileName,
|
|||
|
IN DWORD dwAccessFlags,
|
|||
|
IN LPDWORD lpdwLogType,
|
|||
|
IN HQUERY hQuery,
|
|||
|
IN DWORD dwMaxSize,
|
|||
|
IN LPCSTR szUserCaption,
|
|||
|
IN HLOG *phLog
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the status code is Success or Informational severity
|
|||
|
FALSE if the status code is Error or Warning severity
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return PdhOpenLogA( szLogFileName,
|
|||
|
dwAccessFlags,
|
|||
|
lpdwLogType,
|
|||
|
hQuery,
|
|||
|
dwMaxSize,
|
|||
|
szUserCaption,
|
|||
|
phLog
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbUpdateLog (
|
|||
|
IN HLOG hLog,
|
|||
|
IN LPCSTR szUserString
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN HLOG hLog,
|
|||
|
IN LPCWSTR szUserString
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the status code is Success or Informational severity
|
|||
|
FALSE if the status code is Error or Warning severity
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
return PdhUpdateLogA(hLog,
|
|||
|
szUserString
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
PdhVbGetLogFileSize (
|
|||
|
IN HLOG hLog,
|
|||
|
IN LONG *lSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN HLOG hLog,
|
|||
|
IN LONGLONG *llSize
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the status code is Success or Informational severity
|
|||
|
FALSE if the status code is Error or Warning severity
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
LONGLONG llTemp;
|
|||
|
|
|||
|
pdhStatus = PdhGetLogFileSize(hLog,
|
|||
|
&llTemp);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
if (llTemp > 0x0000000080000000) {
|
|||
|
// file size is larger than a long value
|
|||
|
pdhStatus = PDH_INSUFFICIENT_BUFFER;
|
|||
|
} else {
|
|||
|
__try {
|
|||
|
*lSize = (LONG)(llTemp & 0x000000007FFFFFFF);
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
pdhStatus = PDH_INVALID_ARGUMENT;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return pdhStatus;
|
|||
|
}
|
|||
|
|