www.pudn.com > Process_Mo18292312142004.rar > Procinfo.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; 
extern char szOSVersion[200]; 
 
 
CProcInfo::CProcInfo(CWindow *CWnd) 
{ 
	m_CWnd=CWnd; 
	m_hRoot=NULL; 
	m_iSaveItem=0; 
	m_iIconDefProg=0; 
	m_iIconProg=0; 
	m_iIconInfo=0; 
	m_iIconThread=0; 
	m_iIconPort=0; 
	m_iIconWnd=0; 
	m_iIconMainWnd=0; 
	m_iIconReg=0; 
	m_iIconService=0; 
} 
 
/*  
Function Description: 
 
	Callback function for enum toplevel windows 
	Calls: AddItem 
	Started by: SetInfo 
Arguments: 
IN	hWnd,	Handle to toplevel window 
IN	lParam,	pointer to class CProcIno 
Returns: 
    false if window is found 
*/ 
 
BOOL CALLBACK EnumWindowsProc(HWND hWnd,LPARAM lParam) 
{ 
	DWORD dwWinPid; 
 
	CProcInfo *CTemp=(CProcInfo *)lParam; 
 
	GetWindowThreadProcessId(hWnd,&dwWinPid); 
 
	/* 
	check if Pid is pid we are searching for 
	check if it is a owner window 
	check if it is visible 
	*/ 
	if (dwWinPid == CTemp->m_Proc.dwPID && !GetWindow(hWnd,GW_OWNER) && IsWindowVisible(hWnd)) { 
 
		char szBuffer[MAX_PATH]; 
 
		if (GetWindowText(hWnd,szBuffer,sizeof(szBuffer)) > 0) { 
			int iIcon=CTemp->m_iIconWnd; 
 
			//get windows icon 
			HICON hIcon=(HICON)SendMessage(hWnd,WM_GETICON,ICON_BIG,0); 
			if (!hIcon) hIcon=(HICON)SendMessage(hWnd,WM_GETICON,ICON_SMALL,0);		 
			if (hIcon) { 
				iIcon=ImageList_ReplaceIcon(CTemp->m_hImg,CTemp->m_iIconMainWnd,hIcon); 
			} 
 
			//add window title to treeview 
			CTemp->AddItem(szBuffer,CTemp->m_hRoot,iIcon,(long)hWnd); 
 
			return false;//return false to stop enum 
		} 
	} 
	return true; 
} 
 
/*  
Function Description: 
 
	Callback function for enum thread windows 
	Calls: AddItem 	 
	Started by: SetInfo 
Arguments: 
IN	hWnd,	Handle to window 
IN	lParam,	pointer to class CProcIno 
Returns: 
    true 
*/ 
 
BOOL CALLBACK EnumThreadWndCallBack(HWND hWnd,LPARAM lParam) 
{ 
	CProcInfo *CTemp=(CProcInfo *)lParam; 
 
	char szWindowName[MAX_PATH]; 
	int i=0; 
	 
	i=GetWindowText(hWnd,szWindowName,MAX_PATH - 80); 
	 
	if (i) { 
		szWindowName[i]=' '; 
		szWindowName[i+1]='('; 
		i+=2; 
	} 
	else { 
		i=1; 
		szWindowName[0]='('; 
	} 
	i+=GetClassName(hWnd,szWindowName+i,MAX_PATH-i); 
		 
	szWindowName[i]=')'; 
	szWindowName[i+1]=0; 
	 
	if (i == 1) strcpy(szWindowName,"Unknown"); 
 
	HTREEITEM hSave; 
 
	//save old item 
	hSave=CTemp->m_hTempItem; 
 
	CTemp->m_hTempItem = CTemp->AddItem(szWindowName,CTemp->m_hTempItem,CTemp->m_iIconWnd,(LPARAM)hWnd); 
 
	EnumChildWindows(hWnd,EnumThreadWndCallBack,(LPARAM)CTemp); 
	 
	//set item back 
	CTemp->m_hTempItem=hSave; 
 
	return true; 
} 
 
/*  
Function Description: 
 
	Opens regedit  	 
	Called by: CProcInfo::Commands 
Arguments: 
IN	szKey,	Name of key to show when opening regedit 
Returns: 
    void 
*/ 
 
void CProcInfo::OpenRegEdit(char *szKey) 
{ 
	/* 
	is there not a command line option to open a key?? 
	i cant find it so i set the last open key value in the register and then execute regedit 
	*/ 
 
	HKEY hKey; 
 
	if (RegOpenKeyEx( 
		HKEY_CURRENT_USER, 
		"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit", 
		0, 
		KEY_ALL_ACCESS, 
		&hKey 
		) != ERROR_SUCCESS) return; 
 
	//strip key value and data 
	char *pbuf=szKey+strlen(szKey)-9; 
 
	while (pbuf > szKey) { 
		if (strncmp(pbuf,"   Name: ",9) == 0) { 
			*pbuf=0; 
		} 
		pbuf--; 
	} 
 
	RegSetValueEx(hKey,"LastKey",0,REG_SZ,(LPBYTE)szKey,strlen(szKey)); 
	RegCloseKey(hKey); 
 
	ShellExecute(NULL,"open","regedit.exe","","",SW_SHOW); 
} 
 
/*  
Function Description: 
	Kills a thread  	 
	Called by: CProcInfo::Commands 
Arguments: 
IN	hWnd,		Owner window 
IN	szThread,	String containing "Thread Id:%id" 
Returns: 
    void 
*/ 
 
void CProcInfo::KillThread(HWND hWnd,char *szThread) 
{ 
	HANDLE	hThread=NULL; 
 
	try { 
		//openthread should be loaded here  
		if (!NtApi.fOpenThread) throw("Could not load OpenThread"); 
		 
		char *pbuf=szThread+10;	 
 
		while (*pbuf && *pbuf != ' ') pbuf++; 
 
		*pbuf=0; 
		int ThreadId=atoi(szThread+10); 
 
		if (ThreadId < 1) throw("Invalid Thread ID"); 
	 
		//get a handle to the thread 
 
		hThread = NtApi.fOpenThread(THREAD_TERMINATE,false,ThreadId); 
	 
		if (!hThread) throw("Could not open thread handle"); 
 
		if (!TerminateThread(hThread,0)) throw("Could not kill thread"); 
 
		CloseHandle(hThread); 
 
		SetInfo(-2); 
	} 
	catch(char *szError) 
	{ 
		if (hThread) CloseHandle(hThread); 
		ShowError(hWnd,szError); 
	} 
	return; 
} 
 
