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; 
}