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; 
}