/*  
Function Description: 
 
	Set Priority for a thread 
 
Arguments: 
IN szThread,	pointer to thread string as shown in the tree view 
IN dwPri,		Priority to set 
Returns: 
    void 
*/ 
 
void CProcInfo::SetPriority(char *szThread,DWORD dwPri) 
{ 
	HANDLE hThread=NULL; 
 
	try { 
 
		if (!NtApi.fOpenThread) throw("Could not load API OpenThread"); 
 
		char *pbuf=szThread+10;	 
 
		while (*pbuf && *pbuf != ' ') pbuf++; 
 
		*pbuf=0; 
						 
		int ThreadId=atoi(szThread+10); 
 
		if (ThreadId < 1) throw("Invalid thread id"); 
	 
		//get a handle to the thread 
 
		hThread=NtApi.fOpenThread(THREAD_SET_INFORMATION,false,ThreadId); 
						 
		if (!hThread) throw("Could not open thread"); 
 
		if (!SetThreadPriority(hThread,dwPri)) throw("Could not set priority"); 
	} 
	catch(char *szError) 
	{ 
		ShowError(m_hTree,szError); 
	} 
	if (hThread) CloseHandle(hThread); 
 
} 
 
 
/*  
Function Description: 
	For WM_COMMAND messages 
	Called by: CWindow::Commands 
	Used by all popup commands from the processinfo listview 
	calls: CWindow::SetClipBoardText, OpenRegEdit, KillThread, KillTcpConnection, CWindowInfo::GetInfo 
Arguments: 
IN	hWnd,		Owner window 
IN	wParam, 
IN	lParam. 
Returns: 
    void 
*/ 
 
void CProcInfo::Commands(HWND hWnd,WPARAM wParam,LPARAM lParam) 
{ 
	HTREEITEM hItem= TreeView_GetSelection(m_hTree); 
 
	if (!hItem) return; 
 
	TVITEMA tvi; 
	char szText[MAX_PATH]; 
	tvi.mask=TVIF_PARAM | TVIF_TEXT	| TVIF_HANDLE | TVIF_IMAGE; 
	tvi.pszText=szText; 
	tvi.cchTextMax=sizeof(szText); 
	tvi.hItem=hItem; 
 
	if (SendMessage(m_hTree,TVM_GETITEM,0,(WPARAM)&tvi) == false) return; 
	//just to be sure its null terminated 
	szText[sizeof(szText)-1]=0; 
 
	switch(LOWORD(wParam)) 
	{ 
	case EXTRA_ACTIVE: 
		SetForegroundWindow((HWND)tvi.lParam); 
		break; 
	case EXTRA_SHOW: 
		ShowWindow((HWND)tvi.lParam,SW_SHOW); 
		break; 
	case EXTRA_HIDE: 
		ShowWindow((HWND)tvi.lParam,SW_HIDE); 
		break; 
	case EXTRA_DESTROY: 
		PostMessage((HWND)tvi.lParam,WM_CLOSE,0,0); 
		SetInfo(-2); 
		break; 
	case EXTRA_CLIP: 
		m_CWnd->SetClipBoardText(tvi.pszText); 
		break; 
	case EXTRA_OPEN_KEY: 
		OpenRegEdit(tvi.pszText); 
		break; 
	case EXTRA_OPEN_FILE: 
	{ 
		//strip filename 
		char *pbuf=strrchr(tvi.pszText,'\\'); 
		if (pbuf) *(pbuf+1)=0; 
		//tvi.pszText+6 to skip "File: "  
		ShellExecute(NULL,"explore",tvi.pszText+6,"","",SW_SHOW); 
		break; 
	} 
	case EXTRA_KILL_THREAD: 
		KillThread(hWnd,tvi.pszText); 
		break; 
	case EXTRA_IDLE: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_IDLE); 
		break; 
	case EXTRA_LOWEST: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_LOWEST); 
		break; 
	case EXTRA_BELOW: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_BELOW_NORMAL); 
		break; 
	case EXTRA_NORMAL: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_NORMAL); 
		break; 
	case EXTRA_ABOVE: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_ABOVE_NORMAL); 
		break; 
	case EXTRA_HIGH: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_HIGHEST	); 
		break; 
	case EXTRA_REALTIME: 
		SetPriority(tvi.pszText,THREAD_PRIORITY_TIME_CRITICAL); 
		break; 
	case EXTRA_PROPERTIES: 
		OpenFileProperties(hWnd,tvi.pszText+15); 
		break; 
	case EXTRA_OPEN_SERVICES: 
		ShellExecute(NULL,"open","services.msc","","",SW_SHOW); 
		break; 
	case EXTRA_TCP_KILL: 
		KillTcpConnection(hWnd,tvi.pszText); 
		break; 
	case EXTRA_GETWNDINFO: 
		{ 
			CWndInfo *CWindowInfo; 
			CWindowInfo= new CWndInfo; 
			if (CWindowInfo) { 
				CWindowInfo->GetInfo(hWnd,(HWND)tvi.lParam); 
				delete CWindowInfo; 
			} 
			break; 
		} 
	} 
} 
 
/*  
Function Description: 
	For WM_NOTIFY message  
	Called by: CWindow::Notify 
Arguments: 
IN	hWnd,		Owner window 
IN	wParam, 
IN	lParam. 
Returns: 
    void 
*/ 
 
