www.pudn.com > Process_Mo18292312142004.rar > ModuleList.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; 
CModuleInfo *g_CModule; 
 
 
CModuleInfo::CModuleInfo(CWindow *CWnd) 
{ 
	m_CWnd=CWnd; 
	m_iListSize=0; 
	m_hPopup=NULL; 
	m_dwOldItem=0; 
} 
 
 
void CModuleInfo::Commands(HWND hWnd,WPARAM wParam,LPARAM lParam) 
{ 
	int iItem=SendMessage(m_hModuleList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 
	if (iItem == -1) return; 
 
	switch(LOWORD(wParam)) 
	{ 
	case DLL_PROPERTIES: 
		{ 
			char szBuffer[MAX_PATH]; 
			LVITEMA lvi; 
			lvi.mask=LVIF_TEXT; 
			lvi.iSubItem=4; 
			lvi.iItem=iItem; 
			lvi.pszText=szBuffer; 
			lvi.cchTextMax=sizeof(szBuffer); 
			if (SendMessage(m_hModuleList,LVM_GETITEM,0,(LPARAM)&lvi)) OpenFileProperties(hWnd,lvi.pszText); 
		} 
		break; 
	case DLL_CLIP: 
		ClipBoardModule(m_hModuleList,iItem,false); 
		break; 
	case DLL_UNLOAD: 
		UnloadDll(hWnd,iItem,false); 
		break; 
 
	} 
} 
 
void CModuleInfo::Notify(HWND hWnd,WPARAM wParam,LPARAM lParam) 
{ 
	NMHDR *nmt=(NMHDR *)lParam; 
	if (nmt->code == NM_RCLICK) { 
		if (!m_hPopup) { 
			m_hPopup=GetSubMenu(m_CWnd->m_hListViewPopup,1); 
		} 
 
		POINT pt; 
		GetCursorPos(&pt); 
 
		TrackPopupMenu(m_hPopup,TPM_LEFTALIGN	,pt.x,pt.y,0,hWnd,NULL); 
	} 
	else if (nmt->code == NM_DBLCLK) { 
 
		int iItem=SendMessage(nmt->hwndFrom, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 
		if (iItem == -1) return;	 
		char szBuffer[MAX_PATH]; 
		LVITEMA lvi; 
		lvi.mask=LVIF_TEXT; 
 
		//if message comes from search window fullpath to dll is in subitem 6 
		if (nmt->idFrom == IDC_LIST1) lvi.iSubItem=6; 
		else lvi.iSubItem=4; 
 
		lvi.iItem=iItem; 
		lvi.pszText=szBuffer; 
		lvi.cchTextMax=sizeof(szBuffer); 
 
		//load fileinfo 
		if (SendMessage(nmt->hwndFrom,LVM_GETITEM,0,(LPARAM)&lvi)) OpenFileProperties(hWnd,lvi.pszText); 
 
	} 
} 
 
void CModuleInfo::ClipBoardModule(HWND hWnd,DWORD dwItem,bool bIsSearchWnd) 
{ 
	char szBigBuf[MAX_PATH * 6]; 
	char szBuffer[MAX_PATH]; 
	*szBigBuf=0; 
	LVITEMA lvi; 
	lvi.mask=LVIF_TEXT; 
	lvi.iSubItem=0; 
	lvi.iItem=dwItem; 
	lvi.pszText=szBuffer; 
	lvi.cchTextMax=sizeof(szBuffer)-1; 
	if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcpy(szBigBuf,szBuffer); 
 
	lvi.iSubItem=1; 
	szBuffer[0]=' '; 
	lvi.pszText=szBuffer+1; 
 
	if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
	 
	lvi.iSubItem=2; 
 
	if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
 
	lvi.iSubItem=3; 
 
	if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
 
	lvi.iSubItem=4; 
 
	if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
 
	//if it is the search window we have 2 more columns 
	if (bIsSearchWnd) { 
		lvi.iSubItem=5; 
 
		if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
 
		lvi.iSubItem=6; 
 
		if (SendMessage(hWnd,LVM_GETITEM,0,(LPARAM)&lvi)) strcat(szBigBuf,szBuffer); 
	} 
 
	m_CWnd->SetClipBoardText(szBigBuf); 
} 
 
 
void CModuleInfo::UnloadDll(HWND hWnd,DWORD dwItem,bool bIsSearchWnd) 
{ 
	/* 
	Unload the dll from the remote proc. 
	this only works if the dll is loaded with LoadLibrary  
	this function is usefull to unload dll's that are loaded in a process with CreateRemoteThread 
	to bypass software firewalls 
	Warning if the process is still using this dll it will crash 
	it doesnt know that its unloaded 
	*/ 
 
	char szBuffer[MAX_PATH]; 
	LVITEMA lvi; 
	lvi.mask=LVIF_TEXT; 
	if (bIsSearchWnd) lvi.iSubItem=2; 
	else lvi.iSubItem=0; 
	lvi.iItem=dwItem; 
	lvi.pszText=szBuffer; 
	lvi.cchTextMax=sizeof(szBuffer); 
	if (!SendMessage(m_hModuleList,LVM_GETITEM,0,(LPARAM)&lvi)) return; 
 
	HANDLE hProc=NULL; 
	DWORD dwPID; 
 
	try { 
		UNLOADDLL Data; 
 
		HMODULE hKernel=GetModuleHandle("kernel32.dll"); 
		HMODULE hNtdll=GetModuleHandle("ntdll.dll"); 
 
		if (!hKernel || !hNtdll) throw("Could not load dll's"); 
 
		Data.fLdrUnloadDll=(pLdrUnloadDll)GetProcAddress(hNtdll,"LdrUnloadDll"); 
		Data.fGetModuleHandle=(pGetModuleHandle)GetProcAddress(hKernel,"GetModuleHandleA"); 
		strcpy(Data.szLibName,szBuffer); 
 
		if (!Data.fLdrUnloadDll || !Data.fGetModuleHandle) throw("Could not load needed api's"); 
		 
		if (bIsSearchWnd) { 
			//its the search window get the pid from the listview 
			lvi.iSubItem=1; 
			if (!SendMessage(m_hModuleList,LVM_GETITEM,0,(LPARAM)&lvi) || 
				(dwPID=atoi(szBuffer)) == 0) throw("Invalid Parameters"); 
			 
		} 
		else dwPID=m_Proc.dwPID;//else the pid is stored in PROCESSLIST 
 
		HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,false,dwPID); 
 
		if (!hProc) throw("Error opening process"); 
 
		//remote thread returns GetModuleHandle so if it is null dll is unloaded 
		if (RemoteThread(hProc, RemoteUnloadLib,300,&Data,sizeof(Data)) == NULL) { 
			throw("Dll unloaded from process"); 
		} 
		else throw("Could not unload this dll"); 
	} 
	catch(char *szError) 
	{ 
		ShowError(hWnd,szError); 
	} 
 
	if (hProc) CloseHandle(hProc); 
	//reload listview if its not the Search window 
	if (!bIsSearchWnd) SetInfo(-2); 
	return; 
} 
 
HWND CModuleInfo::ModuleListView(HWND hWnd,HINSTANCE hInst) 
{ 
 
	m_hModuleList=CreateWindowEx( 
							WS_EX_CLIENTEDGE, 
							"SysListView32", 
							NULL, 
							WS_CHILD | WS_VISIBLE | LVS_SINGLESEL | LVS_REPORT | LVS_SHOWSELALWAYS, 
							0,  
							0, 
							0, 
							0,  
							hWnd,  
							0, 
							hInst,  
							NULL 
							); 
 
	if (!m_hModuleList) { 
		return NULL; 
	} 
 
	InsertColumns(m_hModuleList); 
 
	return m_hModuleList; 
} 
 
void CModuleInfo::InsertColumns(HWND hWnd) 
{ 
	//add columns to the module listview 
	SendMessage( 
		hWnd,  
		LVM_SETEXTENDEDLISTVIEWSTYLE,  
		0,  
		LVS_EX_FULLROWSELECT  
#ifdef SHOW_GRIDLINES 
		|  LVS_EX_GRIDLINES  
#endif 
		); 
 
 
	LVCOLUMN lvc; 
 
    lvc.mask = LVCF_TEXT | LVCF_WIDTH; 
 
	lvc.pszText="Full Path"; 
	lvc.cx=240; 
 
	SendMessage(hWnd, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
	lvc.pszText="Version"; 
	lvc.cx=200; 
 
	SendMessage(hWnd, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
 
	lvc.pszText="Company Name"; 
	lvc.cx=140; 
 
	SendMessage(hWnd, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
 
	lvc.pszText="Description"; 
	lvc.cx=240; 
 
	SendMessage(hWnd, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
	lvc.pszText="Module"; 
	lvc.cx=105; 
 
	SendMessage(hWnd, LVM_INSERTCOLUMN, 0,(long)&lvc); 
	 
	return; 
} 
 
 
int CModuleInfo::SetInfo(int iItem) 
{ 
	//fill the module listview 
	if (iItem == -2) iItem=m_dwOldItem; 
	 
	m_dwOldItem=iItem;	 
 
	if (m_CWnd->CProc->GetProcessInfo(&m_Proc,iItem) != ERR_SUCCESS) return 0; 
 
	if (m_Proc.dwPID == 0) return 0;//system idle process 
	 
	if (m_Proc.dwPID == 4) { 
		//system process get drivers 
		GetDrivers(iItem); 
		return 0; 
	} 
 
	//load needed api's 
	if (!NtApi.fEnumProcesses ||  
		!NtApi.fEnumProcessModules ||  
		!NtApi.fGetModuleFileNameEx 
		) { 
			return -1; 
	} 
	 
	HANDLE hProcess=NULL; 
 
	DWORD dwSize; 
	int iNumModules; 
	char VersionInfo[3][128]; 
	char szModuleName[MAX_PATH]; 
	char *pModule; 
 
	HMODULE *hModules=NULL; 
	 
	LVITEMA lvi; 
	lvi.iItem=0; 
 
	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 
                           false, 
						   m_Proc.dwPID 
						   ); 
 
	try { 
 
		if (hProcess == NULL) 
			throw(0); 
 
		//get size 
		if (!NtApi.fEnumProcessModules(hProcess, NULL, 0, &dwSize)) 
			throw(0); 
	 
		hModules = new HMODULE[dwSize / sizeof(HMODULE)]; 
 
		if (hModules == NULL) throw(0); 
 
		if (!NtApi.fEnumProcessModules(hProcess, hModules,dwSize, &dwSize))  
			throw(0); 
		 
		//get number of modules 
		iNumModules = dwSize / sizeof(HMODULE);  
		int i; 
 
		//disable redraw (this looks better) 
		SendMessage(m_hModuleList,WM_SETREDRAW,false,0); 
	 
        for (i=0,lvi.iItem=0;i= m_iListSize) m_CWnd->mySendMessage(m_hModuleList, LVM_INSERTITEM, 0,(LPARAM)&lvi);	 
				else m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(LPARAM)&lvi); 
				lvi.mask=LVIF_TEXT; 
				lvi.iSubItem=4; 
				lvi.pszText=szModuleName; 
 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(LPARAM)&lvi); 
				 
				//get file info 
				char *pFile=GetFileName(szModuleName); 
 
				GetFileInfo(pFile,(char *)VersionInfo,128,3); 
			 
				lvi.iSubItem=1; 
				lvi.pszText=VersionInfo[0]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(LPARAM)&lvi); 
				lvi.iSubItem=2; 
				lvi.pszText=VersionInfo[1]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(LPARAM)&lvi); 
				lvi.iSubItem=3; 
				lvi.pszText=VersionInfo[2]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(LPARAM)&lvi); 
				lvi.iItem++;				 
            } 
        } 
		 
		throw(lvi.iItem); 
    } 
 
	catch(int iError) 
	{ 
		if (hProcess) CloseHandle(hProcess); 
		if (hModules) delete hModules; 
		if (m_CWnd->m_iDataOption == MES_NORMAL) { 
			//delete old items if the list is smaller than previus one 
			while (lvi.iItem <= m_iListSize) { 
				SendMessage(m_hModuleList,LVM_DELETEITEM,m_iListSize,0); 
				m_iListSize--; 
			} 
		} 
		//draw the list 
		SendMessage(m_hModuleList,WM_SETREDRAW,true,0); 
        
		m_iListSize = lvi.iItem; 
		return iError; 
	} 
 
	return 0; 
} 
 
 
int CModuleInfo::GetDrivers(int iItem) 
{ 
	//almost the same as SetInfo() only now get drivers 
 
	DWORD *lpImageBase=NULL; 
	LVITEMA lvi; 
	lvi.iItem=0; 
 
	try { 
		if (!NtApi.fEnumDeviceDrivers || !NtApi.fGetDeviceDriverFileName) { 
			throw(0); 
		} 
 
		DWORD dwSize=0; 
		DWORD *lpImageBase; 
		int iSize=1024; 
 
		lpImageBase = new DWORD[iSize]; 
 
		if (!lpImageBase) throw(0); 
 
		if (!NtApi.fEnumDeviceDrivers((void **)lpImageBase,iSize * sizeof(DWORD),&dwSize)) throw(0); 
 
		if (dwSize > (iSize * sizeof(DWORD))) { 
			delete lpImageBase; 
			 
			iSize=dwSize / sizeof(DWORD); 
			lpImageBase = new DWORD[iSize]; 
 
			if (!lpImageBase) throw(0); 
 
			if (!NtApi.fEnumDeviceDrivers((void **)lpImageBase,iSize * sizeof(DWORD),&dwSize)) throw(0); 
		} 
 
		char VersionInfo[3][128]; 
		char szDriverName[MAX_PATH]; 
		char szSystemDir[MAX_PATH]; 
		char *pDriver, 
			 *pBuf; 
		int i=0,x=dwSize / sizeof(DWORD); 
		 
		GetSystemDirectory(szSystemDir,MAX_PATH); 
		strcat(szSystemDir,"\\Drivers\\"); 
		pBuf=szSystemDir+strlen(szSystemDir); 
 
		SendMessage(m_hModuleList,WM_SETREDRAW,false,0); 
        
		while (i < x) { 
			if (NtApi.fGetDeviceDriverFileName((void *)lpImageBase[i],szDriverName,MAX_PATH)) { 
 
				pDriver=szDriverName+strlen(szDriverName); 
							 
				while (pDriver != szDriverName && *pDriver != '\\') pDriver--; 
 
				if (*pDriver == '\\') pDriver++; 
 
				lvi.iSubItem=0; 
				lvi.pszText=pDriver; 
				lvi.mask=LVIF_TEXT | LVIF_PARAM; 
				lvi.lParam=(LPARAM)iItem; 
				if (lvi.iItem >= m_iListSize) m_CWnd->mySendMessage(m_hModuleList, LVM_INSERTITEM, 0,(long)&lvi);	 
				else m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(long)&lvi); 
 
				char *pFile=GetFileName(szDriverName); 
 
				if ( 
					!GetFileInfo(pFile,(char *)VersionInfo,128,3) &&  
					pDriver == szDriverName 
				){ //no full path 
					strcpy(pBuf,szDriverName);		 
					if (GetFileInfo(szSystemDir,(char *)VersionInfo,128,3)) { 
						strcpy(szDriverName,szSystemDir); 
					}	 
				} 
 
				lvi.mask=LVIF_TEXT; 
				lvi.iSubItem=4; 
				lvi.pszText=pFile; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(long)&lvi); 
 
				 
				lvi.iSubItem=1; 
				lvi.pszText=VersionInfo[0]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(long)&lvi); 
				lvi.iSubItem=2; 
				lvi.pszText=VersionInfo[1]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(long)&lvi); 
				lvi.iSubItem=3; 
				lvi.pszText=VersionInfo[2]; 
				m_CWnd->mySendMessage(m_hModuleList, LVM_SETITEM, 0,(long)&lvi); 
				 
				lvi.iItem++; 
			} 
			i++; 
			 
		} 
		throw (lvi.iItem); 
	} 
	catch (int iError)  
	{ 
		if (lpImageBase) delete lpImageBase; 
		 
		if (iError == 0) SendMessage(m_hModuleList,LVM_DELETEALLITEMS,0,0); 
 
		if (m_CWnd->m_iDataOption == MES_NORMAL) { 
			while (lvi.iItem <= m_iListSize) { 
				SendMessage(m_hModuleList,LVM_DELETEITEM,m_iListSize,0); 
				m_iListSize--; 
			}  
		} 
		SendMessage(m_hModuleList,WM_SETREDRAW,true,0); 
        
		m_iListSize = lvi.iItem; 
 
		return iError; 
	} 
} 
 
 
//proc for the Search dialog 
 
