Link to home
Start Free TrialLog in
Avatar of suresh2000
suresh2000

asked on

Problem with windows2000 Registry!!

I have a prg written under NT 4.0, which reads all the Processes running and get their PID to find the Total Kernel Time of each process and hence the cumulative Kernel time for the entire system by summing up the kernel time for individual process.

  The above program is running Fine in NT 4.0, but if i try to execute the same programe under windows 2000, the program is failing and the error given is "Could Not Obtain Performance Data" .

  What could be the reason for this, I'm herewith attaching the code.  Please read it and if possible try to rectify the error, because it's very urgent.

Code :-

#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <ctype.h>
#include <process.h>
                                                
#define REGKEY_PERF         "software\\microsoft\\windows nt\\currentversion\\perflib"
#define REGSUBKEY_COUNTERS  "Counters"
#define PROCESS_COUNTER     "process"
#define PN_PROCESS_ID       "ID Process"

#define INITIAL_SIZE        51200
#define EXTEND_SIZE         25600

BOOL EnumAllProcesses();
BOOL FindProcessesNT();
void test1(HANDLE hProcess);
DWORD KernelTime;
DWORD  UserTime;
      

void main(int arrgc,char** argv[])
{
      
       FindProcessesNT();      
      printf("Total Kernel Time is : %d\n " ,KernelTime);
      printf("Total User Time is : %d " ,UserTime);

}

BOOL FindProcessesNT()
{
      HANDLE                                     hProcess;
      BOOL                                     bErrorOccured = FALSE;
      DWORD                        rc;
    HKEY                         hKeyNames;
    DWORD                        dwType;
    DWORD                        dwSize;
    LPBYTE                       buf = NULL;
    TCHAR                        szSubKey[1024];
    LANGID                       lid;
    LPSTR                        p;
    LPSTR                        p2;
    PPERF_DATA_BLOCK             pPerf;
    PPERF_OBJECT_TYPE            pObj;
    PPERF_INSTANCE_DEFINITION    pInst;
    PPERF_COUNTER_BLOCK          pCounter;
      PPERF_COUNTER_DEFINITION       pCounterdef;

    DWORD                        i;
    TCHAR                        szProcessName[MAX_PATH];
    DWORD                        dwLimit = 256;
      DWORD                                     dwNumTasks;
      char*                                     m_strLastError;
      char                                     px_process[10];

      DWORD                                     *pProcessID;
      DWORD                                     ProcessID;


      PPERF_COUNTER_DEFINITION FindCounter (PPERF_OBJECT_TYPE pObject, DWORD TitleIndex);
      PVOID CounterData (PPERF_INSTANCE_DEFINITION pInst, PPERF_COUNTER_DEFINITION pCount);

    lid = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
    sprintf( szSubKey, "%s\\%03x", REGKEY_PERF, lid );
    rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                       szSubKey,
                       0,
                       KEY_READ,
                       &hKeyNames
                     );
    if (rc != ERROR_SUCCESS)
      {
            bErrorOccured=TRUE;
            m_strLastError = "Could not open performance registry key";
        goto exit;

    }

      //
    // get the buffer size for the counter names
    //
    rc = RegQueryValueEx(hKeyNames,
                          REGSUBKEY_COUNTERS,
                          NULL,
                          &dwType,
                          NULL,
                          &dwSize
                        );

    if (rc != ERROR_SUCCESS)
      {
            bErrorOccured=TRUE;
            m_strLastError="Could not open counter registry key";
        goto exit;
    }

    //
    // allocate the counter names buffer
    //
    buf = (LPBYTE) malloc(dwSize);
     if (buf == NULL)
      {
            bErrorOccured=TRUE;
            m_strLastError="Out of Memory";
        goto exit;
    }
    memset(buf, 0, dwSize);

    //
    // read the counter names from the registry
    //
    rc = RegQueryValueEx( hKeyNames,
                          REGSUBKEY_COUNTERS,
                          NULL,
                          &dwType,
                          buf,
                          &dwSize
                        );

    if (rc != ERROR_SUCCESS)
      {
            bErrorOccured = TRUE;
            m_strLastError = "Could Not Read the counter Names";
        goto exit;
    }

    //
    // now loop thru the counter names looking for the "Process" counters:
    // the buffer contains multiple null terminated strings and then
    // finally null terminated at the end.  the strings are in pairs of
    // counter number and counter name.
    //

    p =(LPSTR) buf;
    while (*p)
      {
        if (p > (LPSTR)buf)
            {
            for( p2=p-2; isdigit(*p2); p2--)
                                    ;
        }
        if (_stricmp(p, PROCESS_COUNTER) == 0)
            {
            // look backwards for the counter number
            for(p2=p-2; isdigit(*p2); p2--)
                                    ;
            strcpy(szSubKey, p2+1);
        }
        if (_stricmp(p, PN_PROCESS_ID) == 0)
            {
            // look backwards for the counter number
            for(p2=p-2; isdigit(*p2); p2--)
                                    ;
            strcpy(px_process,p2+1);
        }
        p += (strlen(p) + 1);
    }


    // free the counter names buffer
    free(buf);


    // allocate the initial buffer for the performance data

    dwSize = INITIAL_SIZE;
    buf = (LPBYTE)malloc( dwSize );
    if (buf == NULL)
      {
            bErrorOccured = TRUE;
            m_strLastError ="Out of Memory";
        goto exit;
    }
    memset(buf, 0, dwSize);

  //  dwR = GetPerfTitleSz (ghMachineKey, ghPerfKey, &TitleBuffer, &Title, &Last);

    while (TRUE)
      {

        rc = RegQueryValueEx( HKEY_PERFORMANCE_DATA,
                              szSubKey,
                              NULL,
                              &dwType,
                              buf,
                              &dwSize
                            );

        pPerf = (PPERF_DATA_BLOCK) buf;

        // check for success and valid perf data block signature

        if ((rc == ERROR_SUCCESS) &&
            (dwSize > 0) &&
            (pPerf)->Signature[0] == (WCHAR)'P' &&
            (pPerf)->Signature[1] == (WCHAR)'E' &&
            (pPerf)->Signature[2] == (WCHAR)'R' &&
            (pPerf)->Signature[3] == (WCHAR)'F' )
            {
            break;
        }

        // if buffer is not big enough, reallocate and try again

        if (rc == ERROR_MORE_DATA)
            {
            dwSize += EXTEND_SIZE;
            buf = (LPBYTE)realloc( buf, dwSize );
            memset( buf, 0, dwSize );
        }
        else
            {
                  bErrorOccured = TRUE;
                  m_strLastError = "Could Not Obtain Performance Data";
                  goto exit;
        }
    }

      // set the perf_object_type pointer

    pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
      dwNumTasks = min( dwLimit, (DWORD)pObj->NumInstances );
    pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);

    // loop thru the performance instance data extracting each process name

    for (i=0; i<dwNumTasks; i++)
      {
        //
        // pointer to the process name
        //
        p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);

        //
        // convert it to ascii
        //
        rc = WideCharToMultiByte( CP_ACP,
                                  0,
                                  (LPCWSTR)p,
                                  -1,
                                  szProcessName,
                                  sizeof(szProcessName),
                                  NULL,
                                  NULL
                                );
            // get the process id
            pCounter = (PPERF_COUNTER_BLOCK)((PCHAR)pInst + pInst->ByteLength);

          if (pCounterdef = FindCounter (pObj, atol(px_process)))
        {
                  pProcessID = (DWORD *) CounterData (pInst, pCounterdef);
                  ProcessID = *pProcessID;
                  printf("Process id: %d  ", ProcessID);
        }
