Exemplo n.º 1
0
/** 
 * 
 * Retrieve GDI resource usage for process.
 * 
 * @param       Nil
 * @return      bool - Return status.
 * @exception   Nil
 * @see         Nil
 * @since       1.0
 */
bool Process::ExtractGDIInfo()
{
    // Check whether process handle is valid
    if( !m_ahmProcess.IsValid() )
    {
        return false;
    }

    // Get resource usage count
    m_dwGDIObjs = GetGuiResources( m_ahmProcess, GR_GDIOBJECTS );
    m_dwUserObjs = GetGuiResources( m_ahmProcess, GR_USEROBJECTS );

    return GetLastError() == NO_ERROR;
}
Exemplo n.º 2
0
// Returns whether we should, at this time, use image surfaces instead of
// optimized platform-specific surfaces.
static bool ShouldUseImageSurfaces()
{
#if defined(USE_WIN_SURFACE)
  static const DWORD kGDIObjectsHighWaterMark = 7000;

  if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() ==
      gfxWindowsPlatform::RENDER_DIRECT2D) {
    return PR_TRUE;
  }

  // at 7000 GDI objects, stop allocating normal images to make sure
  // we never hit the 10k hard limit.
  // GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik
  DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
  if (count == 0 ||
      count > kGDIObjectsHighWaterMark)
  {
    // either something's broken (count == 0),
    // or we hit our high water mark; disable
    // image allocations for a bit.
    return PR_TRUE;
  }
#endif

  return PR_FALSE;
}
Exemplo n.º 3
0
BOOL  isGuiApp() {
	DWORD mypid;
	HANDLE myprocess;
	mypid = GetCurrentProcessId();
	myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid);
	return GetGuiResources(myprocess, 1) > 0;
	}
Exemplo n.º 4
0
void CCrashHandler::CollectMiscCrashInfo()
{  
  // Get crash time
  Utility::GetSystemTimeUTC(m_sCrashTime);

  HANDLE hCurProcess = GetCurrentProcess();

  // Determine the period of time the process is working.
  SYSTEMTIME CurTime;
  GetSystemTime(&CurTime);
  ULONG64 uCurTime = Utility::SystemTimeToULONG64(CurTime);
  ULONG64 uStartTime = Utility::SystemTimeToULONG64(m_AppStartTime);
  
  // Check that the application works for at least one minute before crash.
  // This might help to avoid cyclic error report generation when the applciation
  // crashes on startup.
  double dDiffTime = (double)(uCurTime-uStartTime)*10E-08;
  if(dDiffTime<60)
  {
    m_bAppRestart = FALSE; // Disable restart.
  }

  // Get number of GUI resources in use  
  m_dwGuiResources = GetGuiResources(hCurProcess, GR_GDIOBJECTS);
  
  // Determine if GetProcessHandleCount function available
  typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD);
  HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = 
    (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount");
  if(pfnGetProcessHandleCount!=NULL)
  {    
    // Get count of opened handles
    DWORD dwHandleCount = 0;
    BOOL bGetHandleCount = pfnGetProcessHandleCount(hCurProcess, &dwHandleCount);
    if(bGetHandleCount)
      m_dwProcessHandleCount = dwHandleCount;
    else
      m_dwProcessHandleCount = 0;
  }

  // Get memory usage info
  PROCESS_MEMORY_COUNTERS meminfo;
  BOOL bGetMemInfo = GetProcessMemoryInfo(hCurProcess, &meminfo, 
    sizeof(PROCESS_MEMORY_COUNTERS));
  if(bGetMemInfo)
  {    
    CString sMemUsage;
#ifdef _WIN64
    sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024);
#else
    sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024);
#endif 
    m_sMemUsage = sMemUsage;
  }

  // Get cursor position
  GetCursorPos(&m_ptCursorPos);
}
Exemplo n.º 5
0
void CCrashHandler::CollectMiscCrashInfo()
{  
  // Get crash time
  Utility::GetSystemTimeUTC(m_sCrashTime);

  // Get number of GUI resources in use
  HANDLE hCurProcess = GetCurrentProcess();
  m_dwGuiResources = GetGuiResources(hCurProcess, GR_GDIOBJECTS);
  
  // Determine if GetProcessHandleCount function available
  typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD);
  HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
  LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = 
    (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount");
  if(pfnGetProcessHandleCount!=NULL)
  {    
    // Get count of opened handles
    DWORD dwHandleCount = 0;
    BOOL bGetHandleCount = pfnGetProcessHandleCount(hCurProcess, &dwHandleCount);
    if(bGetHandleCount)
      m_dwProcessHandleCount = dwHandleCount;
    else
      m_dwProcessHandleCount = 0;
  }

  // Get memory usage info
  PROCESS_MEMORY_COUNTERS meminfo;
  BOOL bGetMemInfo = GetProcessMemoryInfo(hCurProcess, &meminfo, 
    sizeof(PROCESS_MEMORY_COUNTERS));
  if(bGetMemInfo)
  {    
    CString sMemUsage;
#ifdef _WIN64
    sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024);
#else
    sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024);