BOOL CALLBACK FindDlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(Msg) 
    { 
	case WM_NOTIFY: 
	{ 
		g_CModule->Notify(hWnd,wParam,lParam); 
		break; 
	} 
	case WM_SIZE: 
	{ 
		RECT rc; 
		GetClientRect(hWnd,&rc); 
		SetWindowPos(GetDlgItem(hWnd,IDC_LIST1), NULL, 5, 49,rc.right-10,rc.bottom-54, SWP_NOZORDER); 
		break; 
	} 
	case WM_INITDIALOG: 
	{ 
		HWND hList=GetDlgItem(hWnd,IDC_LIST1); 
 
		//add moduleinfo columns to list 
		g_CModule->InsertColumns(hList); 
 
		//add columns pid and process to list 
		LVCOLUMN lvc; 
		lvc.mask = LVCF_TEXT | LVCF_WIDTH; 
		lvc.pszText="PID"; 
		lvc.cx=40; 
		SendMessage(hList, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
		lvc.pszText="Process"; 
		lvc.cx=70; 
		SendMessage(hList, LVM_INSERTCOLUMN, 0,(long)&lvc); 
 
		//set icon 
		SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(GetModuleHandle(NULL),MAKEINTRESOURCE(ID_ICON_FIND)));	 
 
		break; 
	} 
	case WM_COMMAND: 
	{ 
		int iItem; 
		//if it is from the list get the selected item 
		if (LOWORD(wParam) >= DLL_PROPERTIES && LOWORD(wParam) <= DLL_UNLOAD) { 
			iItem=SendMessage(GetDlgItem(hWnd,IDC_LIST1), LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 
			if (iItem == -1) break; 
		} 
 
		switch(LOWORD(wParam)) 
		{ 
		case IDC_BUTTON1://search button 
		{ 
			char szText[MAX_PATH]; 
			if (GetDlgItemText(hWnd,IDC_EDIT1,szText,sizeof(szText)) == 0) break; 
			g_CModule->StartSearch(hWnd,szText); 
			break; 
		} 
		case IDC_BUTTON2://cancel button 
			EndDialog(hWnd, IDCANCEL); 
			break; 
		//commands comming from the popup 
		case DLL_PROPERTIES: 
		{ 
			char szBuffer[MAX_PATH]; 
			LVITEMA lvi; 
			lvi.mask=LVIF_TEXT; 
			lvi.iSubItem=6; 
			lvi.iItem=iItem; 
			lvi.pszText=szBuffer; 
			lvi.cchTextMax=sizeof(szBuffer); 
			if (SendMessage(GetDlgItem(hWnd,IDC_LIST1),LVM_GETITEM,0,(LPARAM)&lvi)) OpenFileProperties(hWnd,lvi.pszText); 
			break; 
		} 
		case DLL_CLIP: 
			g_CModule->ClipBoardModule(GetDlgItem(hWnd,IDC_LIST1),iItem,true); 
			break; 
		case DLL_UNLOAD: 
			g_CModule->UnloadDll(hWnd,iItem,true); 
			break; 
		} 
        break; 
	} 
	case WM_CLOSE: 
		EndDialog(hWnd, IDCANCEL); 
		break; 
	default: 
		return false; 
    } 
    return true; 
} 
 
void CModuleInfo::StartSearch(HWND hWnd,char *szString) 
{ 
	int i,iNumberItems; 
	char szBuf[MAX_PATH+50]; 
	HWND hList; 
	 
	hList=GetDlgItem(hWnd,IDC_LIST1); 
 
	iNumberItems=SendMessage(m_CWnd->hProcList,LVM_GETITEMCOUNT,0,0); 
 
	//set titlebar to tell the user search has started 
	sprintf(szBuf,"Searching processes for a dll containing string: %s",szString);  
	SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)szBuf); 
 
	m_hModuleList=hList; 
	m_CWnd->iSearchOption=0; 
	strcpy(m_CWnd->szSearchString,szString); 
 
	//clean the listview 
	SendMessage(hList,LVM_DELETEALLITEMS,0,0); 
 
	//loop true all processes in the list 
	for(i=0;i