www.pudn.com > Process_Mo18292312142004.rar > HandleList.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;
CHandleInfo::CHandleInfo(CWindow *CWnd)
{
m_CWnd=CWnd;
m_iListSize=0;
m_dwOldItem=0;
m_hPopup=NULL;
}
CHandleInfo::~CHandleInfo()
{
}
void CHandleInfo::ClipBoardHandle(HWND hWnd,DWORD dwItem)
{
char szBigBuf[MAX_PATH * 2];
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);
m_CWnd->SetClipBoardText(szBigBuf);
}
void CHandleInfo::Commands(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
int iItem=SendMessage(m_hHandleList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
if (iItem == -1) return;
switch(LOWORD(wParam))
{
case HANDLE_CLIP:
ClipBoardHandle(m_hHandleList,iItem);
break;
}
return;
}
void CHandleInfo::Notify(HWND hWnd,WPARAM wParam,LPARAM lParam)
{
NMHDR *nmt=(NMHDR *)lParam;
if (nmt->code == NM_RCLICK) {//right click
if (!m_hPopup) {
m_hPopup=GetSubMenu(m_CWnd->m_hListViewPopup,2);
}
POINT pt;
GetCursorPos(&pt);
TrackPopupMenu(m_hPopup,TPM_LEFTALIGN ,pt.x,pt.y,0,hWnd,NULL);
}
}
HWND CHandleInfo::HandleListView(HWND hWnd,HINSTANCE hInst)
{
m_hHandleList=CreateWindowEx(
WS_EX_CLIENTEDGE,
"SysListView32",
NULL,
WS_CHILD | WS_VISIBLE | LVS_SINGLESEL | LVS_REPORT | LVS_SHOWSELALWAYS,
0,
0,
0,
0,
hWnd,
NULL,
hInst,
NULL
);
if (!m_hHandleList) {
return NULL;
}
SendMessage(
m_hHandleList,
LVM_SETEXTENDEDLISTVIEWSTYLE,
0,
LVS_EX_FULLROWSELECT
#ifdef SHOW_GRIDLINES
| LVS_EX_GRIDLINES
#endif
);
//add columns to the listview
LVCOLUMN lvc;
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
lvc.pszText="Name";
lvc.cx=920;
SendMessage(m_hHandleList, LVM_INSERTCOLUMN, 0,(long)&lvc);
lvc.pszText="Type";
lvc.cx=90;
SendMessage(m_hHandleList, LVM_INSERTCOLUMN, 0,(long)&lvc);
return m_hHandleList;
}
//struct. for HandleToFileName thread used to pass parameters to it and to get return value's
typedef struct {
HANDLE hLocal; //IN handle to file
NTSTATUS nRet; //OUT return value from fNtQueryInformationFile
UCHAR Buffer[1000]; //OUT buffer where the filename is stored when the thread returns
} HANDLE_TO_NAME_INFO;
/*
GetFileName from handle
run this in a diferent thread because sometimes it just doesnt return
now we execute the thread and if it doesnt return after x sec. we terminate the thread
i gues this happens because we dont have access to the handle and this was the only solution i could find
*/
DWORD WINAPI HandleToFileName(void *lpParam)
{
HANDLE_TO_NAME_INFO *hInfo=(HANDLE_TO_NAME_INFO *)lpParam;
IO_STATUS_BLOCK isb;
hInfo->nRet = NtApi.fNtQueryInformationFile(hInfo->hLocal, &isb,hInfo->Buffer,sizeof(hInfo->Buffer), 9);
return 0;
}
int CHandleInfo::SetInfo(int iItem)
{
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
void *Buffer=NULL,
*ObjBuffer=NULL;
HANDLE hProc=NULL,
hLocal=NULL;
LVITEMA lvi;
lvi.mask=LVIF_TEXT;
lvi.iItem=-1;
try {
if (!NtApi.fNtQueryInformationThread ||
!NtApi.fNtQueryInformationProcess ||
!NtApi.fNtQueryInformationFile ||
!NtApi.fNtQuerySystemInformation ||
!NtApi.fNTQueryObject) {
throw(0);
}
SYSTEM_HANDLE_INFORMATION *shi;
NTSTATUS nStatus;
Buffer = malloc(sizeof(SYSTEM_HANDLE_INFORMATION));
if (Buffer == NULL) throw(0);
//get number of handles
nStatus=NtApi.fNtQuerySystemInformation(SystemHandleInformation,Buffer,sizeof(SYSTEM_HANDLE_INFORMATION),0);
if (nStatus != STATUS_INFO_LENGTH_MISMATCH && nStatus != 0) {
throw(0);
}
shi=(SYSTEM_HANDLE_INFORMATION *)Buffer;
int iSize;
iSize=shi->NumberOfHandles;
free(Buffer);
//get a buffer that can store all handles
Buffer = malloc(sizeof(SYSTEM_HANDLE_INFORMATION) * iSize + 4);
if (Buffer == NULL) throw(0);
/*
Fill the buffer
NOTE: the buffer contains all handles from all processes
so we need to filter out only to handles from the process we are interested in
*/
nStatus=NtApi.fNtQuerySystemInformation(SystemHandleInformation,Buffer,iSize * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) + 4 ,0);
if (nStatus != 0) throw(0);
shi=(SYSTEM_HANDLE_INFORMATION *)Buffer;
int i;
SYSTEM_HANDLE_TABLE_ENTRY_INFO *sht;
sht=(SYSTEM_HANDLE_TABLE_ENTRY_INFO *)((int)Buffer+4);
//open the process with PROCESS_DUP_HANDLE access
hProc=OpenProcess(PROCESS_DUP_HANDLE,true,m_Proc.dwPID);
if (hProc == NULL) throw(0);
HANDLE hThisProc;
hThisProc=GetCurrentProcess();
OBJECT_TYPE_INFO *ObjTypeInfo;
OBJECT_NAME_INFO *lpObjNameInfo;
DWORD dwSize=0;
char szBuffer[MAX_PATH];
char szName[MAX_PATH];
//dont redraw to listview before we are ready
SendMessage(m_hHandleList,WM_SETREDRAW,false,0);
//loop true all handles
for(i=0;i < iSize;i++)
{
if (hLocal) CloseHandle(hLocal);
if (sht[i].UniqueProcessId != m_Proc.dwPID) continue; //dont need this handle its from a other process go to the next
//dublicate the handle
if (DuplicateHandle( hProc, (void *)sht[i].HandleValue, GetCurrentProcess(), &hLocal, 0, FALSE, DUPLICATE_SAME_ACCESS ) == 0) {
continue;
}
//get the size of buffer needed to store OBJECT_TYPE_INFO
nStatus=NtApi.fNTQueryObject(hLocal,ObjectTypeInfo,0,0,&dwSize);
if (nStatus != STATUS_INFO_LENGTH_MISMATCH || dwSize < 1) {
continue;
}
ObjBuffer=malloc(dwSize);
if (ObjBuffer == NULL) {
continue;
}
//get OBJECT_TYPE_INFO
nStatus=NtApi.fNTQueryObject(hLocal,ObjectTypeInfo,ObjBuffer,dwSize,&dwSize);
if (nStatus != 0) {
continue;
}
ObjTypeInfo=(OBJECT_TYPE_INFO *)ObjBuffer;
if (
//its a unicode string convert it to anci string
WideCharToMultiByte(
CP_ACP,
0,
(wchar_t *)ObjTypeInfo->ObjectTypeName.Buffer,
ObjTypeInfo->ObjectTypeName.Length,
szBuffer,
MAX_PATH,
NULL,
NULL
) == 0) {
//failed free buffer and continue
free(ObjBuffer);
continue;
}
free(ObjBuffer);
lvi.pszText=szBuffer;
lvi.iSubItem=0;
lvi.iItem++;
//add the typename of the handle to the listview
if (lvi.iItem >= m_iListSize) m_CWnd->mySendMessage(m_hHandleList, LVM_INSERTITEM, 0,(LPARAM)&lvi);
else m_CWnd->mySendMessage(m_hHandleList, LVM_SETITEM, 0,(LPARAM)&lvi);
//try to find the name of the handle
*szName=0;
if (stricmp(szBuffer,"File") == 0) {
//its a file
HANDLE_TO_NAME_INFO hInfo;
DWORD dwThreadId;
HANDLE hThread;
hInfo.hLocal=hLocal;
hThread=CreateThread(NULL,10,(LPTHREAD_START_ROUTINE)HandleToFileName,&hInfo,0,&dwThreadId);
if (hThread) {
/*
waith 50 miliseconds for the thread to return if it doesnt terminate the thread
fNtQueryInformationFile sometimes never returns this was the only "solution" i could find
*/
if (WaitForSingleObject(hThread,50) == WAIT_TIMEOUT)
{
//memory leak here
TerminateThread(hThread,0);
}
else if (hInfo.nRet == 0 && *(int *)hInfo.Buffer < 1000) {
if (WideCharToMultiByte(
CP_ACP,
0,
(wchar_t *)hInfo.Buffer+2,
*(int *)hInfo.Buffer,
szName,
sizeof(szName),
NULL,
NULL
) == 0) {
*szName=0;
}
else szName[*(int *)hInfo.Buffer/2]=0;
}
CloseHandle(hThread);
}
}
else if (stricmp(szBuffer,"Process") == 0) {
//its a process handle so try to get pid and process name
PROCESS_BASIC_INFORMATION pProcInfo;
if (NtApi.fNtQueryInformationProcess(hLocal, 0,&pProcInfo, sizeof(PROCESS_BASIC_INFORMATION), &dwSize) == 0) {
HANDLE hTemp=OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,pProcInfo.UniqueProcessId);
if (hTemp) {
PROCESSLIST Proc;
if (m_CWnd->CProc->GetProcessInfoFromPid(&Proc,pProcInfo.UniqueProcessId) == ERR_SUCCESS) {
strcpy(szName,Proc.pProcessName);
}
else strcpy(szName,"Unknown"); //process is death??
CloseHandle(hTemp);
strcpy(szName+strlen(szName)," PID: ");
inttochar(szName+strlen(szName),pProcInfo.UniqueProcessId,sizeof(szName) - strlen(szName));
}
}
}
else if (stricmp(szBuffer,"Thread") == 0) {
//its a thread handle so try to get thread id and proc id and name of the proc
THREAD_BASIC_INFORMATION ThreadInfo;
if (NtApi.fNtQueryInformationThread(hLocal,0,&ThreadInfo,sizeof(ThreadInfo),&dwSize) == 0) {
PROCESSLIST Proc;
char szTemp[MAX_PATH];
if (m_CWnd->CProc->GetProcessInfoFromPid(&Proc,(DWORD)ThreadInfo.ClientId.UniqueProcess) == ERR_SUCCESS) {
strcpy(szTemp,Proc.pProcessName);
}
else strcpy(szTemp,"Unknown");
sprintf(szName,"%s Proc Id: %i Thread Id: %i",szTemp,ThreadInfo.ClientId.UniqueProcess,ThreadInfo.ClientId.UniqueThread);
}
}
//if we still dont have the name of the handle..
if (*szName == 0) {
//try the default way to get the name of the handle
//get size of needed buffer
nStatus=NtApi.fNTQueryObject(hLocal,ObjectNameInfo,0,0,&dwSize);
if (nStatus == STATUS_INFO_LENGTH_MISMATCH) {
ObjBuffer=malloc(dwSize);
if (ObjBuffer) {
if (NtApi.fNTQueryObject(hLocal,ObjectNameInfo,ObjBuffer,dwSize,&dwSize) == 0) {
lpObjNameInfo=(OBJECT_NAME_INFO *)ObjBuffer;
WideCharToMultiByte(
CP_ACP,
0,
(wchar_t *)lpObjNameInfo->ObjectName.Buffer,
lpObjNameInfo->ObjectName.Length,
szName,
sizeof(szName),
NULL,
NULL
);
}
free(ObjBuffer);
}
}
}
//if we have a name for the handle add it to the list
if (*szName) {
lvi.iSubItem=1;
lvi.pszText=szName;
m_CWnd->mySendMessage(m_hHandleList, LVM_SETITEM, 0,(LPARAM)&lvi);
}
}
throw(i);
}
catch(int iError)
{
if (hProc) CloseHandle(hProc);
if (hLocal) CloseHandle(hLocal);
if (Buffer) free(Buffer);
//delete old items
while (lvi.iItem <= m_iListSize) {
SendMessage(m_hHandleList,LVM_DELETEITEM,m_iListSize,0);
m_iListSize--;
}
//draw the listview
SendMessage(m_hHandleList,WM_SETREDRAW,true,0);
m_iListSize=lvi.iItem;
return iError;
}
return 0;
}