#endif 
    m_sMemUsage = sMemUsage;
  }

  // Get cursor position
  GetCursorPos(&m_ptCursorPos);
}
    // 使进程崩溃. 当位图分配失败时调用, 函数尝试确定失败的原因, 并在适当的地方触发
    // 崩溃. 这样我们可以更加清楚导致崩溃的原因. 函数需要传入位图的宽高, 这样可以试
    // 着创建位图定位错误.
    //
    // 注意在沙盒渲染器中, 函数调用GetProcessMemoryInfo()会导致崩溃, 因为此时会加载
    // load psapi.dll, 这么做是正确的, 但这种崩溃有可能让你摸不着头脑.
    void CrashForBitmapAllocationFailure(int w, int h)
    {
        // 存储扩展的错误信息到一个调试时容易找到的地方.
        struct
        {
            unsigned int last_error;
            unsigned int diag_error;
        } extended_error_info;
        extended_error_info.last_error = GetLastError();
        extended_error_info.diag_error = 0;

        // 如果位图太大, 有可能分配失败.
        // 使用64M像素=256MB, 每个像素4字节来检查.
        const __int64 kGinormousBitmapPxl = 64000000;
        CHECK(static_cast<__int64>(w) * static_cast<__int64>(h) <
            kGinormousBitmapPxl);

        // 每个进程GDI对象的上限是10K. 如果接近这个值, 很可能出现问题.
        const unsigned int kLotsOfGDIObjects = 9990;
        unsigned int num_gdi_objects = GetGuiResources(GetCurrentProcess(),
            GR_GDIOBJECTS);
        if(num_gdi_objects == 0)
        {
            extended_error_info.diag_error = GetLastError();
            CHECK(0);
        }
        CHECK(num_gdi_objects < kLotsOfGDIObjects);

        // 如果过度使用虚拟地址空间, 创建位图需要的内存可能不足.
        const SIZE_T kLotsOfMem = 1500000000; // 1.5GB.
        PROCESS_MEMORY_COUNTERS pmc;
        if(!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)))
        {
            extended_error_info.diag_error = GetLastError();
            CHECK(0);
        }
        CHECK(pmc.PagefileUsage < kLotsOfMem);

        // 其它的问题全部在这里崩溃.
        CHECK(0);
    }