void CProcInfo::Notify(HWND hWnd,WPARAM wParam,LPARAM lParam) 
{ 
	NMHDR *nmt=(NMHDR *)lParam; 
	if (nmt->code == NM_RCLICK) { 
		HTREEITEM hItem= TreeView_GetSelection(nmt->hwndFrom); 
 
		if (!hItem) return; 
 
		char szText[MAX_PATH]; 
		TVITEMA tvi; 
		tvi.mask=TVIF_PARAM | TVIF_TEXT	| TVIF_HANDLE | TVIF_IMAGE; 
		tvi.pszText=szText; 
		tvi.cchTextMax=sizeof(szText); 
		tvi.hItem=hItem; 
 
		if (SendMessage(nmt->hwndFrom,TVM_GETITEM,0,(WPARAM)&tvi) == false) return; 
 
		//create the popups on the fly... 
		HMENU hPop=CreatePopupMenu(); 
		if (!hPop) return; 
		bool bSep=false; 
 
		if (tvi.iImage == m_iIconWnd || tvi.iImage == m_iIconMainWnd) { 
			AppendMenu(hPop,MF_STRING,EXTRA_GETWNDINFO,"&Show Window Style's"); 
			AppendMenu(hPop,MF_SEPARATOR,0,""); 
			AppendMenu(hPop,MF_STRING,EXTRA_ACTIVE,"&Set Active Window"); 
			AppendMenu(hPop,MF_SEPARATOR,0,"");			 
			AppendMenu(hPop,MF_STRING,EXTRA_SHOW,"&Show Window");			 
			AppendMenu(hPop,MF_STRING,EXTRA_HIDE,"&Hide Window");	 
			AppendMenu(hPop,MF_SEPARATOR,0,"");			 
			AppendMenu(hPop,MF_STRING,EXTRA_DESTROY,"&Destroy Window"); 
			bSep=true;	 
		} 
		else { 
			bSep=true; 
			switch(tvi.lParam) 
			{ 
			case TREE_KEY:			 
				AppendMenu(hPop,MF_STRING,EXTRA_OPEN_KEY,"&Open with regedit"); 
				break; 
			case TREE_FILE: 
				AppendMenu(hPop,MF_STRING,EXTRA_OPEN_FILE,"Open Directory with Explorer"); 
				break; 
			case TREE_THREADS: 
				{ 
					int iPri=THREAD_PRIORITY_ERROR_RETURN; 
					if (NtApi.fOpenThread) { 
						char *pbuf=tvi.pszText+10;	 
 
						while (*pbuf && *pbuf != ' ') pbuf++; 
 
						*pbuf=0; 
						 
						int ThreadId=atoi(tvi.pszText+10); 
 
						if (ThreadId > 0) { 
	 
							//get a handle to the thread 
 
							HANDLE hThread = NtApi.fOpenThread(THREAD_QUERY_INFORMATION,false,ThreadId); 
							if (hThread) { 
								iPri=GetThreadPriority(hThread); 
								CloseHandle(hThread); 
							} 
						} 
					} 
					AppendMenu(hPop,MF_STRING,EXTRA_REALTIME,	"&RealTime"); 
					AppendMenu(hPop,MF_STRING,EXTRA_HIGH,		"&High"); 
					AppendMenu(hPop,MF_STRING,EXTRA_ABOVE,		"&Above Normal"); 
					AppendMenu(hPop,MF_STRING,EXTRA_NORMAL,		"&Normal"); 
					AppendMenu(hPop,MF_STRING,EXTRA_BELOW,		"&Below Normal"); 
					AppendMenu(hPop,MF_STRING,EXTRA_LOWEST,		"&Lowest"); 
					AppendMenu(hPop,MF_STRING,EXTRA_IDLE,		"&Idle"); 
					if (iPri != THREAD_PRIORITY_ERROR_RETURN) { 
						int iItem; 
 
						switch(iPri)  
						{ 
						case THREAD_PRIORITY_TIME_CRITICAL: 
							iItem=EXTRA_REALTIME; 
							break; 
						case THREAD_PRIORITY_HIGHEST: 
							iItem=EXTRA_HIGH; 
							break; 
						case THREAD_PRIORITY_ABOVE_NORMAL: 
							iItem=EXTRA_ABOVE; 
							break; 
						case THREAD_PRIORITY_NORMAL: 
							iItem=EXTRA_NORMAL; 
							break; 
						case THREAD_PRIORITY_BELOW_NORMAL: 
							iItem=EXTRA_BELOW; 
							break; 
						case THREAD_PRIORITY_LOWEST: 
							iItem=EXTRA_LOWEST; 
							break; 
						case THREAD_PRIORITY_IDLE: 
							iItem=EXTRA_IDLE; 
							break; 
						default: 
							iItem=0; 
						} 
						//set Priority checked 
						if (iItem != 0) SetItemState(hPop,iItem,true); 
 
					} 
					AppendMenu(hPop,MF_SEPARATOR,0,""); 
					AppendMenu(hPop,MF_STRING,EXTRA_KILL_THREAD,"&Terminate Thread"); 
					break; 
				} 
			case TREE_PARENT: 
				AppendMenu(hPop,MF_STRING,EXTRA_PROPERTIES,"&File properties"); 
				break; 
			case TREE_SERVICES: case TREE_SERVICES_NAME: case TREE_SERVICES_MAIN: 
				AppendMenu(hPop,MF_STRING,EXTRA_OPEN_SERVICES,"Open &Services"); 
				break; 
			case TREE_NETSTAT_TCP_OPEN: 
				AppendMenu(hPop,MF_STRING,EXTRA_TCP_KILL,"&Close Port"); 
				break; 
			default: 
				bSep=false; 
				break; 
			} 
		} 
	 
		if (bSep) AppendMenu(hPop,MF_SEPARATOR,0,""); 
		AppendMenu(hPop,MF_STRING,EXTRA_CLIP,"Copy To &ClipBoard");			 
		 
		POINT pt; 
		GetCursorPos(&pt); 
		TrackPopupMenu(hPop,TPM_LEFTALIGN,pt.x,pt.y,NULL,hWnd,NULL); 
		DestroyMenu(hPop); 
	} 
	 
	return; 
} 
 
