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