Microsoft KB Archive/274561

{|
 * width="100%"|

BUG: PdhExpandCounterPath Fails on Windows 2000

 * }

Q274561

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), included with:
 * the operating system: Microsoft Windows 2000

-

SYMPTOMS
On Windows 2000, the PdhExpandCounterPath API fails and a random error code is returned. Both the ANSI version of the API, PdhExpandCounterPathA, and the Unicode version, PdhExpandCounterPathW, exhibit this problem.

RESOLUTION
A supported fix is now available from Microsoft, but it is only intended to correct the problem described in this article and should be applied only to systems experiencing this specific problem. This fix may receive additional testing at a later time, to further ensure product quality. Therefore, if you are not severely affected by this problem, Microsoft recommends that you wait for the next Windows 2000 Service Pack that contains this fix.

To resolve this problem immediately, contact Microsoft Product Support Services to obtain the fix. For a complete list of Microsoft Product Support Services phone numbers and information about support costs, please go to the following address on the World Wide Web:

http://support.microsoft.com/directory/overview.asp

NOTE: In special cases, charges that are normally incurred for support calls may be canceled, if a Microsoft Support Professional determines that a specific update will resolve your problem. Normal support costs will apply to additional support questions and issues that do not qualify for the specific update in question.

STATUS
Microsoft has confirmed this to be a problem in Microsoft Windows 2000 and Microsoft Windows 2000 Service Pack 1.

MORE INFORMATION
If an application needs to determine all of the counter paths for a given performance object, the following algorithm can be used on Windows NT 4.0 as well as Windows 2000:


 * 1) Call the PdhEnumObjectItems API to return the available counters and instances provided by a given object on a given computer.
 * 2) Call the PdhMakeCounterPath API to create a full counter path from individual path members.

Sample Code
The following sample code demonstrates the problem with PdhExpandCounterPath. It also demonstrates how to use the other Performance Data Helper (PDH) APIs to work around the problem. This code must be linked with Pdh.lib.

#define UNICODE
 * 1) define _UNICODE


 * 1) include 
 * 2) include 
 * 3) include 

// The following headers require that this code be linked with Pdh.lib.
 * 1) include 
 * 2) include 


 * 1) define PATHSIZE 0xFFFF

void DemonstrateFailure {

// This routine will fail on Windows 2000 and Windows 2000 SP1 // due to a bug in PdhExpandCounterPath.

PTSTR szCtrPath = NULL; DWORD cchCtrPath = 0;

TCHAR szWildCardPath[MAX_PATH];

PDH_STATUS pdhStatus;

// Use the counter path format without specifying the computer. // \object(parent/instance#index)\counter

_tcscpy(szWildCardPath, TEXT(&quot;\\Process(*/*#1)\\*&quot;));

// First try with an initial buffer size. szCtrPath = (PTSTR) GlobalAlloc(GPTR, PATHSIZE * sizeof(TCHAR)); cchCtrPath = PATHSIZE;

pdhStatus = PdhExpandCounterPath(szWildCardPath, szCtrPath,         &cchCtrPath);

// Upon success, print all counter path names. if (pdhStatus == PDH_CSTATUS_VALID_DATA) {

PTSTR ptr;

ptr = szCtrPath; while (*ptr) { _tprintf(TEXT(&quot;[] %s\n&quot;), ptr); ptr += _tcslen(ptr); ptr++; }

} else _tprintf(TEXT(&quot;PdhExpandCounterPath failed: %X\n&quot;), pdhStatus);

GlobalFree((PVOID)szCtrPath); }

void main {

PTSTR szCtrPath      = NULL; DWORD cchCtrPath     = 0;

PTSTR szInstancePath = NULL; DWORD cchInstancePath = 0; TCHAR szWildCardPath[MAX_PATH]; TCHAR szFullCounterPath[MAX_PATH]; PDH_COUNTER_PATH_ELEMENTS counterPath;

PDH_STATUS pdhStatus;

DemonstrateFailure;

printf(&quot;\nPress any key to demonstrate the workaround...\n&quot;); _getch;

_tcscpy(szWildCardPath, TEXT(&quot;Process&quot;));

szCtrPath = (PTSTR) GlobalAlloc(GPTR, PATHSIZE * sizeof(TCHAR)); cchCtrPath = PATHSIZE; szInstancePath = (PTSTR) GlobalAlloc(GPTR, PATHSIZE * sizeof(TCHAR)); cchInstancePath = PATHSIZE;

pdhStatus = PdhEnumObjectItems(NULL, NULL, szWildCardPath, szCtrPath,        &cchCtrPath, szInstancePath, &cchInstancePath,          PERF_DETAIL_WIZARD, 0);

// Upon success, print all counter path names. if (pdhStatus == ERROR_SUCCESS) {

PTSTR ptr, ptr1;

counterPath.szMachineName = NULL; counterPath.szObjectName = szWildCardPath; counterPath.szParentInstance = NULL; counterPath.dwInstanceIndex = -1;

ptr = szCtrPath; while (*ptr) {

counterPath.szCounterName = ptr; ptr1 = szInstancePath; while (*ptr1) {

counterPath.szInstanceName = ptr1;

cchCtrPath = sizeof(szFullCounterPath); pdhStatus = PdhMakeCounterPath(&counterPath,                  szFullCounterPath, &cchCtrPath, 0);

if (pdhStatus == ERROR_SUCCESS) _tprintf(TEXT(&quot;%s\n&quot;), szFullCounterPath); else _tprintf(TEXT(&quot;PdhMakeCounterPath failed : %X\n&quot;),                    pdhStatus);

ptr1 += _tcslen(ptr1); ptr1++; }

ptr += _tcslen(ptr); ptr++; }  }   else _tprintf(TEXT(&quot;PdhEnumObjectItems failed: %X\n&quot;), pdhStatus);

GlobalFree((PVOID) szCtrPath); GlobalFree((PVOID) szInstancePath); }