/*  
Function Description: 
	Creates TreeWindow and add icons to it 
	Called by: CWindow::ChangeSubWindow 
Arguments: 
IN	hWnd,		Owner window 
IN	hInst,		Handle to application instance 
Returns: 
    Handle to treeview 
*/ 
 
HWND CProcInfo::SubTree(HWND hWnd,HINSTANCE hInst) 
{ 
	m_hTree = CreateWindowEx(WS_EX_CLIENTEDGE, 
                            WC_TREEVIEW, 
                            "Tree View", 
							WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_RTLREADING | TVS_SHOWSELALWAYS,  
                            0,  
                            0,  
                            0,  
                            0, 
                            hWnd,  
                            NULL,  
                            hInst,  
                            NULL);  
 
 
	if (!m_hTree) { 
		ShowError(hWnd,"Error Creating TreeView"); 
		return NULL; 
	} 
	 
	//create the icon list 
	m_hImg=ImageList_Create(16,16,ILC_COLOR,0,8); 
 
	if (m_hImg == NULL) { 
		return m_hTree; 
	} 
 
	ImageList_SetBkColor(m_hImg,RGB(255,255,255)); 
 
	SendMessage(m_hTree,TVM_SETIMAGELIST,TVSIL_NORMAL,(long)m_hImg); 
 
	HICON hIcon; 
	hIcon=LoadIcon(NULL,IDI_ASTERISK); 
 
	m_iIconInfo=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_THREAD)); 
	m_iIconThread=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_VERSION)); 
	m_iIconVersion=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_NETSTAT)); 
	m_iIconPort=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_WINDOW)); 
	m_iIconMainWnd=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_WINDOW)); 
	m_iIconWnd=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(NULL,IDI_APPLICATION); 
	m_iIconDefProg=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
	m_iIconProg=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_REGEDIT)); 
	m_iIconReg=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_SERVICES)); 
	m_iIconService=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_PRI)); 
	m_iIconPri=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_FILE)); 
	m_iIconFile=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	hIcon=LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_COMMAND)); 
	m_iIconCommand=ImageList_ReplaceIcon(m_hImg,-1,hIcon); 
 
	return m_hTree; 
} 
 
/*  
Function Description: 
	Adds a item to the three view 
	calls: CWindow::mySendMessage 
	Called by: All functions that need to add items to the threeview 
Arguments: 
IN	Buf,		Text to show in the item		 
IN	hRoot,		Root item 
IN	iIcon,		Index of icon to show 
IN	lParam,		Param to set for the item 
Returns: 
    Handle to treeview 
*/ 
 
HTREEITEM CProcInfo::AddItem(char *Buf,HTREEITEM hRoot,int iIcon,LPARAM lParam) 
{ 
	TVINSERTSTRUCTA tv; 
	TVITEMA tvi; 
	 
	tvi.mask=TVIF_TEXT | LVIF_IMAGE | TVIF_SELECTEDIMAGE | LVIF_PARAM; 
	tvi.pszText=Buf; 
	tvi.cchTextMax=strlen(Buf); 
	tvi.iImage=iIcon; 
	tvi.iSelectedImage=iIcon; 
	tvi.lParam=lParam; 
	tv.hParent=hRoot; 
	tv.hInsertAfter=TVI_LAST; 
	tv.item=tvi; 
	 
	HTREEITEM hItem= (HTREEITEM)m_CWnd->mySendMessage(m_hTree,TVM_INSERTITEM,0,(LPARAM)&tv); 
	 
	if (tvi.lParam == m_ItemToSelect) { 
		m_hItemToSelect=hItem; 
		m_ItemToSelect=-1; 
	} 
	return hItem; 
} 
 
/*  
Function Description: 
 
	Creates the tree with process info 
	Called by: CWindow::LogItem, Commands, KillTcpConnection, KillThread, CWindow::Notify 
	calls:	CProcList::GetProcessInfo, AddItem GetThreads, NetStatGetList,  
			GetServicesForProc, CStartup::SearchStartupKeys 
Arguments: 
IN	iItem,	Item in ProcessList to show info from 
Returns: 
    void 
*/ 
 