//  #endif

            // next process
        pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
            printf("%s\n",szProcessName);
            hProcess = OpenProcess(
    PROCESS_ALL_ACCESS,      
    FALSE,
    ProcessID);       // process identifier
   
       test1(hProcess);


     }


      


             printf("\nTotal number of process Running is %d ",dwNumTasks);

exit:
    if (buf)
      {
        free(buf);
    }

    RegCloseKey(hKeyNames);
    RegCloseKey(HKEY_PERFORMANCE_DATA);
      return !bErrorOccured;

}


PPERF_COUNTER_DEFINITION NextCounter (PPERF_COUNTER_DEFINITION pCounter)
{
    if (pCounter)
        return (PPERF_COUNTER_DEFINITION)((PCHAR) pCounter + pCounter->ByteLength);
    else
        return NULL;
}

PPERF_COUNTER_DEFINITION FirstCounter (PPERF_OBJECT_TYPE pObject)
{
    if (pObject)
        return (PPERF_COUNTER_DEFINITION)((PCHAR) pObject + pObject->HeaderLength);
    else
        return NULL;
}

PVOID CounterData (PPERF_INSTANCE_DEFINITION pInst, PPERF_COUNTER_DEFINITION pCount)
{
      PPERF_COUNTER_BLOCK pCounterBlock;

    if (pCount && pInst)
        {
        pCounterBlock = (PPERF_COUNTER_BLOCK)((PCHAR)pInst + pInst->ByteLength);
        return (PVOID)((PCHAR)pCounterBlock + pCount->CounterOffset);
        }
    else
        return NULL;
}