PRBool
nsThebesImage::ShouldUseImageSurfaces()
{
#ifdef XP_WIN
    static const DWORD kGDIObjectsHighWaterMark = 7000;

    // at 7000 GDI objects, stop allocating normal images to make sure
    // we never hit the 10k hard limit.
    // GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik
    DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
    if (count == 0 ||
        count > kGDIObjectsHighWaterMark)
    {
        // either something's broken (count == 0),
        // or we hit our high water mark; disable
        // image allocations for a bit.
        return PR_TRUE;
    }
#endif

    return PR_FALSE;
}
Exemplo n.º 8
0
void CCrashInfoReader::CollectMiscCrashInfo(CErrorReportInfo& eri)
{   
    // Get crash time
    Utility::GetSystemTimeUTC(eri.m_sSystemTimeUTC);

    // Open parent process handle
    HANDLE hProcess = OpenProcess(
        PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, 
        FALSE, 
        m_dwProcessId);
		
    if(hProcess!=NULL)
    {	
		SIZE_T uBytesRead = 0;
		BYTE buff[1024];
		memset(&buff, 0, 1024);
		
		// Read exception information from process memory
		if(m_pExInfo!=NULL)
		{			
			if(ReadProcessMemory(hProcess, m_pExInfo, &buff, sizeof(EXCEPTION_POINTERS), &uBytesRead) &&
				uBytesRead==sizeof(EXCEPTION_POINTERS))
			{
				EXCEPTION_POINTERS* pExcPtrs = (EXCEPTION_POINTERS*)buff;

				if(pExcPtrs->ExceptionRecord!=NULL)
				{
					DWORD64 dwExcRecordAddr = (DWORD64)pExcPtrs->ExceptionRecord;
					if(ReadProcessMemory(hProcess, (LPCVOID)dwExcRecordAddr, &buff, sizeof(EXCEPTION_RECORD), &uBytesRead) &&
						uBytesRead==sizeof(EXCEPTION_RECORD))
					{
						EXCEPTION_RECORD* pExcRec = (EXCEPTION_RECORD*)buff;

						eri.m_dwExceptionAddress = (DWORD64)pExcRec->ExceptionAddress;
					}
				}				
			}
		}
		else
			eri.m_dwExceptionAddress = 0;

        // Get number of GUI resources in use  
        eri.m_dwGuiResources = GetGuiResources(hProcess, GR_GDIOBJECTS);

        // Determine if GetProcessHandleCount function available
        typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD);
        HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
        if(hKernel32!=NULL)
        {
            LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = 
                (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount");
            if(pfnGetProcessHandleCount!=NULL)
            {    
                // Get count of opened handles
                DWORD dwHandleCount = 0;
                BOOL bGetHandleCount = pfnGetProcessHandleCount(hProcess, &dwHandleCount);
                if(bGetHandleCount)
                    eri.m_dwProcessHandleCount = dwHandleCount;
                else
                    eri.m_dwProcessHandleCount = 0;
            }

            FreeLibrary(hKernel32);
            hKernel32=NULL;
        }

        // Get memory usage info
        PROCESS_MEMORY_COUNTERS meminfo;
        BOOL bGetMemInfo = GetProcessMemoryInfo(hProcess, &meminfo, 
            sizeof(PROCESS_MEMORY_COUNTERS));
        if(bGetMemInfo)
        {    
            CString sMemUsage;
#ifdef _WIN64
            sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024);
#else
            sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024);
#endif 
            eri.m_sMemUsage = sMemUsage;
        }

        // Determine the period of time the process is working.
        FILETIME CreationTime, ExitTime, KernelTime, UserTime;
        /*BOOL bGetTimes = */GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime);
        /*ATLASSERT(bGetTimes);*/
        SYSTEMTIME AppStartTime;
        FileTimeToSystemTime(&CreationTime, &AppStartTime);

        SYSTEMTIME CurTime;
        GetSystemTime(&CurTime);
        ULONG64 uCurTime = Utility::SystemTimeToULONG64(CurTime);
        ULONG64 uStartTime = Utility::SystemTimeToULONG64(AppStartTime);

        // Check that the application works for at least one minute before crash.
        // This might help to avoid cyclic error report generation when the applciation
        // crashes on startup.
        double dDiffTime = (double)(uCurTime-uStartTime)*10E-08;
        if(dDiffTime<60)
        {
            m_bAppRestart = FALSE; // Disable restart.
        } 
    }

    // Get operating system friendly name from registry.
    Utility::GetOSFriendlyName(eri.m_sOSName);

    // Determine if Windows is 64-bit.
    eri.m_bOSIs64Bit = Utility::IsOS64Bit();

    // Get geographic location.
    Utility::GetGeoLocation(eri.m_sGeoLocation);  
}
Exemplo n.º 9
0
VOID PhpUpdateProcessStatistics(
    _In_ HWND hwndDlg,
    _In_ PPH_PROCESS_ITEM ProcessItem,
    _In_ PPH_STATISTICS_CONTEXT Context
    )
{
    WCHAR timeSpan[PH_TIMESPAN_STR_LEN_1];

    SetDlgItemInt(hwndDlg, IDC_ZPRIORITY_V, ProcessItem->BasePriority, TRUE); // priority
    PhPrintTimeSpan(timeSpan, ProcessItem->KernelTime.QuadPart, PH_TIMESPAN_HMSM); // kernel time
    SetDlgItemText(hwndDlg, IDC_ZKERNELTIME_V, timeSpan);
    PhPrintTimeSpan(timeSpan, ProcessItem->UserTime.QuadPart, PH_TIMESPAN_HMSM); // user time
    SetDlgItemText(hwndDlg, IDC_ZUSERTIME_V, timeSpan);
    PhPrintTimeSpan(timeSpan,
        ProcessItem->KernelTime.QuadPart + ProcessItem->UserTime.QuadPart, PH_TIMESPAN_HMSM); // total time
    SetDlgItemText(hwndDlg, IDC_ZTOTALTIME_V, timeSpan);

    SetDlgItemText(hwndDlg, IDC_ZPRIVATEBYTES_V,
        PhaFormatSize(ProcessItem->VmCounters.PagefileUsage, -1)->Buffer); // private bytes (same as PrivateUsage)
    SetDlgItemText(hwndDlg, IDC_ZPEAKPRIVATEBYTES_V,
        PhaFormatSize(ProcessItem->VmCounters.PeakPagefileUsage, -1)->Buffer); // peak private bytes
    SetDlgItemText(hwndDlg, IDC_ZVIRTUALSIZE_V,
        PhaFormatSize(ProcessItem->VmCounters.VirtualSize, -1)->Buffer); // virtual size
    SetDlgItemText(hwndDlg, IDC_ZPEAKVIRTUALSIZE_V,
        PhaFormatSize(ProcessItem->VmCounters.PeakVirtualSize, -1)->Buffer); // peak virtual size
    SetDlgItemText(hwndDlg, IDC_ZPAGEFAULTS_V,
        PhaFormatUInt64(ProcessItem->VmCounters.PageFaultCount, TRUE)->Buffer); // page faults
    SetDlgItemText(hwndDlg, IDC_ZWORKINGSET_V,
        PhaFormatSize(ProcessItem->VmCounters.WorkingSetSize, -1)->Buffer); // working set
    SetDlgItemText(hwndDlg, IDC_ZPEAKWORKINGSET_V,
        PhaFormatSize(ProcessItem->VmCounters.PeakWorkingSetSize, -1)->Buffer); // peak working set

    SetDlgItemText(hwndDlg, IDC_ZIOREADS_V,
        PhaFormatUInt64(ProcessItem->IoCounters.ReadOperationCount, TRUE)->Buffer); // reads
    SetDlgItemText(hwndDlg, IDC_ZIOREADBYTES_V,
        PhaFormatSize(ProcessItem->IoCounters.ReadTransferCount, -1)->Buffer); // read bytes
    SetDlgItemText(hwndDlg, IDC_ZIOWRITES_V,
        PhaFormatUInt64(ProcessItem->IoCounters.WriteOperationCount, TRUE)->Buffer); // writes
    SetDlgItemText(hwndDlg, IDC_ZIOWRITEBYTES_V,
        PhaFormatSize(ProcessItem->IoCounters.WriteTransferCount, -1)->Buffer); // write bytes
    SetDlgItemText(hwndDlg, IDC_ZIOOTHER_V,
        PhaFormatUInt64(ProcessItem->IoCounters.OtherOperationCount, TRUE)->Buffer); // other
    SetDlgItemText(hwndDlg, IDC_ZIOOTHERBYTES_V,
        PhaFormatSize(ProcessItem->IoCounters.OtherTransferCount, -1)->Buffer); // read bytes

    SetDlgItemText(hwndDlg, IDC_ZHANDLES_V,
        PhaFormatUInt64(ProcessItem->NumberOfHandles, TRUE)->Buffer); // handles

    // Optional information
    if (!PH_IS_FAKE_PROCESS_ID(ProcessItem->ProcessId))
    {
        PPH_STRING peakHandles = NULL;
        PPH_STRING gdiHandles = NULL;
        PPH_STRING userHandles = NULL;
        PPH_STRING cycles = NULL;
        ULONG pagePriority = -1;
        IO_PRIORITY_HINT ioPriority = -1;
        PPH_STRING privateWs = NULL;
        PPH_STRING shareableWs = NULL;
        PPH_STRING sharedWs = NULL;
        BOOLEAN gotCycles = FALSE;
        BOOLEAN gotWsCounters = FALSE;

        if (ProcessItem->QueryHandle)
        {
            ULONG64 cycleTime;

            if (WindowsVersion >= WINDOWS_7)
            {
                PROCESS_HANDLE_INFORMATION handleInfo;

                if (NT_SUCCESS(NtQueryInformationProcess(
                    ProcessItem->QueryHandle,
                    ProcessHandleCount,
                    &handleInfo,
                    sizeof(PROCESS_HANDLE_INFORMATION),
                    NULL
                    )))
                {
                    peakHandles = PhaFormatUInt64(handleInfo.HandleCountHighWatermark, TRUE);
                }
            }

            gdiHandles = PhaFormatUInt64(GetGuiResources(ProcessItem->QueryHandle, GR_GDIOBJECTS), TRUE); // GDI handles
            userHandles = PhaFormatUInt64(GetGuiResources(ProcessItem->QueryHandle, GR_USEROBJECTS), TRUE); // USER handles

            if (WINDOWS_HAS_CYCLE_TIME &&
                NT_SUCCESS(PhGetProcessCycleTime(ProcessItem->QueryHandle, &cycleTime)))
            {
                cycles = PhaFormatUInt64(cycleTime, TRUE);
                gotCycles = TRUE;
            }

            if (WindowsVersion >= WINDOWS_VISTA)
            {
                PhGetProcessPagePriority(ProcessItem->QueryHandle, &pagePriority);
                PhGetProcessIoPriority(ProcessItem->QueryHandle, &ioPriority);
            }
        }

        if (Context->ProcessHandle)
        {
            PH_PROCESS_WS_COUNTERS wsCounters;

            if (NT_SUCCESS(PhGetProcessWsCounters(Context->ProcessHandle, &wsCounters)))
            {
                privateWs = PhaFormatSize((ULONG64)wsCounters.NumberOfPrivatePages * PAGE_SIZE, -1);
                shareableWs = PhaFormatSize((ULONG64)wsCounters.NumberOfShareablePages * PAGE_SIZE, -1);
                sharedWs = PhaFormatSize((ULONG64)wsCounters.NumberOfSharedPages * PAGE_SIZE, -1);
                gotWsCounters = TRUE;
            }
        }

        if (WindowsVersion >= WINDOWS_7)
        {
            if (!gotCycles)
                cycles = PhaFormatUInt64(ProcessItem->CycleTimeDelta.Value, TRUE);
            if (!gotWsCounters)
                privateWs = PhaFormatSize(ProcessItem->WorkingSetPrivateSize, -1);
        }

        if (WindowsVersion >= WINDOWS_7)
            SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, PhGetStringOrDefault(peakHandles, L"Unknown"));
        else
            SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, L"N/A");

        SetDlgItemText(hwndDlg, IDC_ZGDIHANDLES_V, PhGetStringOrDefault(gdiHandles, L"Unknown"));
        SetDlgItemText(hwndDlg, IDC_ZUSERHANDLES_V, PhGetStringOrDefault(userHandles, L"Unknown"));
        SetDlgItemText(hwndDlg, IDC_ZCYCLES_V,
            PhGetStringOrDefault(cycles, WINDOWS_HAS_CYCLE_TIME ? L"Unknown" : L"N/A"));

        if (WindowsVersion >= WINDOWS_VISTA)
        {
            if (pagePriority != -1 && pagePriority <= MEMORY_PRIORITY_NORMAL)
                SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, PhPagePriorityNames[pagePriority]);
            else
                SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"Unknown");

            if (ioPriority != -1 && ioPriority < MaxIoPriorityTypes)
                SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, PhIoPriorityHintNames[ioPriority]);
            else
                SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"Unknown");
        }
        else
        {
            SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"N/A");
            SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"N/A");
        }

        SetDlgItemText(hwndDlg, IDC_ZPRIVATEWS_V, PhGetStringOrDefault(privateWs, L"Unknown"));
        SetDlgItemText(hwndDlg, IDC_ZSHAREABLEWS_V, PhGetStringOrDefault(shareableWs, L"Unknown"));
        SetDlgItemText(hwndDlg, IDC_ZSHAREDWS_V, PhGetStringOrDefault(sharedWs, L"Unknown"));
    }
    else
    {
        SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZGDIHANDLES_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZUSERHANDLES_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZCYCLES_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZPRIVATEWS_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZSHAREABLEWS_V, L"N/A");
        SetDlgItemText(hwndDlg, IDC_ZSHAREDWS_V, L"N/A");
    }
}
Exemplo n.º 10
0
ULONG
PerfUpdateInformation(
	VOID
	)
{
	ULONG i;
    ULONG64 TotalTime;
	PLIST_ENTRY ListEntry;
	LIST_ENTRY ListHead;
	PBSP_PROCESS Process;
	PPERF_INFORMATION Information;
	NTSTATUS Status;
	LIST_ENTRY FreeListHead;

    RtlZeroMemory(&PerfCpuTotal, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));

    Status = (*NtQuerySystemInformation)(SystemProcessorPerformanceInformation,
									     PerfCpuInformation,
									     PerfCpuInformationLength,
									     NULL);
	ASSERT(Status == STATUS_SUCCESS);

    for (i = 0; i < BspProcessorNumber; i++) {

        PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Cpu = &PerfCpuInformation[i];

        Cpu->KernelTime.QuadPart -= Cpu->IdleTime.QuadPart + Cpu->DpcTime.QuadPart + Cpu->InterruptTime.QuadPart;

        PerfCpuTotal.DpcTime.QuadPart += Cpu->DpcTime.QuadPart;
        PerfCpuTotal.IdleTime.QuadPart += Cpu->IdleTime.QuadPart;
        PerfCpuTotal.InterruptCount += Cpu->InterruptCount;
        PerfCpuTotal.InterruptTime.QuadPart += Cpu->InterruptTime.QuadPart;
        PerfCpuTotal.KernelTime.QuadPart += Cpu->KernelTime.QuadPart;
        PerfCpuTotal.UserTime.QuadPart += Cpu->UserTime.QuadPart;

        PerfUpdateDelta(&PerfCpusKernelDelta[i], Cpu->KernelTime.QuadPart);
        PerfUpdateDelta(&PerfCpusUserDelta[i], Cpu->UserTime.QuadPart);
        PerfUpdateDelta(&PerfCpusOtherDelta[i],
			             Cpu->IdleTime.QuadPart + 
						 Cpu->DpcTime.QuadPart + 
						 Cpu->InterruptTime.QuadPart);

        TotalTime = PerfCpusKernelDelta[i].Delta + PerfCpusUserDelta[i].Delta + PerfCpusOtherDelta[i].Delta;

        if (TotalTime != 0) {
            PerfCpusKernelUsage[i] = (FLOAT)PerfCpusKernelDelta[i].Delta / TotalTime;
            PerfCpusUserUsage[i] = (FLOAT)PerfCpusUserDelta[i].Delta / TotalTime;
        }
        else {
            PerfCpusKernelUsage[i] = 0;
            PerfCpusUserUsage[i] = 0;
        }
	}

    PerfUpdateDelta(&PerfCpuKernelDelta, PerfCpuTotal.KernelTime.QuadPart);
    PerfUpdateDelta(&PerfCpuUserDelta, PerfCpuTotal.UserTime.QuadPart);
	PerfUpdateDelta(&PerfCpuOtherDelta, 
		             PerfCpuTotal.IdleTime.QuadPart + 
					 PerfCpuTotal.DpcTime.QuadPart  + 
					 PerfCpuTotal.InterruptTime.QuadPart);

    TotalTime = PerfCpuKernelDelta.Delta + PerfCpuUserDelta.Delta + PerfCpuOtherDelta.Delta;

    if (TotalTime) {
        PerfCpuKernelUsage = (FLOAT)PerfCpuKernelDelta.Delta / TotalTime;
        PerfCpuUserUsage = (FLOAT)PerfCpuUserDelta.Delta / TotalTime;
    }
    else {
        PerfCpuKernelUsage = 0;
        PerfCpuUserUsage = 0;
	}

    PerfTotalTime = TotalTime;
	
	InitializeListHead(&ListHead);
	InitializeListHead(&FreeListHead);

	BspQueryProcessList(&ListHead);

	ListEntry = PerfListHead.Flink;
	while (ListEntry != &PerfListHead) {

		HANDLE ProcessHandle;
		PROCESS_MEMORY_COUNTERS_EX MemoryCounters;
		IO_COUNTERS IoCounters;

		Information = CONTAINING_RECORD(ListEntry, PERF_INFORMATION, ListEntry);
		Process = BspQueryProcessById(&ListHead, Information->ProcessId);

		if (!Process) {

			ASSERT(Information->ProcessId != 0);

			ListEntry = ListEntry->Flink;
			Information->Terminated = TRUE;
			RemoveEntryList(&Information->ListEntry);	
			InsertTailList(&FreeListHead, &Information->ListEntry);
			
			if (!PerfFirstRun) {
				PerfPushUpdateToConsumers(Information);
			}

			continue;
		}

		PerfUpdateDelta(&Information->CpuKernelDelta, Process->KernelTime.QuadPart);
		PerfUpdateDelta(&Information->CpuUserDelta, Process->UserTime.QuadPart);

		if (PerfTotalTime != 0) {
			Information->CpuKernelUsage = (FLOAT)Information->CpuKernelDelta.Delta / PerfTotalTime;
			Information->CpuUserUsage = (FLOAT)Information->CpuUserDelta.Delta / PerfTotalTime;
			Information->CpuTotalUsage = (FLOAT)Information->CpuKernelUsage + Information->CpuUserUsage;
		} else {
			Information->CpuKernelUsage = 0;
			Information->CpuUserUsage = 0;
			Information->CpuTotalUsage = 0;
		}

		ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Process->ProcessId);
		GetProcessMemoryInfo(ProcessHandle, (PPROCESS_MEMORY_COUNTERS)&MemoryCounters, 
			                 sizeof(MemoryCounters));

		GetProcessIoCounters(ProcessHandle, &IoCounters);

		PerfUpdateDelta(&Information->PrivateDelta, MemoryCounters.PrivateUsage);
		PerfUpdateDelta(&Information->WorkingSetDelta, MemoryCounters.WorkingSetSize);
		Information->WorkingSetPeak = MemoryCounters.PeakWorkingSetSize;

		PerfUpdateDelta(&Information->VirtualDelta, Process->VirtualBytes);
		PerfUpdateDelta(&Information->IoReadDelta, IoCounters.ReadTransferCount);
		PerfUpdateDelta(&Information->IoWriteDelta, IoCounters.WriteTransferCount);

		Information->KernelHandles = Process->KernelHandleCount;
		
		Information->UserHandles = GetGuiResources(ProcessHandle, GR_USEROBJECTS);
		Information->GdiHandles = GetGuiResources(ProcessHandle, GR_GDIOBJECTS);
		CloseHandle(ProcessHandle);

		if (Information->KernelHandlesPeak < Information->KernelHandles) {
			Information->KernelHandlesPeak = Information->KernelHandles;
		}

		if (Information->UserHandlesPeak < Information->UserHandles) {
			Information->UserHandlesPeak = Information->UserHandles;
		}

		if (Information->GdiHandlesPeak < Information->GdiHandles) {
			Information->GdiHandlesPeak = Information->GdiHandles;
		}

		//
		// Notify all performance data consumers via registered callback objects
		//
		
		if (!PerfFirstRun) {
			PerfPushUpdateToConsumers(Information);
		}

		ListEntry = ListEntry->Flink;
	}
	
	//
	// Deallocate died PERF_INFORMATION structures
	//

	while (IsListEmpty(&FreeListHead) != TRUE) {
		ListEntry = RemoveHeadList(&FreeListHead);
		Information = CONTAINING_RECORD(ListEntry, PERF_INFORMATION, ListEntry);
		BspFree(Information);
	}
	
	BspFreeProcessList(&ListHead);

	if (PerfFirstRun) {
		PerfFirstRun = FALSE;
	}

	return 0;
}
Exemplo n.º 11
0
/*
	The following block is copied from the Java source code. It documents the counters array.

	 * @param counters the results are returned in this array.
	 * <ol>
	 * <li>working set in bytes for this process
	 * <li>peak working set in bytes for this process
	 * <li>elapsed time in milliseconds
	 * <li>user time in milliseconds
	 * <li>kernel time in milliseconds
	 * <li>page faults for the process
	 * <li>commit charge total in bytes (working set for the entire machine). On some 
	 * machines we have problems getting this value so we return -1 in that case.
	 * <li>number of GDI objects in the process
	 * <li>number of USER objects in the process
	 * <li>number of open handles in the process. returns -1 if this information is not available
	 * <li>Number of read operations
	 * <li>Number of write operations
	 * <li>Number of bytes read
	 * <li>Number of bytes written
	 * </ol>

*/
JNIEXPORT jboolean JNICALL Java_org_eclipse_perfmsr_core_PerformanceMonitor_nativeGetPerformanceCounters
  (JNIEnv * jniEnv, jclass jniClass, jlongArray counters)
{
	FILETIME creationTime, exitTime, kernelTime, userTime, systemTime;
	ULARGE_INTEGER uliCreation, uliSystem, uliKernel, uliUser;
	ULONGLONG diff;
	IO_COUNTERS ioCounters;

	jboolean result = TRUE;
	jsize len = (*jniEnv)->GetArrayLength(jniEnv, counters);
	jlong *body = (*jniEnv)->GetLongArrayElements(jniEnv, counters, 0);
	HANDLE me = GetCurrentProcess();
	PROCESS_MEMORY_COUNTERS memCounters;
	DWORD cb = sizeof(PROCESS_MEMORY_COUNTERS);
	BOOL rc = GetProcessMemoryInfo(me, &memCounters, cb);
	if (rc != 0)
	{
		body[0] = memCounters.WorkingSetSize;
		body[1] = memCounters.PeakWorkingSetSize;
		body[5] = memCounters.PageFaultCount;
	}
	else
	{
		handleSystemError(jniEnv);
		return FALSE;
	}

	if (!GetProcessTimes(me, &creationTime, &exitTime, &kernelTime, &userTime))
	{
		handleSystemError(jniEnv);
		return FALSE;
	}
	GetSystemTimeAsFileTime(&systemTime);

	memcpy(&uliCreation, &creationTime, sizeof(uliCreation));  
	memcpy(&uliSystem, &systemTime, sizeof(uliSystem));
	memcpy(&uliKernel, &kernelTime, sizeof(uliSystem));
	memcpy(&uliUser, &userTime, sizeof(ULARGE_INTEGER));
	diff = uliSystem.QuadPart - uliCreation.QuadPart;
	body[2] = diff / 10000;
	body[3] = uliUser.QuadPart / 10000;
	body[4] = uliKernel.QuadPart / 10000;
	body[6] = getTotalCommitted(jniEnv);

	body[7] = GetGuiResources(me, GR_GDIOBJECTS);
	body[8] = GetGuiResources(me, GR_USEROBJECTS);
	body[9] = getHandleCount(jniEnv, me);

	if (!GetProcessIoCounters(me, &ioCounters))
	{
		handleSystemError(jniEnv);
		return FALSE;
	}
	body[10] = ioCounters.ReadOperationCount;
	body[11] = ioCounters.WriteOperationCount;
	body[12] = ioCounters.ReadTransferCount;
	body[13] = ioCounters.WriteTransferCount;

	(*jniEnv)->ReleaseLongArrayElements(jniEnv, counters, body, 0);

	return result;
}
Exemplo n.º 12
0
PLUGIN_EXPORT double Update(void* data)
{
	MeasureData* measure = (MeasureData*)data;

	// count the existing window objects
	if (measure->type == WINDOW_COUNT)
	{
		g_WindowCount = 0;
		EnumChildWindows(NULL, EnumWindowProc, 0);
		return g_WindowCount;
	}

	const WCHAR* processName = measure->process.c_str();
	bool name = !measure->process.empty();

	DWORD aProcesses[1024];
	DWORD bytesNeeded;
	WCHAR buffer[1024];
	HMODULE hMod[1024];
	DWORD cbNeeded;

	if (!EnumProcesses(aProcesses, sizeof(aProcesses), &bytesNeeded))
	{
		return 0.0;
	}

	// step through the running processes
	DWORD flags = PROCESS_QUERY_INFORMATION;

	if (name)
	{
		flags |= PROCESS_VM_READ;
	}

	UINT resourceCount = 0;
	for (UINT i = 0, isize = bytesNeeded / sizeof(DWORD); i < isize; ++i)
	{
		HANDLE hProcess = OpenProcess(flags, true, aProcesses[i]);
		if (hProcess != NULL)
		{
			if (name)
			{
				if (EnumProcessModules(hProcess, hMod, sizeof(hMod), &cbNeeded))
				{
					if (GetModuleBaseName(hProcess, hMod[0], buffer, sizeof(buffer)))
					{
						if (_wcsicmp(buffer, processName) != 0)
						{
							CloseHandle(hProcess);
							continue;
						}
					}
					else
					{
						CloseHandle(hProcess);
						continue;
					}
				}
				else
				{
					CloseHandle(hProcess);
					continue;
				}
			}

			if (measure->type == GDI_COUNT)
			{
				resourceCount += GetGuiResources(hProcess, GR_GDIOBJECTS);
			}
			else if (measure->type == USER_COUNT)
			{
				resourceCount += GetGuiResources(hProcess, GR_USEROBJECTS);
			}
			else if (measure->type == HANDLE_COUNT)
			{
				DWORD tempHandleCount = 0;
				GetProcessHandleCount(hProcess, &tempHandleCount);
				resourceCount += tempHandleCount;
			}
		}
		CloseHandle(hProcess);
	}

	return resourceCount;
}
Exemplo n.º 13
0
void PerfDataRefresh(void)
{
    ULONG                                      ulSize;
    NTSTATUS                                   status;
    LPBYTE                                     pBuffer;
    ULONG                                      BufferSize;
    PSYSTEM_PROCESS_INFORMATION                pSPI;
    PPERFDATA                                  pPDOld;
    ULONG                                      Idx, Idx2;
    HANDLE                                     hProcess;
    HANDLE                                     hProcessToken;
    SYSTEM_PERFORMANCE_INFORMATION             SysPerfInfo;
    SYSTEM_TIMEOFDAY_INFORMATION               SysTimeInfo;
    SYSTEM_FILECACHE_INFORMATION               SysCacheInfo;
    LPBYTE                                     SysHandleInfoData;
    PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION  SysProcessorTimeInfo;
    double                                     CurrentKernelTime;
    PSECURITY_DESCRIPTOR                       ProcessSD;
    PSID                                       ProcessUser;
    ULONG                                      Buffer[64]; /* must be 4 bytes aligned! */
    ULONG                                      cwcUserName;

    /* Get new system time */
    status = NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), NULL);
    if (!NT_SUCCESS(status))
        return;

    /* Get new CPU's idle time */
    status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL);
    if (!NT_SUCCESS(status))
        return;

    /* Get system cache information */
    status = NtQuerySystemInformation(SystemFileCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL);
    if (!NT_SUCCESS(status))
        return;

    /* Get processor time information */
    SysProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors);
    status = NtQuerySystemInformation(SystemProcessorPerformanceInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors, &ulSize);

    if (!NT_SUCCESS(status))
    {
        if (SysProcessorTimeInfo != NULL)
            HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo);
        return;
    }

    /* Get handle information
     * We don't know how much data there is so just keep
     * increasing the buffer size until the call succeeds
     */
    BufferSize = 0;
    do
    {
        BufferSize += 0x10000;
        SysHandleInfoData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize);

        status = NtQuerySystemInformation(SystemHandleInformation, SysHandleInfoData, BufferSize, &ulSize);

        if (status == STATUS_INFO_LENGTH_MISMATCH) {
            HeapFree(GetProcessHeap(), 0, SysHandleInfoData);
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    /* Get process information
     * We don't know how much data there is so just keep
     * increasing the buffer size until the call succeeds
     */
    BufferSize = 0;
    do
    {
        BufferSize += 0x10000;
        pBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize);

        status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize);

        if (status == STATUS_INFO_LENGTH_MISMATCH) {
            HeapFree(GetProcessHeap(), 0, pBuffer);
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    EnterCriticalSection(&PerfDataCriticalSection);

    /*
     * Save system performance info
     */
    memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION));

    /*
     * Save system cache info
     */
    memcpy(&SystemCacheInfo, &SysCacheInfo, sizeof(SYSTEM_FILECACHE_INFORMATION));

    /*
     * Save system processor time info
     */
    if (SystemProcessorTimeInfo) {
        HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo);
    }
    SystemProcessorTimeInfo = SysProcessorTimeInfo;

    /*
     * Save system handle info
     */
    memcpy(&SystemHandleInfo, SysHandleInfoData, sizeof(SYSTEM_HANDLE_INFORMATION));
    HeapFree(GetProcessHeap(), 0, SysHandleInfoData);

    for (CurrentKernelTime=0, Idx=0; Idx<(ULONG)SystemBasicInfo.NumberOfProcessors; Idx++) {
        CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime);
        CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime);
        CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime);
    }

    /* If it's a first call - skip idle time calcs */
    if (liOldIdleTime.QuadPart != 0) {
        /*  CurrentValue = NewValue - OldValue */
        dbIdleTime = Li2Double(SysPerfInfo.IdleProcessTime) - Li2Double(liOldIdleTime);
        dbKernelTime = CurrentKernelTime - OldKernelTime;
        dbSystemTime = Li2Double(SysTimeInfo.CurrentTime) - Li2Double(liOldSystemTime);

        /*  CurrentCpuIdle = IdleTime / SystemTime */
        dbIdleTime = dbIdleTime / dbSystemTime;
        dbKernelTime = dbKernelTime / dbSystemTime;

        /*  CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */
        dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
        dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
    }

    /* Store new CPU's idle and system time */
    liOldIdleTime = SysPerfInfo.IdleProcessTime;
    liOldSystemTime = SysTimeInfo.CurrentTime;
    OldKernelTime = CurrentKernelTime;

    /* Determine the process count
     * We loop through the data we got from NtQuerySystemInformation
     * and count how many structures there are (until RelativeOffset is 0)
     */
    ProcessCountOld = ProcessCount;
    ProcessCount = 0;
    pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
    while (pSPI) {
        ProcessCount++;
        if (pSPI->NextEntryOffset == 0)
            break;
        pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
    }

    /* Now alloc a new PERFDATA array and fill in the data */
    pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PERFDATA) * ProcessCount);

    pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
    for (Idx=0; Idx<ProcessCount; Idx++) {
        /* Get the old perf data for this process (if any) */
        /* so that we can establish delta values */
        pPDOld = NULL;
        if (pPerfDataOld) {
            for (Idx2=0; Idx2<ProcessCountOld; Idx2++) {
                if (pPerfDataOld[Idx2].ProcessId == pSPI->UniqueProcessId) {
                    pPDOld = &pPerfDataOld[Idx2];
                    break;
                }
            }
        }

        if (pSPI->ImageName.Buffer) {
            /* Don't assume a UNICODE_STRING Buffer is zero terminated: */
            int len = pSPI->ImageName.Length / 2;
            /* Check against max size and allow for terminating zero (already zeroed): */
            if(len >= MAX_PATH)len=MAX_PATH - 1;
            wcsncpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer, len);
        } else {
            LoadStringW(hInst, IDS_IDLE_PROCESS, pPerfData[Idx].ImageName,
                       sizeof(pPerfData[Idx].ImageName) / sizeof(pPerfData[Idx].ImageName[0]));
        }

        pPerfData[Idx].ProcessId = pSPI->UniqueProcessId;

        if (pPDOld)    {
            double    CurTime = Li2Double(pSPI->KernelTime) + Li2Double(pSPI->UserTime);
            double    OldTime = Li2Double(pPDOld->KernelTime) + Li2Double(pPDOld->UserTime);
            double    CpuTime = (CurTime - OldTime) / dbSystemTime;
            CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */
            pPerfData[Idx].CPUUsage = (ULONG)CpuTime;
        }
        pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart;
        pPerfData[Idx].WorkingSetSizeBytes = pSPI->WorkingSetSize;
        pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSize;
        if (pPDOld)
            pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->WorkingSetSize - (LONG)pPDOld->WorkingSetSizeBytes);
        else
            pPerfData[Idx].WorkingSetSizeDelta = 0;
        pPerfData[Idx].PageFaultCount = pSPI->PageFaultCount;
        if (pPDOld)
            pPerfData[Idx].PageFaultCountDelta = labs((LONG)pSPI->PageFaultCount - (LONG)pPDOld->PageFaultCount);
        else
            pPerfData[Idx].PageFaultCountDelta = 0;
        pPerfData[Idx].VirtualMemorySizeBytes = pSPI->VirtualSize;
        pPerfData[Idx].PagedPoolUsagePages = pSPI->QuotaPeakPagedPoolUsage;
        pPerfData[Idx].NonPagedPoolUsagePages = pSPI->QuotaPeakNonPagedPoolUsage;
        pPerfData[Idx].BasePriority = pSPI->BasePriority;
        pPerfData[Idx].HandleCount = pSPI->HandleCount;
        pPerfData[Idx].ThreadCount = pSPI->NumberOfThreads;
        pPerfData[Idx].SessionId = pSPI->SessionId;
        pPerfData[Idx].UserName[0] = UNICODE_NULL;
        pPerfData[Idx].USERObjectCount = 0;
        pPerfData[Idx].GDIObjectCount = 0;
        ProcessUser = SystemUserSid;
        ProcessSD = NULL;

        if (pSPI->UniqueProcessId != NULL) {
            hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, PtrToUlong(pSPI->UniqueProcessId));
            if (hProcess) {
                /* don't query the information of the system process. It's possible but
                   returns Administrators as the owner of the process instead of SYSTEM */
                if (pSPI->UniqueProcessId != (HANDLE)0x4)
                {
                    if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
                    {
                        DWORD RetLen = 0;
                        BOOL Ret;

                        Ret = GetTokenInformation(hProcessToken, TokenUser, (LPVOID)Buffer, sizeof(Buffer), &RetLen);
                        CloseHandle(hProcessToken);

                        if (Ret)
                            ProcessUser = ((PTOKEN_USER)Buffer)->User.Sid;
                        else
                            goto ReadProcOwner;
                    }
                    else
                    {
ReadProcOwner:
                        GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, &ProcessUser, NULL, NULL, NULL, &ProcessSD);
                    }

                    pPerfData[Idx].USERObjectCount = GetGuiResources(hProcess, GR_USEROBJECTS);
                    pPerfData[Idx].GDIObjectCount = GetGuiResources(hProcess, GR_GDIOBJECTS);
                }

                GetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters);
                CloseHandle(hProcess);
            } else {
                goto ClearInfo;
            }
        } else {
ClearInfo:
            /* clear information we were unable to fetch */
            ZeroMemory(&pPerfData[Idx].IOCounters, sizeof(IO_COUNTERS));
        }

        cwcUserName = sizeof(pPerfData[0].UserName) / sizeof(pPerfData[0].UserName[0]);
        CachedGetUserFromSid(ProcessUser, pPerfData[Idx].UserName, &cwcUserName);

        if (ProcessSD != NULL)
        {
            LocalFree((HLOCAL)ProcessSD);
        }

        pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart;
        pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart;
        pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset);
    }
    HeapFree(GetProcessHeap(), 0, pBuffer);
    if (pPerfDataOld) {
        HeapFree(GetProcessHeap(), 0, pPerfDataOld);
    }
    pPerfDataOld = pPerfData;
    LeaveCriticalSection(&PerfDataCriticalSection);
}