void CProcInfo::SetInfo(int iItem) 
{ 
	HANDLE hProc=NULL; 
	 
	m_ItemToSelect=-1; 
	m_hItemToSelect=NULL; 
 
	//if iItem = -2 update treeview 
	if (iItem == -2) { 
		iItem=m_iSaveItem; 
 
		/* 
		save selection so we can reselect it when the tree view is updated 
		note: we normaly only update when we killed something (window, thread) 
		so we can't select it so we find the parameter that belongs to the current selection 
		and select the first item with that parameter 
		*/ 
 
		HTREEITEM hItem= TreeView_GetSelection(m_hTree); 
		while (hItem) { 
			TVITEMA tvi; 
			tvi.mask=TVIF_PARAM | TVIF_IMAGE; 
			tvi.hItem=hItem; 
 
			if (SendMessage(m_hTree,TVM_GETITEM,0,(WPARAM)&tvi)) { 
				if (tvi.iImage == m_iIconWnd) { 
					/* 
						This is a window lParam is a window handle so find first parent item that  
						isnt a window 
					*/ 
					hItem=TreeView_GetParent(m_hTree,hItem); 
					continue; 
				} 
				else m_ItemToSelect=tvi.lParam; 
			 
			} 
			break; 
		}	 
	} 
	m_iSaveItem=iItem; 
 
	char szFileName[MAX_PATH]; 
	char szBuffer[MAX_PATH]; 
	char szBuf[MAX_PATH]; 
	char *pFile=szFileName; 
	int iIconIndex=m_iIconDefProg, 
		i; 
 
	*szFileName=0; 
 
	HICON pSmallIcon,pLargeIcon; 
 
	if (m_CWnd->CProc->GetProcessInfo(&m_Proc,iItem) != ERR_SUCCESS) return; 
 
	if (m_Proc.dwPID == 0) return;//system idle process 
 
	SendMessage(m_hTree,WM_SETREDRAW,false,0); 
 
	if (m_hRoot) SendMessage(m_hTree,TVM_DELETEITEM ,0,(LPARAM)m_hRoot); 
        
	hProc=OpenProcess(PROCESS_ALL_ACCESS,false,m_Proc.dwPID); 
 
	if (hProc) { 
		//get fullpath of process 
		if (HandleToName(hProc,szFileName)) { 
 
			pFile=GetFileName(szFileName); 
 
			//try to get the icon of the file	 
			if (ExtractIconEx(pFile, 
							0,  
							&pLargeIcon,  
							&pSmallIcon, 
							1 
							) != NULL) { 
				iIconIndex=ImageList_ReplaceIcon(m_hImg,m_iIconProg,pSmallIcon ? pSmallIcon : pLargeIcon); 
 
				//if failed set to default icon 
				if (iIconIndex == -1) iIconIndex=m_iIconDefProg; 
			}	 
		} 
	} 
 
	strcpy(szBuffer,m_Proc.pProcessName); 
 
	i=strlen(szBuffer); 
	 
	strcpy(szBuffer+i,"  Updated on: "); 
	i+=14; //=strlen(szBuffer); 
 
	//add current time to string 
	GetTimeFormat(LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT,NULL,NULL,szBuffer+i,sizeof(szBuffer)-i); 
 
	//add proc name + time to the tree view 
	m_hRoot=AddItem(szBuffer,TVI_ROOT,iIconIndex,TREE_ROOT); 
 
	//if we log it to a file first add some other info to the file 
	if (m_CWnd->m_iDataOption == MES_LOG_TO_FILE) { 
		FILETIME ft; 
		SYSTEMTIME st,lt; 
		char szTime[50]; 
	 
		*((LARGE_INTEGER *)&ft) = m_Proc.ftStartTime; 
 
		if (ft.dwLowDateTime != 0) { 
			FileTimeToSystemTime(&ft,&st); 
			SystemTimeToTzSpecificLocalTime(NULL,&st,<); 
			sprintf(szTime,"%02i:%02i:%02i  %02i-%02i" ,lt.wHour,lt.wMinute,lt.wSecond,lt.wDay,lt.wMonth); 
		} 
		else strcpy(szTime,"N\\A"); 
		 
		sprintf(szBuffer, 
			"OS: %s\r\nOwner:%s\r\nProcess ID:%i\r\nCPU Usage %0.2f\r\nRam Usage %i\r\nStart Time %s\r\n", 
			szOSVersion, 
			m_Proc.pOwnerName, 
			m_Proc.dwPID, 
			m_Proc.dCpu, 
			m_Proc.dwRam, 
			szTime 
		); 
		DWORD dwWritten; 
		WriteFile(m_CWnd->hLogFile,szBuffer,strlen(szBuffer),&dwWritten,NULL); 
	} 
 
 
	//try to find main window of this process 
	EnumWindows((WNDENUMPROC)EnumWindowsProc,(LPARAM)this); 
 
	//add fullpath to tree view 
 
	if (*pFile) AddItem(pFile,m_hRoot,m_iIconFile,TREE_FULLPATH); 
 
	//try to get command line 
	if (hProc) { 
		DWORD dwThreadId; 
 
		//execute GetCommandLine in the remote process 
		HANDLE hThread = CreateRemoteThread( 
								hProc,  
								NULL,  
								0,  
								(LPTHREAD_START_ROUTINE)&GetCommandLine, 
								0, 
								0, 
								&dwThreadId 
								); 
 
		if (hThread) { 
			DWORD dwExit; 
			if (WaitForSingleObject(hThread,200) == WAIT_OBJECT_0) { 
 
				//get exit code of the thread (this is a pointer to the commandline) 
				GetExitCodeThread(hThread,&dwExit); 
				 
				if (dwExit) { 
					//read the string from remote process 
					if (ReadProcessMemory(hProc,(void *)dwExit,szBuffer,sizeof(szBuffer)-14,&dwThreadId)) { 
						strcpy(szBuf,"CommandLine:  "); 
						strcpy(szBuf+13,szBuffer); 
						//add commandline to the treeview 
						AddItem(szBuf,m_hRoot,m_iIconCommand,TREE_COMMAND_LINE); 
					} 
				} 
	 
			} 
			CloseHandle(hThread); 
		} 
		//close handle to process we dont need it anymore 
		CloseHandle(hProc); 
	} 
 
	//get filename of parent process if there is one 
	if (m_Proc.dwOwnerPID > 0) { 
 
		hProc=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,m_Proc.dwOwnerPID); 
 
		if (hProc) { 
			if (HandleToName(hProc,szBuffer) == true) { 
				szBuffer[sizeof(szBuffer) - 18]=0; 
				strcpy(szBuf,"Parent Process:"); 
				strcat(szBuf,szBuffer); 
 
				//add fullpath of parent proc to the treeview 
 
				AddItem(szBuf,m_hRoot,m_iIconDefProg,TREE_PARENT); 
			} 
			CloseHandle(hProc); 
		} 
	} 
 
	//get base priority of process 
 
	strcpy(szBuffer,"Priority "); 
 
 
	switch (GetPriority(m_Proc.dwPID,m_Proc.BasePriority)) 
	{ 
	case IDLE_PRIORITY_CLASS: 
		strcat(szBuffer,"Idle"); 
		break; 
	case BELOW_NORMAL_PRIORITY_CLASS: 
		strcat(szBuffer,"Below Normal"); 
		break; 
	case NORMAL_PRIORITY_CLASS: 
		strcat(szBuffer,"Normal"); 
		break; 
	case ABOVE_NORMAL_PRIORITY_CLASS: 
		strcat(szBuffer,"Above Normal"); 
		break; 
	case HIGH_PRIORITY_CLASS: 
		strcat(szBuffer,"High"); 
		break; 
	case REALTIME_PRIORITY_CLASS: 
		strcat(szBuffer,"RealTime"); 
		break; 
	default: 
		strcat(szBuffer,"Unknown"); 
		break; 
	} 
	//add priority to the treeview 
	AddItem(szBuffer,m_hRoot,m_iIconPri,TREE_PRIORITY); 
 
	//add read/write transfer count 
	char szRead[MAX_PATH]="Read transfer count: "; 
	largeinttochar(szRead+21,&m_Proc.ReadTransferCount,sizeof(szRead)-28); 
	strcat(szRead," bytes"); 
	AddItem(szRead,m_hRoot,m_iIconInfo,TREE_READ_TRANSFER_COUNT); 
	 
	char szWrite[MAX_PATH]="Write transfer count: "; 
	largeinttochar(szWrite+22,&m_Proc.WriteTransferCount,sizeof(szWrite)-29); 
	strcat(szWrite," bytes"); 
	AddItem(szWrite,m_hRoot,m_iIconInfo,TREE_WRITE_TRANSFER_COUNT); 
 
 
	char VersionInfo[8][128]; 
	HTREEITEM hSubItem; 
 
	if (*szFileName) { 
		//get version info..... 
		if (GetFileInfo(pFile,(char *)VersionInfo,128,8)) { 
 
			hSubItem=AddItem("Version Info",m_hRoot,m_iIconVersion,TREE_VERSION_MAIN); 
 
			//add version info 
			AddItem(VersionInfo[0],hSubItem,m_iIconVersion,TREE_DESCRIPTION); 
			AddItem(VersionInfo[1],hSubItem,m_iIconVersion,TREE_COMPANY); 
			AddItem(VersionInfo[2],hSubItem,m_iIconVersion,TREE_VERSION); 
			AddItem(VersionInfo[3],hSubItem,m_iIconVersion,TREE_VERSION); 
			AddItem(VersionInfo[4],hSubItem,m_iIconVersion,TREE_VERSION); 
			AddItem(VersionInfo[5],hSubItem,m_iIconVersion,TREE_VERSION); 
			AddItem(VersionInfo[6],hSubItem,m_iIconVersion,TREE_VERSION); 
			AddItem(VersionInfo[7],hSubItem,m_iIconVersion,TREE_VERSION); 
		} 
	} 
 
 
	//get threads for this process.... 
	GetThreads(); 
 
	//get netstat for this process  
	NetStatGetList(m_Proc.dwPID); 
 
	//get services registered in this process 
	GetServicesForProc(m_Proc.dwPID); 
 
 
	if (m_Proc.dwPID != 4 && m_Proc.dwPID != 0) { 
		/* 
			Search Registry and startupdirs for a possible way how this process is executed 
		*/ 
		CStartup *CTempStartup; 
 
		CTempStartup = new CStartup(this,m_hRoot,m_iIconReg); 
 
		if (CTempStartup) { 
			CTempStartup->SearchStartupKeys(m_Proc.pProcessName); 
			delete CTempStartup; 
		} 
	} 
 
	TreeView_Expand(m_hTree,m_hRoot,TVE_EXPAND); 
 
	SendMessage(m_hTree,WM_SETREDRAW,true,0); 
 
	if (m_hItemToSelect) { 
		TreeView_SelectItem(m_hTree,m_hItemToSelect); 
	} 
	else { 
		TreeView_SelectItem(m_hTree,m_hRoot); 
	} 
	return; 
} 
 
