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