PPERF_COUNTER_DEFINITION FindCounter (PPERF_OBJECT_TYPE pObject, DWORD TitleIndex)
{
      PPERF_COUNTER_DEFINITION pCounter;
      DWORD         i = 0;

    if (pCounter = FirstCounter (pObject))
        while (i < pObject->NumCounters)
            {
            if (pCounter->CounterNameTitleIndex == TitleIndex)
                return pCounter;

            pCounter = NextCounter (pCounter);
            i++;
            }

    return NULL;

}


                                                                                                                                                                                                                                                                                                                                                                                          
void test1(HANDLE hProcess) {


    FILETIME lpCreationTime;      // when the process was created
    FILETIME lpExitTime;            // when the process exited
    FILETIME lpKernelTime;            // time the process has spent in kernel mode
    FILETIME lpUserTime;             // time the process has spent in user mode
      SYSTEMTIME lpSystemTimeKernel;
      SYSTEMTIME lpSystemTimeUser;

         

      GetProcessTimes(hProcess,&lpCreationTime,&lpExitTime,&lpKernelTime,&lpUserTime);
//      FileTimeToSystemTime(&lpCreationTime,&lpSystemTime);
//      printf("The Creation Time is %d-%d-%d-%d\n ",lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds);
      FileTimeToSystemTime(&lpKernelTime,&lpSystemTimeKernel) ;
      //printf("The TotalKernel Time is %d-%d-%d-%d\n ",lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds);
      printf("The TotalKernel Time IN MillSecond is %d\n",lpSystemTimeKernel.wMilliseconds);

      FileTimeToSystemTime(&lpUserTime,&lpSystemTimeUser) ;
      //printf("The TotalUser Time is %d-%d-%d-%d\n ",lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds);
      printf("The TotalUser Time IN MillSecond is %d\n ",lpSystemTimeUser.wMilliseconds);

      //FileTimeToSystemTime(&lpExitTime,&lpSystemTime)      ;
      //printf("The TotalExit Time is %d-%d-%d-%d\n ",lpSystemTime.wHour,lpSystemTime.wMinute,lpSystemTime.wSecond,lpSystemTime.wMilliseconds);
      KernelTime = KernelTime + lpSystemTimeKernel.wMilliseconds;
      UserTime = UserTime + lpSystemTimeUser.wMilliseconds;

}
Avatar of suresh2000
suresh2000

ASKER

Please help me, it's very urgent.
ASKER CERTIFIED SOLUTION
Avatar of naveenkohli
naveenkohli

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Naveen,

   Thanks for your immediate response and reply, Previously i was running in Windows 2000 RC1 and now i upgraded to windows2000 RC2, and still now i'm facing the sample problem,
and the execution fails at this point

{
bErrorOccured = TRUE;
m_strLastError = "Could Not Obtain Performance Data";
goto exit;
}

and it exits.  

Even i debugged and saw, but could not find the reason, If possible can u diagnose and tell the reason,  so if the code is running in u'r system, then the problem is not with the code!!! or some other.!!  
Suresh,
Do one thing.. In the code block, get the last error and check form the list what  this corresponds to.

{
bErrorOccured = TRUE;
m_strLastError = "Could Not Obtain Performance Data";

LPVOID lpErrorDesc
DWORD dwError = ::GetLastError ();
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpErrorDesc, 0, NULL);

goto exit;
}

Hi Naveen,

   Thanks for your immediate response and reply, Previously i was running in Windows 2000 RC1 and now i upgraded to windows2000 RC2, and still now i'm facing the sample problem,
and the execution fails at this point

{
bErrorOccured = TRUE;
m_strLastError = "Could Not Obtain Performance Data";
goto exit;
}

and it exits.  

Even i debugged and saw, but could not find the reason, If possible can u diagnose and tell the reason,  so if the code is running in u'r system, then the problem is not with the code!!! or some other.!!  
Hi Naveen,
 
   I checked it up, using the GetLastError(), i checked up, but the error number  showing is 0, which indicates no_erorr.

  May be its not able to allocate so much buffer!!!

  still seeking for solution!! and could not diagnose!!
Hi naveen.
 
When i debugged, what i found out is when the control comes at the line named rc and when it checks for rc  it fails, and does not go to the statement break; is it the problem of unicode in nt2k.

 
if ((rc == ERROR_SUCCESS) && 
                            (dwSize > 0) && 
                            (pPerf)->Signature[0] == (WCHAR)'P' && 
                            (pPerf)->Signature[1] == (WCHAR)'E' && 
                            (pPerf)->Signature[2] == (WCHAR)'R' && 
                            (pPerf)->Signature[3] == (WCHAR)'F' )
                {
                            break;
                 }
Probably this is the reason that you are getting errors. Try using conditional checks i.e. making  sure the kind of build you are dealing with ..

#ifdef _UNICODE
...
...

#else
.....
...

#endif

I did not try with unicode build.
hi naveen,
I tried, but still the same problem, the execution fails at the line tc ==ERROR_SUCCESS and does not break.