/*  
Function Description: 
	Get threads running in a process and window's associated with a thread 
	Called by: SetInfo 
	Calls: GetThreadTimesFromID, AddItem, EnumThreadWindows 
Arguments: 
 
Returns: 
    0 
*/ 
 
int CProcInfo::GetThreads() 
{ 
	HANDLE hSnap=NULL; 
	HTREEITEM	hThread, 
				hChild; 
	ULONGLONG	TotalCpuTime=0, 
				TempThreadTime=0, 
				*ThreadTimes=NULL; 
 
	THREADENTRY32 ThreadEntry; 
 
	char szBuffer[MAX_PATH]; 
 
	try { 
		//get snapshot for all threads 
		hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0); 
 
		if (hSnap == NULL) throw(0); 
 
		ThreadEntry.dwSize=sizeof(THREADENTRY32); 
			 
		if (Thread32First(hSnap,&ThreadEntry) == false) throw(0); 
		 
		//check if we have a complete struct. 
 
		if (ThreadEntry.dwSize != sizeof(THREADENTRY32)) throw(0); 
 
		hThread=AddItem("Threads",m_hRoot,m_iIconThread,TREE_THREADS_MAIN); 
 
		int Counter=0; 
		//loop true all entry's and calc. total cpu time 
		do { 
			if (ThreadEntry.th32OwnerProcessID == m_Proc.dwPID) { 
				 
				//get time thread has executed in kernel+user mode 
				 
				if (GetThreadTimesFromID(ThreadEntry.th32ThreadID,&TempThreadTime)) { 
					 
					ThreadTimes=(ULONGLONG *)realloc(ThreadTimes,sizeof(ULONGLONG) * (Counter + 1)); 
 
					memcpy((void *)&ThreadTimes[Counter],(void *)&TempThreadTime,sizeof(ULONGLONG)); 
 
					TotalCpuTime+=TempThreadTime;//add to the total 
 
					Counter++; 
				} 
				 
			} 
 
		} while (Thread32Next(hSnap,&ThreadEntry)); 
		 
		ThreadEntry.dwSize=sizeof(THREADENTRY32); 
 
		//get first entry 
		if (Thread32First(hSnap,&ThreadEntry) == false) throw(0); 
 
		int cpu=0, 
			i=0; 
 
		/* 
		loop again true all entry's and calc cpu and add info to treeview and enum all thread windows 
		cpu=threadtime / totaltime * 100 
		the totaltime is som of all threadtimes for this process 
		  */ 
		do { 
			if (ThreadEntry.th32OwnerProcessID == m_Proc.dwPID) { 
				 
				if (i < Counter) { 
					cpu = ((int)(ThreadTimes[i] / ((TotalCpuTime / 1000) ? (TotalCpuTime / 1000) : 1))) / 10;								 
					if (cpu > 99) cpu=99; 
				} 
 
				sprintf(szBuffer,"Thread Id:%04i Cpu %02i%%",ThreadEntry.th32ThreadID,cpu); 
 
				hChild=AddItem(szBuffer,hThread,m_iIconThread,TREE_THREADS); 
 
 
				m_hTempItem=hChild; 
 
				EnumThreadWindows(ThreadEntry.th32ThreadID,EnumThreadWndCallBack,(LPARAM)this); 
 
				i++; 
			}			 
		} while (Thread32Next(hSnap,&ThreadEntry)); 
 
	} 
	catch (int iError) 
	{ 
		if (hSnap) CloseHandle(hSnap); 
		if (ThreadTimes) free(ThreadTimes); 
		return iError; 
	} 
 
	return 0; 
} 
 
