www.pudn.com > Process_Mo18292312142004.rar > ProcList.cpp
/*******************************************************
This file is part of Process Monitor.
Copyright (c) 2004 by Michel van Kerkhof, ( michel000@planet.nl http://home.wxs.nl/~wijk0550/ )
For more information consult the Readme file.
This program is free software; you can redistribute it
and/or modify it under the terms of the GNU
General Public License as published by the Free
Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU
General Public License along with this program;
if not, write to:
the Free Software Foundation, Inc.,
59 Temple Place,
Suite 330, Boston,
MA 02111-1307 USA
*******************************************************
If you like my work and you have a job for me please contact me at: michel000@planet.nl
*******************************************************/
#include "includes.h"
extern NTAPIS NtApi;
//Changed State
const BYTE SET_ALL = 1<<1;
const BYTE SET_CPU = 1<<2;
const BYTE SET_RAM = 1<<3;
const BYTE SET_PRI = 1<<4;
const BYTE SET_WTC = 1<<5;
const BYTE SET_RTC = 1<<6;
/*
Function Description:
Constructor for CProcList
Arguments:
OUT dwRet, 1 = success 0 = error
IN hWnd, Handle to main window
Returns:
void
*/
CProcList::CProcList(DWORD *dwRet,HWND hWnd)
{
*dwRet=0;
if (!NtApi.fCachedGetUserFromSid ||
!NtApi.fWinStationGetProcessSid ||
!NtApi.fNtQuerySystemInformation
) {
return;
}
m_hMain=hWnd;
m_pBuffer=NULL;
m_dwBufferSize=0;
m_pList=NULL;
m_dwListSize=0;
m_bUpdateInProgress=false;
m_bAccessToBuffer=false;
#ifdef CHECK_LAG
m_bLagging=false;
#endif
*dwRet=1;
return;
}
/*
Function Description:
Gets the owner name for a process and puts it in m_pList
called by: UpdateProcList
Arguments:
IN dwItem, item number in processlist to get ownername for
Returns:
void
*/
int CProcList::SetOwnerName(DWORD dwItem)
{
PSID pSid = NULL;
DWORD dwSize = 0;
try {
if (NtApi.fWinStationGetProcessSid(NULL,m_pList[dwItem]->dwPID,*((FILETIME *)&m_pList[dwItem]->ftStartTime),(PBYTE)pSid,&dwSize) != 0) throw(ERR_NTAPI);
pSid = (PSID) new BYTE[dwSize];
if (pSid == NULL) throw(ERR_NO_MEMORY);
if (NtApi.fWinStationGetProcessSid(NULL,m_pList[dwItem]->dwPID,*((FILETIME *)&m_pList[dwItem]->ftStartTime), (PBYTE)pSid ,&dwSize) == 0) throw(ERR_NTAPI);
unsigned short OwnerName[MAX_PATH-1];
DWORD dwSize = MAX_PATH-1;
NtApi.fCachedGetUserFromSid(pSid,OwnerName,&dwSize);
int iSize= WideCharToMultiByte
(
CP_ACP,
0,
(wchar_t *)OwnerName,
dwSize+1,
m_pList[dwItem]->pOwnerName,
MAX_PATH,
NULL,
NULL
);
if (iSize == 0) throw(ERR_UNKNOWN);
throw(ERR_SUCCESS);
}
catch (int ErrorCode) {
if (pSid) delete pSid;
return ErrorCode;
}
}
/*
Function Description:
Creates a buffer and fills it with SystemProcessInformation
called by UpdateProcList
Arguments:
Returns:
int errorcode (ERR_SUCCESS if successfull)
*/
int CProcList::GetNewBuffer()
{
if (m_pBuffer) VirtualFree(m_pBuffer, 0, MEM_RELEASE);
m_dwBufferSize=4096;
m_pBuffer = VirtualAlloc(NULL,m_dwBufferSize,MEM_COMMIT,PAGE_READWRITE);
if (!m_pBuffer)
return ERR_NO_MEMORY;
NTSTATUS ntStatus;
do {
ntStatus = NtApi.fNtQuerySystemInformation(
SystemProcessInformation,
m_pBuffer,
m_dwBufferSize,
NULL
);
if (ntStatus == 0)
break;//Success
if (ntStatus != STATUS_INFO_LENGTH_MISMATCH)
return -1;
//Create a Bigger Buffer
VirtualFree(m_pBuffer, 0, MEM_RELEASE);
m_pBuffer=NULL;
m_dwBufferSize += 4096;
m_pBuffer = VirtualAlloc(NULL,m_dwBufferSize,MEM_COMMIT,PAGE_READWRITE);
if (m_pBuffer == NULL)
return ERR_NO_MEMORY;
} while(1);
return ERR_SUCCESS;
}
/*
Function Description:
Fills m_pList with process info
called by: CWindow::Timers CWindow::ProcessListView
Arguments:
IN CWnd, pointer to a CWindow class
Returns:
int errorcode (ERR_SUCCESS if successfull)
*/
int CProcList::UpdateProcList(CWindow *CWnd)
{
if (m_bUpdateInProgress || m_bAccessToBuffer) return ERR_PLEASE_WAITH;
m_bUpdateInProgress=true;
int iError;
iError=GetNewBuffer();
if (iError != ERR_SUCCESS) return iError;
SYSTEM_PROCESS_INFORMATION *pTemp;
DWORD iOffset=0,
dwCount=0;
LARGE_INTEGER TotalTime;
TotalTime.QuadPart=0;
m_OldListSize=m_dwListSize;
do {
pTemp = (SYSTEM_PROCESS_INFORMATION *)&((LPBYTE)m_pBuffer)[iOffset];
if (pTemp->UniqueProcessId != NULL || pTemp->NumberOfThreads != 0) {
LARGE_INTEGER TimeDelta,
Time;
if (m_dwListSize <= dwCount) {
m_pList=(PROCESSLIST **)realloc(m_pList,sizeof(PROCESSLIST *) * (dwCount + 1));
if (m_pList == NULL) return ERR_NO_MEMORY;
m_pList[dwCount]=(PROCESSLIST *)malloc(sizeof(PROCESSLIST));
if (m_pList[dwCount] == NULL) return ERR_NO_MEMORY;
m_pList[dwCount]->dwPID=-1;
m_pList[dwCount]->ftStartTime.QuadPart=0;
m_dwListSize++;
}
m_pList[dwCount]->Changed=0;
Time.QuadPart = pTemp->UserTime.QuadPart + pTemp->KernelTime.QuadPart;
if ((DWORD)pTemp->UniqueProcessId == m_pList[dwCount]->dwPID && pTemp->CreateTime.QuadPart == m_pList[dwCount]->ftStartTime.QuadPart) {
m_pList[dwCount]->Changed=0;
TimeDelta.QuadPart = Time.QuadPart - m_pList[dwCount]->CpuOldTime.QuadPart;
m_pList[dwCount]->CpuOldTime.QuadPart = Time.QuadPart;
m_pList[dwCount]->CpuDeltaTime.QuadPart = TimeDelta.QuadPart;
if (m_pList[dwCount]->dwRam != pTemp->WorkingSetSize) {
m_pList[dwCount]->Changed |= SET_RAM;
m_pList[dwCount]->dwRam = pTemp->WorkingSetSize;
}
if (m_pList[dwCount]->BasePriority != pTemp->BasePriority) {
m_pList[dwCount]->BasePriority = pTemp->BasePriority;
m_pList[dwCount]->Changed |= SET_PRI;
}
if (m_pList[dwCount]->ReadTransferCount.QuadPart != pTemp->ReadTransferCount.QuadPart) {
m_pList[dwCount]->ReadTransferCount.QuadPart = pTemp->ReadTransferCount.QuadPart;
m_pList[dwCount]->Changed |= SET_RTC;
}
if (m_pList[dwCount]->WriteTransferCount.QuadPart != pTemp->WriteTransferCount.QuadPart) {
m_pList[dwCount]->WriteTransferCount.QuadPart = pTemp->WriteTransferCount.QuadPart;
m_pList[dwCount]->Changed |= SET_WTC;
}
}
else {
//new Process fill the list
m_pList[dwCount]->dwPID = (DWORD)pTemp->UniqueProcessId;
m_pList[dwCount]->dwOwnerPID = (DWORD)pTemp->InheritedFromUniqueProcessId;
m_pList[dwCount]->ftStartTime = pTemp->CreateTime;
m_pList[dwCount]->dwRam = pTemp->WorkingSetSize;
m_pList[dwCount]->BasePriority= pTemp->BasePriority;
if (m_pList[dwCount]->dwPID == 0) { //idle process
strcpy(m_pList[dwCount]->pProcessName,"System Idle Process");
strcpy(m_pList[dwCount]->pOwnerName,"SYSTEM");
}
else {
int iSize;
iSize = WideCharToMultiByte
(
CP_ACP,
0,
(wchar_t *)pTemp->ImageName.Buffer,
-1,
m_pList[dwCount]->pProcessName,
MAX_PATH,
NULL,
NULL
);
if (iSize == 0) {
strcpy(m_pList[dwCount]->pProcessName,"Unknown");
}
if (SetOwnerName(dwCount) != ERR_SUCCESS) {
strcpy(m_pList[dwCount]->pOwnerName,"Unknown");
}
}
m_pList[dwCount]->CpuDeltaTime.QuadPart=0;
m_pList[dwCount]->CpuOldTime.QuadPart=0;
m_pList[dwCount]->dCpu=0;
m_pList[dwCount]->Changed = ~0;
TimeDelta.QuadPart=0;
}
TotalTime.QuadPart+=TimeDelta.QuadPart;
m_pList[dwCount]->CpuOldTime.QuadPart = Time.QuadPart;
dwCount++;
}
iOffset += pTemp->NextEntryOffset;
} while (pTemp->NextEntryOffset);
if (m_dwListSize > dwCount) {
while (m_dwListSize > dwCount) {
m_dwListSize--;
free(m_pList[m_dwListSize]);
}
m_pList=(PROCESSLIST **)realloc(m_pList,sizeof(PROCESSLIST *) * (dwCount + 1));
}
/*
calculate cpu percentage
DeltaTime = the KernelTime + Usertime from this UpdateProcessList - the KernelTime + UserTime from the last UpdataProcessList
TotalDeltaTime = the sum of all DeltaTime's
cpu = (DeltaTime / TotalDeltaTime) * 100
*/
DWORD dwItem=0;
double dCpu,dTotalCpu=0;
while (dwItem < m_dwListSize) {
dCpu = ((double)(m_pList[dwItem]->CpuDeltaTime.QuadPart / ((TotalTime.QuadPart / 1000) ? (TotalTime.QuadPart / 1000) : 1))) / 10;
#ifdef CHECK_LAG
if (m_bLagging && !(m_pList[dwItem]->Changed & SET_ALL) && m_pList[dwItem]->dwPID != 0 && dCpu > 99.90) {
int iPri;
int iOldPri=GetPriority(m_pList[dwItem]->Changed,m_pList[dwItem]->BasePriority);
switch(iOldPri)
{
case NORMAL_PRIORITY_CLASS:
iPri=THREAD_PRIORITY_BELOW_NORMAL;
break;
case ABOVE_NORMAL_PRIORITY_CLASS:
iPri=NORMAL_PRIORITY_CLASS;
break;
case HIGH_PRIORITY_CLASS:
iPri=ABOVE_NORMAL_PRIORITY_CLASS;
break;
case REALTIME_PRIORITY_CLASS:
iPri=HIGH_PRIORITY_CLASS;
break;
default:
iPri=0;
break;
}
if (iPri) {
HANDLE hProc=OpenProcess(PROCESS_SET_INFORMATION,false,m_pList[dwItem]->dwPID);
if (hProc) {
SetPriorityClass(hProc,iPri);
CloseHandle(hProc);
}
}
m_bLagging=false;
}
#endif
if (dCpu > 99.50) dCpu=99.50;
if (m_pList[dwItem]->dwPID != 0) {
dTotalCpu+=dCpu;
}
if (dCpu != m_pList[dwItem]->dCpu) {
m_pList[dwItem]->dCpu = dCpu;
m_pList[dwItem]->Changed |= SET_CPU;
}
dwItem++;
}
SetList(CWnd->hProcList);
//set status bar
char szBuffer[128];
sprintf(szBuffer,"Processes: %i",dwCount);
SendMessage(CWnd->hStatus,SB_SETTEXT,(LPARAM)0 | 0,(WPARAM)szBuffer);
if (m_dOldCpu != dTotalCpu) {
sprintf(szBuffer,"CPU Usage: %0.1f%%",dTotalCpu);
SendMessage(CWnd->hStatus,SB_SETTEXT,(LPARAM)1 | 0,(WPARAM)szBuffer);
NOTIFYICONDATA trayIcon;
trayIcon.cbSize=sizeof(NOTIFYICONDATA);
trayIcon.hWnd=m_hMain;
trayIcon.uID=IDI_TRAY;
trayIcon.uFlags=NIF_TIP;
strcpy(trayIcon.szTip,szBuffer);
Shell_NotifyIcon(NIM_MODIFY ,&trayIcon);
m_dOldCpu=dTotalCpu;
}
MEMORYSTATUS MemStat;
MemStat.dwLength=sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&MemStat);
sprintf(szBuffer,"Memory Usage: %i/%iMB",(MemStat.dwTotalPageFile-MemStat.dwAvailPageFile) / 1048576,MemStat.dwTotalPageFile / 1048576);
SendMessage(CWnd->hStatus,SB_SETTEXT,(LPARAM)2 | 0,(WPARAM)szBuffer);
m_bUpdateInProgress=false;
return ERR_SUCCESS;
}
/*
Function Description:
Fills ListView with process info from m_pList
only set value's that are changed
called by: SetList
Arguments:
IN hWnd, Handle to ListView
Returns:
Number of items in list
*/
int CProcList::SetList(HWND hWnd)
{
BYTE dwChange=0;
LVITEMA lvi;
lvi.mask=LVIF_TEXT;
lvi.iItem=0;
char szBuffer[MAX_PATH];
char szVersion[2][128];
char szFileName[MAX_PATH];
//disable redraw (this looks better)
SendMessage(hWnd,WM_SETREDRAW,false,0);
while ((DWORD)lvi.iItem < m_dwListSize) {
if (dwChange & SET_ALL) dwChange=~0;
else dwChange=m_pList[lvi.iItem]->Changed;
if (dwChange & SET_ALL) {
//this is a new process or order in the list is changed
lvi.pszText=m_pList[lvi.iItem]->pProcessName;
lvi.iSubItem=0;
if (lvi.iItem >= m_OldListSize) SendMessage(hWnd, LVM_INSERTITEM, 0,(long)&lvi);
else SendMessage(hWnd, LVM_SETITEM, 0,(long)&lvi);
lvi.iSubItem=1;
lvi.pszText=m_pList[lvi.iItem]->pOwnerName;
SendMessage(hWnd, LVM_SETITEM, 0,(long)&lvi);
inttochar(szBuffer,m_pList[lvi.iItem]->dwPID,sizeof(szBuffer));
lvi.iSubItem=3;
lvi.pszText=szBuffer;
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
//if we cant get the fullpath we try it with only the prog. name
strcpy(szFileName,m_pList[lvi.iItem]->pProcessName);
//Get FileInfo
HANDLE hProc=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,m_pList[lvi.iItem]->dwPID);
if (hProc) {
HandleToName(hProc,szFileName);
CloseHandle(hProc);
}
GetFileInfo(GetFileName(szFileName),(char *)szVersion,128,2);
lvi.iSubItem=5;
lvi.pszText=szVersion[0];
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
lvi.iSubItem=6;
lvi.pszText=szVersion[1];
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
strcpy(szBuffer,"N\\A");
FILETIME ft;
SYSTEMTIME st,lt;
*((LARGE_INTEGER *)&ft) = m_pList[lvi.iItem]->ftStartTime;
if (ft.dwLowDateTime != 0) {
FileTimeToSystemTime(&ft,&st);
SystemTimeToTzSpecificLocalTime(NULL,&st,<);
sprintf(szBuffer,"%02i:%02i:%02i %02i-%02i" ,lt.wHour,lt.wMinute,lt.wSecond,lt.wDay,lt.wMonth);
}
lvi.iSubItem=7;
lvi.pszText=szBuffer;
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
}
if (dwChange & SET_CPU) {
//CPU
sprintf(szBuffer,"%0.1f",m_pList[lvi.iItem]->dCpu);
lvi.iSubItem=2;
lvi.pszText=szBuffer;
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
}
if (dwChange & SET_RAM) {
//RAM
inttochar(szBuffer,m_pList[lvi.iItem]->dwRam / 1024,sizeof(szBuffer));
lvi.iSubItem=4;
lvi.pszText=szBuffer;
SendMessage(hWnd,LVM_SETITEM,0,(long)&lvi);
}
lvi.iItem++;
}
while (lvi.iItem <= m_OldListSize) {
SendMessage(hWnd,LVM_DELETEITEM,(int)lvi.iItem,0);
lvi.iItem++;
}
SendMessage(hWnd,WM_SETREDRAW,true,0);
return lvi.iItem;
}
/*
Function Description:
Get a PROCESSLIST struct by item
Arguments:
OUT lpProcessList, address of a PROCESSLIST struct
IN iLine, Item number to get PROCESSLIST struct from
Returns:
ERR_SUCCESS if successfull
*/
int CProcList::GetProcessInfo(PROCESSLIST *lpProcessList,int iLine)
{
if (m_bUpdateInProgress) return ERR_PLEASE_WAITH;
m_bAccessToBuffer=true;
if (iLine < 0 || (DWORD)iLine >= m_dwListSize) {
m_bAccessToBuffer=false;
return ERR_UNKNOWN;
}
memcpy(lpProcessList,m_pList[iLine],sizeof(PROCESSLIST));
m_bAccessToBuffer=false;
return ERR_SUCCESS;
}
/*
Function Description:
Get a PROCESSLIST struct by Pid
Arguments:
OUT lpProcessList, address of a PROCESSLIST struct
IN dwPID, pid of processto get PROCESSLIST struct from
Returns:
ERR_SUCCESS if successfull
*/
int CProcList::GetProcessInfoFromPid(PROCESSLIST *lpProcessList,DWORD dwPID)
{
if (m_bUpdateInProgress) return ERR_PLEASE_WAITH;
m_bAccessToBuffer=true;
//search true the list
for(int i=0;i<(int)m_dwListSize;i++)
{
if (m_pList[i]->dwPID == dwPID) {
memcpy(lpProcessList,m_pList[i],sizeof(PROCESSLIST));
m_bAccessToBuffer=false;
return ERR_SUCCESS;
}
}
m_bAccessToBuffer=false;
return ERR_UNKNOWN;
}