/*  
Function Description: 
	Get threadtime from a thread id 
	Called by: GetThreadTimesFromID 
Arguments: 
IN	dwThreadID, id of the thread 
OUT	ThreadTimes, Kerneltime+usertime for this thread 
 
Returns: 
    1 if success 
*/ 
 
int CProcInfo::GetThreadTimesFromID(DWORD dwThreadID,ULONGLONG *ThreadTimes) 
{ 
	if (!NtApi.fOpenThread) { 
		return 0; 
	} 
 
	HANDLE	hThread; 
     
	ULONGLONG ftTotal,ftCreation,ftExit,ftKernel,ftUser; 
	 
	//get a handle to the thread 
	hThread = NtApi.fOpenThread(THREAD_QUERY_INFORMATION,false,dwThreadID); 
	 
	if (!hThread) return 0; 
 
	//get thread times... 
	if (GetThreadTimes(hThread,(LPFILETIME)&ftCreation,(LPFILETIME)&ftExit,(LPFILETIME)&ftKernel,(LPFILETIME)&ftUser) == 0) { 
		CloseHandle(hThread); 
		return 0; 
	} 
	ftTotal=ftKernel+ftUser; 
	memcpy((void *)ThreadTimes,(void *)&ftTotal,sizeof(ULONGLONG)); 
	CloseHandle(hThread); 
	return 1; 
} 
 
const char *szTcpState[]={ 
	"UNKNOWN   ", 
	"CLOSED    ", 
	"LISTEN    ", 
	"SYN_SENT  ", 
	"SYN_RCVD  ", 
	"ESTAB     ", 
	"FIN_WAIT1 ", 
	"FIN_WAIT2 ", 
	"CLOSE_WAIT", 
	"CLOSING   ", 
	"LAST_ACK  ", 
	"TIME_WAIT ", 
	"DELETE_TCB", 
}; 
 
/*  
Function Description: 
	Returns pointer to string with the state of the connection 
	Called by: NetStatGetList 
Arguments: 
IN	iState, State of the connection 
Returns: 
    pointer to string 
*/ 
 
const char *CProcInfo::GetState(int iState) 
{ 
	if (iState > 12 || iState < 1) iState=0; 
	return szTcpState[iState];	 
} 
 
/*  
Function Description: 
	Converts a network address into a string in dotted format. 
	Called by: NetStatGetList 
Arguments: 
OUT	szBuffer,	Buffer with dotted ip 
IN	dwIP,		ip address 
Returns: 
    pointer to string 
*/ 
 
char *CProcInfo::ToStringIp(char *szBuffer,DWORD dwIP) 
{ 
	wsprintf(szBuffer, "%i.%i.%i.%i", 
		LOBYTE(LOWORD(dwIP)),  
		HIBYTE(LOWORD(dwIP)), 
		LOBYTE(HIWORD(dwIP)),  
		HIBYTE(HIWORD(dwIP)) 
		); 
	return szBuffer; 
} 
 
/*  
Function Description: 
	Get all open ports used by a process. 
	Called by: SetList 
	Calls: ToStringIp, GetState 
Arguments: 
IN	dwPID,	Process id 
Returns: 
    0 if successfull 
*/ 
 
int CProcInfo::NetStatGetList(DWORD dwPID) 
{ 
	PMIB_TCPTABLE_EX TcpList=NULL; 
	PMIB_UDPTABLE_EX UdpList=NULL; 
 
	try { 
		if (!NtApi.fnAllocateAndGetTcpExTableFromStack ||  
			!NtApi.fnAllocateAndGetUdpExTableFromStack 
		) {  
 
			//windows xp (and newer?) versions only  
			/* 
				You can do this with win2k using GetTcpTable 
				to find the pid for a open port you could search true all File handles with name 
				"\Device\Tcp" and "\Device\Udp" and then use NtDeviceIoControlFile  
				with IoControlCode 0x00210012 to see what port number it is and if it is a port 
				find the correct entry in the MIB_TCPTABLE... 
				i tryed it and it works but with some handles NtDeviceIoControlFile never returns... 
				opening the handle with more access rights works but you cant get all handles then... 
			*/ 
				throw(-1); 
		} 
 
		DWORD i; 
		int len; 
		char szBuffer[MAX_PATH]; 
		char szIp[128]; 
		HTREEITEM hRoot=NULL; 
 
		//get struct. MIB_TCPTABLE_EX 
		if (NtApi.fnAllocateAndGetTcpExTableFromStack((PMIB_TCPTABLE_EX *)&TcpList,true,GetProcessHeap(),0,2) == NO_ERROR) { 
			for (i=0;idwNumEntries;i++) 
			{	 
				if (TcpList->table[i].dwProcessId == dwPID) { 
					if (TcpList->table[i].dwRemoteAddr == 0) TcpList->table[i].dwRemotePort=0; 
			 
					len=wsprintf(szBuffer,"TCP %s:%i", 
						ToStringIp(szIp,TcpList->table[i].dwLocalAddr), 
						ntohs((short)TcpList->table[i].dwLocalPort) 
					); 
					//i cant get them in nice looking coloms... 
					while (len < 28) { 
						szBuffer[len]=' '; 
						len++; 
					} 
 
					sprintf((szBuffer+len),"%s     %s:%i", 
						GetState(TcpList->table[i].dwState), 
						ToStringIp(szIp,TcpList->table[i].dwRemoteAddr), 
						ntohs((short)TcpList->table[i].dwRemotePort) 
					); 
					if (hRoot == NULL) hRoot=AddItem("Netstat",m_hRoot,m_iIconPort,TREE_NETSTAT_MAIN); 
					if (TcpList->table[i].dwState != 5) AddItem(szBuffer,hRoot,m_iIconPort,TREE_NETSTAT_TCP); 
					else AddItem(szBuffer,hRoot,m_iIconPort,TREE_NETSTAT_TCP_OPEN); 
		 
				} 
			} 
		} 
 
		if (NtApi.fnAllocateAndGetUdpExTableFromStack((PMIB_UDPTABLE_EX *)&UdpList,true,GetProcessHeap(),0,2) == NO_ERROR) { 
			for (i=0;idwNumEntries;i++) 
			{	 
				if (UdpList->table[i].dwProcessId == dwPID) { 
		 
					sprintf(szBuffer,"UDP %s:%i", 
						ToStringIp(szIp,UdpList->table[i].dwLocalAddr), 
						ntohs((short)UdpList->table[i].dwLocalPort) 
					); 
					if (hRoot == NULL) hRoot=AddItem("NetStat",m_hRoot,m_iIconPort,TREE_NETSTAT_MAIN); 
					AddItem(szBuffer,hRoot,m_iIconPort,TREE_NETSTAT_UDP); 
				} 
			} 
		} 
		throw(0); 
	} 
	catch(int iError) 
	{ 
		if (UdpList) HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,UdpList); 
		if (TcpList) HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,TcpList); 
		return iError; 
	} 
	return -1; 
} 
 
/*  
Function Description: 
	Kills a Tcp connection  
	Called by: CProcInfo::Commands 
Arguments: 
IN	hWnd,		Handle to owner window 
IN	szTcp,		Pointer to string "TCP 127.0.0.1:80     CONNECTED   127.0.0.1:90" 
Returns: 
    void 
*/ 
 
void CProcInfo::KillTcpConnection(HWND hWnd,char *szTcp) 
{ 
	MIB_TCPROW KillCon; 
	 
	try { 
		if (!NtApi.fSetTcpEntry) { 
			throw(0); 
		} 
		char *pbuf,*pbuf2; 
		if (strncmp(szTcp,"TCP ",4) == 0) { 
 
			//get local address 
			pbuf=strchr(szTcp+4,':'); 
 
			if (!pbuf) throw(-1); 
			 
			*pbuf=0; 
 
			KillCon.dwLocalAddr=inet_addr(szTcp+4); 
 
			if (KillCon.dwLocalAddr ==  INADDR_NONE) throw(-1); 
 
			pbuf++; 
 
			//get local port 
			pbuf2=strchr(pbuf,' '); 
 
			if (!pbuf2) throw(-1); 
			*pbuf2=0; 
			KillCon.dwLocalPort=htons(atoi(pbuf)); 
 
			if (KillCon.dwLocalPort == 0) throw(-1); 
			 
			pbuf2++; 
 
			//get remote address 
 
			//find last space 
			pbuf=strrchr(pbuf2,' '); 
			 
			if (!pbuf) throw(-1); 
			pbuf++; 
 
			pbuf2=strchr(pbuf,':'); 
 
			if (!pbuf2) throw(-1); 
 
			*pbuf2=0; 
			 
			KillCon.dwRemoteAddr=inet_addr(pbuf); 
 
			if (KillCon.dwRemoteAddr == INADDR_NONE) throw(-1); 
 
			pbuf2++; 
 
			//get remote port 
 
			KillCon.dwRemotePort=htons(atoi(pbuf2)); 
 
			if (KillCon.dwRemotePort == 0) throw(-1); 
 
			KillCon.dwState=MIB_TCP_STATE_DELETE_TCB; 
 
			//finaly try to close the port 
			if (NtApi.fSetTcpEntry(&KillCon) != NO_ERROR) throw(-2); 
			 
 
			//if success reload tree view 
			SetInfo(-2); 
 
		} 
		else throw(-1); 
 
	} 
	catch(int iError) 
	{ 
		if (iError == -2) ShowError(hWnd,"Could not close port"); 
		else if (iError == -1) ShowError(hWnd,"Could not close port invalid parameters"); 
		else if (iError == 0) ShowError(hWnd,"Could not load SetTcpEntry API"); 
	} 
} 
 
/*  
Function Description: 
	Get services regestered in a process 
	Called by: SetInfo 
Arguments: 
IN	dwPID,	Process io 
Returns: 
    void 
*/ 
 
void CProcInfo::GetServicesForProc(DWORD dwPID) 
{ 
	if (!NtApi.fEnumServicesStatusExA) { 
		return; 
	} 
 
	ENUM_SERVICE_STATUS_PROCESSA *lpServiceStatus; 
 
	DWORD	dwSize=0, 
			dwNumServices=0, 
			dwResumeHandle=0, 
			dwCount; 
 
	SC_HANDLE scHandle=NULL; 
	 
	int iRet; 
 
	void *Buffer=NULL; 
		 
	char szBuffer[512]; 
	 
	HTREEITEM hChildItem,hRoot=NULL; 
 
	try { 
		scHandle=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 
 
 
		if (!scHandle) throw(0); 
		 
		//get size 
 
		iRet=NtApi.fEnumServicesStatusExA( 
				scHandle, 
				0, 
				0x00000030, 
				1, 
				(LPBYTE)Buffer, 
				0, 
				&dwSize, 
				&dwNumServices, 
				&dwResumeHandle, 
				0 
		); 
 
		Buffer=malloc(dwSize); 
 
		if (!Buffer) throw(0); 
	 
		dwResumeHandle=0; 
 
		//get services 
 
		iRet=NtApi.fEnumServicesStatusExA( 
					scHandle, 
					0, 
					0x00000030, 
					1, 
					(LPBYTE)Buffer, 
					dwSize, 
					&dwSize, 
					&dwNumServices, 
					&dwResumeHandle, 
					0 
			); 
 
		if (!iRet) throw(0); 
 
		lpServiceStatus=(ENUM_SERVICE_STATUS_PROCESSA *)Buffer; 
 
		for (dwCount=0;dwCount