Click here to Skip to main content
15,898,134 members
Articles / Desktop Programming / MFC

The Ultimate Toolbox - Updates and User Contributions

Rate me:
Please Sign up or sign in to vote.
4.79/5 (26 votes)
12 Feb 2013CPOL8 min read 257.1K   23.7K   170  
Updates and User Contributions for the Ultimate Toolbox Libraries
// OXProcess.cpp: implementation of the COXProcess class.
//
//////////////////////////////////////////////////////////////////////
// Version: 9.3


#include "stdafx.h"
#include "OXProcess.h"
#include "OXMainRes.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

typedef BOOL (FAR WINAPI *ISDEBUGGERPRESENT) (VOID);

BOOL IsRunningNT()
{
	OSVERSIONINFO	osvi;
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	if(!::GetVersionEx(&osvi))
		return FALSE;
	return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
}


BOOL COXProcess::m_bIsRunningNT=IsRunningNT();

BOOL COXProcess::m_bProcessFunctionsInitialized=FALSE;
HINSTANCE COXProcess::m_hProcessHelperLib=NULL;
// PSAPI functions
PFNENUMPROCESSES COXProcess::pfnEnumProcesses=NULL;
PFNENUMPROCESSMODULES COXProcess::pfnEnumProcessModules=NULL;
PFNGETMODULEFILENAMEEXA COXProcess::pfnGetModuleFileNameExA=NULL;
// Toolhelp32 functions
PFNCREATETOOLHELP32SNAPSHOT COXProcess::pfnCreateToolhelp32Snapshot=NULL;
PFNPROCESS32FIRST COXProcess::pfnProcess32First=NULL;
PFNPROCESS32NEXT COXProcess::pfnProcess32Next=NULL;
PFNMODULE32FIRST COXProcess::pfnModule32First=NULL;
PFNMODULE32NEXT COXProcess::pfnModule32Next=NULL;



//////////////////////////////////////////////////////////////////////
// Destructor
//////////////////////////////////////////////////////////////////////

COXProcess::~COXProcess() 
{
	if(m_bProcessFunctionsInitialized && m_hProcessHelperLib!=NULL)
	{
		::FreeLibrary(m_hProcessHelperLib);
		m_bProcessFunctionsInitialized=FALSE;
		m_hProcessHelperLib=NULL;
	}
}

//////////////////////////////////////////////////////////////////////
// Static Functions
//////////////////////////////////////////////////////////////////////

DWORD COXProcess::GetCurrentProcessID()
{
	return ::GetCurrentProcessId();
}


BOOL COXProcess::GetCurrentProcessEnvironment(CStringArray& arrEnvironmentString)
{

	arrEnvironmentString.RemoveAll();

	// Get a pointer to the environment block. 
	LPVOID lpvEnv=::GetEnvironmentStrings(); 
	if(lpvEnv==NULL)
	{
		TRACE(_T("COXProcess::GetCurrentProcessEnvironment: GetEnvironmentStrings() returned NULL pointer to environment block\n"));
		return FALSE;
	}
 
	// Variable strings are separated by NULL byte, and the block is 
	// terminated by a NULL byte. 
	CString sEnvironmentString;
	LPTSTR lpszVariable=(LPTSTR)lpvEnv;
	for(;;) 
	{ 
		sEnvironmentString=lpszVariable;
		if(sEnvironmentString.IsEmpty())
			break;
		else
		{
			arrEnvironmentString.Add(sEnvironmentString);
			lpszVariable+=(sEnvironmentString.GetLength()+1)*sizeof(TCHAR);
		}
	}
	
	::FreeEnvironmentStrings((LPTSTR)lpvEnv);

	return TRUE;
}
	
BOOL COXProcess::IsDebuggerPresent()
{
	// get handle of the KERNEL.LIB
	BOOL bAlreadyLoaded=TRUE;
	HINSTANCE hKernel=::GetModuleHandle(_T("kernel32.dll"));
	if(hKernel==NULL)
	{
		// load the DLL
		hKernel=::LoadLibrary(_T("kernel32.dll"));
		bAlreadyLoaded=FALSE;
	}

	BOOL bResult=FALSE;

	if(hKernel)
	{
		/*
		You must get this function explicitly because earlier versions
		don't implement this function.
		*/
		ISDEBUGGERPRESENT pIsDebuggerPresent=
			(ISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent");
   
		if(pIsDebuggerPresent)
			bResult=(*pIsDebuggerPresent)();
   
		if(!bAlreadyLoaded)
			::FreeLibrary(hKernel);
	}

	return bResult;
}

BOOL COXProcess::IsValidProcessID(DWORD dwProcessID)
{
	if(GetCurrentProcessID()==dwProcessID || dwProcessID==0 || dwProcessID==2)
		return TRUE;

	// Using the process ID, open up a handle to the process
	HANDLE hProcess=
		::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,dwProcessID);
	if(hProcess!=NULL)
	{
		::CloseHandle(hProcess);
		return TRUE;
	}

	return FALSE;
}

BOOL COXProcess::GetProcessImageFileName(DWORD dwProcessID, CString& sFileName)
{
	COXProcess process(dwProcessID);
	if(!process.IsValid())
		return FALSE;

	return process.GetImageFileName(sFileName);
}

//////////////////////////////////////////////////////////////////////
// Protected Functions
//////////////////////////////////////////////////////////////////////

BOOL COXProcess::InitializeProcessFunctions() const
{
	if(m_bProcessFunctionsInitialized)
		return TRUE;

	if(m_bIsRunningNT)
	{
		m_hProcessHelperLib=::LoadLibrary(_T("PSAPI.DLL"));
		if(m_hProcessHelperLib==NULL)
			return FALSE;

		pfnEnumProcesses=
			(PFNENUMPROCESSES)::GetProcAddress(m_hProcessHelperLib,"EnumProcesses");
		pfnEnumProcessModules=
			(PFNENUMPROCESSMODULES)::GetProcAddress(m_hProcessHelperLib,"EnumProcessModules");
		pfnGetModuleFileNameExA=
			(PFNGETMODULEFILENAMEEXA)::GetProcAddress(m_hProcessHelperLib,"GetModuleFileNameExA");

		if(!pfnEnumProcesses || !pfnEnumProcessModules || !pfnGetModuleFileNameExA)
		{
			::FreeLibrary(m_hProcessHelperLib);
			m_hProcessHelperLib=NULL;
			return FALSE;
		}
	}
	else
	{
		BOOL bWasLoaded=TRUE;
		HINSTANCE m_hProcessHelperLib=::GetModuleHandle(_T("KERNEL32.DLL"));
		if(m_hProcessHelperLib==NULL)
		{
			HINSTANCE m_hProcessHelperLib=::LoadLibrary(_T("KERNEL32.DLL"));
			if(m_hProcessHelperLib==NULL)
				return FALSE;
			bWasLoaded=FALSE;
		}

		pfnCreateToolhelp32Snapshot=
			(PFNCREATETOOLHELP32SNAPSHOT)
			::GetProcAddress(m_hProcessHelperLib,"CreateToolhelp32Snapshot");
		pfnProcess32First=
			(PFNPROCESS32FIRST)::GetProcAddress(m_hProcessHelperLib,"Process32First");
		pfnProcess32Next=
			(PFNPROCESS32NEXT)::GetProcAddress(m_hProcessHelperLib,"Process32Next");
		pfnModule32First=
			(PFNMODULE32FIRST)::GetProcAddress(m_hProcessHelperLib,"Module32First");
		pfnModule32Next=
			(PFNMODULE32NEXT)::GetProcAddress(m_hProcessHelperLib,"Module32Next");
        
		if(!pfnCreateToolhelp32Snapshot || !pfnProcess32First || 
			!pfnProcess32Next || !pfnModule32First || !pfnModule32Next)
		{
			if(!bWasLoaded)
				::FreeLibrary(m_hProcessHelperLib);
			m_hProcessHelperLib=NULL;
			return (FALSE);
		}

		if(bWasLoaded)
			m_hProcessHelperLib=NULL;
	}

	m_bProcessFunctionsInitialized=TRUE;

	return (TRUE);
}


//////////////////////////////////////////////////////////////////////
// Public Functions
//////////////////////////////////////////////////////////////////////

BOOL COXProcess::GetImageFileName(CString& sFileName) const
{
	if(GetCurrentProcessID()==m_dwProcessID)
	{
		LPTSTR pszBuffer=sFileName.GetBuffer(MAX_PATH);
		ASSERT(pszBuffer!=NULL);
		BOOL bResult=(::GetModuleFileName(NULL,pszBuffer,MAX_PATH)>0);
		sFileName.ReleaseBuffer();

		return bResult;
	}

	VERIFY(InitializeProcessFunctions());

	if(m_bIsRunningNT)
	{
		// Using the process ID, open up a handle to the process
		HANDLE hProcess=::OpenProcess(
			PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,m_dwProcessID);
		if(hProcess==NULL)
		{
			if(m_dwProcessID==0)
			{
				VERIFY(sFileName.LoadString(IDS_OX_PROCESSIDLE));//"System Idle Process"
				return TRUE;
			}
			if(m_dwProcessID==2 || m_dwProcessID==8)
			{
				VERIFY(sFileName.LoadString(IDS_OX_PROCESSSYSTEM));//"System"
				return TRUE;
			}
			return FALSE;
		}
            
		HMODULE moduleArray[1024];
		DWORD cbNeeded;
		// EnumProcessModules returns an array of HMODULEs for the process
		if(!pfnEnumProcessModules(hProcess,moduleArray,sizeof(moduleArray),&cbNeeded))
		{
			::CloseHandle(hProcess);
			if(m_dwProcessID==0)
			{
				VERIFY(sFileName.LoadString(IDS_OX_PROCESSIDLE));//"System Idle Process"
				return TRUE;
			}
			if(m_dwProcessID==2 || m_dwProcessID==8)
			{
				VERIFY(sFileName.LoadString(IDS_OX_PROCESSSYSTEM));//"System"
				return TRUE;
			}
			return FALSE;
		}

		// First module is the EXE
		char szModuleName[MAX_PATH];
		// GetModuleFileNameEx is like GetModuleFileName, but works
		// in other process address spaces
		pfnGetModuleFileNameExA(
			hProcess,moduleArray[0],szModuleName,sizeof(szModuleName));
		sFileName=szModuleName;

		::CloseHandle(hProcess);    // We're done with this process handle
	}
	else
	{
	    // Create a ToolHelp32 snapshot containing the process list
	    //  
	    HANDLE hSnapshotProcess;
	    hSnapshotProcess=pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	    if(hSnapshotProcess==NULL)
		{
			return FALSE;
		}

		// Iterate through each of the processes in the snapshot
		PROCESSENTRY32 procEntry={ sizeof(PROCESSENTRY32) };
		BOOL bProcessContinue;
		BOOL bSuccess=FALSE;
		for(bProcessContinue=pfnProcess32First(hSnapshotProcess,&procEntry);
			bProcessContinue;
			bProcessContinue=pfnProcess32Next(hSnapshotProcess,&procEntry))
		{
			if(m_dwProcessID==procEntry.th32ProcessID)
			{
				sFileName=procEntry.szExeFile;
				bSuccess=TRUE;
				break;
			}
		}
    
		::CloseHandle(hSnapshotProcess);    // Done with process list snapshot

		if(!bSuccess)
		{
			return FALSE;
		}
	}

	return TRUE;
}


BOOL COXProcess::GetPriorityClass(DWORD& dwPriorityClass) const
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;

	dwPriorityClass=::GetPriorityClass(hProcess);
	if(dwPriorityClass==0)
	{
		return FALSE;
	}

	return TRUE;
}


BOOL COXProcess::GetVersion(DWORD& dwVersion) const
{
	dwVersion=::GetProcessVersion(m_dwProcessID);
	return TRUE;
}


// Windows NT functions
//

BOOL COXProcess::IsPriorityBoostDisabled(BOOL& bDisabled) const
{
#if (_WIN32_WINNT >= 0x0400)
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;

	return ::GetProcessPriorityBoost(hProcess,&bDisabled);
#else
	UNREFERENCED_PARAMETER(bDisabled);
	return FALSE;
#endif
}

// v9.3 - udpate 03 - 64-bit - use SIZE_T for > VC6, else DWORD - TD
#if _MSC_VER > 1400
BOOL COXProcess::GetMinMaxWorkingSetSize(SIZE_T& dwMinWorkingSetSize, 
										 SIZE_T& dwMaxWorkingSetSize) const
#else
BOOL COXProcess::GetMinMaxWorkingSetSize(DWORD& dwMinWorkingSetSize, 
										 DWORD& dwMaxWorkingSetSize) const
#endif
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;

	return ::GetProcessWorkingSetSize(hProcess,
		&dwMinWorkingSetSize,&dwMaxWorkingSetSize);
}


BOOL COXProcess::GetCreationTime(FILETIME& fileTime) const
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;
	
	FILETIME exitTime, kernelTime, userTime;
	return ::GetProcessTimes(hProcess,&fileTime,&exitTime,&kernelTime,&userTime);
}

BOOL COXProcess::GetCreationTime(CTime& time) const
{
	FILETIME creationTime;
	if(!GetCreationTime(creationTime))
		return FALSE;

	CTime timeCopy(creationTime);
	time=timeCopy;

	return TRUE;
}

BOOL COXProcess::GetCreationTime(COleDateTime& oleTime) const
{
	FILETIME creationTime;
	if(!GetCreationTime(creationTime))
		return FALSE;

	COleDateTime timeCopy(creationTime);
	oleTime=timeCopy;

	return TRUE;
}


BOOL COXProcess::GetExitTime(FILETIME& fileTime) const
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;
	
	FILETIME creationTime, kernelTime, userTime;
	return ::GetProcessTimes(hProcess,&creationTime,&fileTime,&kernelTime,&userTime);
}

BOOL COXProcess::GetExitTime(CTime& time) const
{
	FILETIME creationTime;
	if(!GetExitTime(creationTime))
		return FALSE;

	CTime timeCopy(creationTime);
	time=timeCopy;

	return TRUE;
}

BOOL COXProcess::GetExitTime(COleDateTime& oleTime) const
{
	FILETIME creationTime;
	if(!GetExitTime(creationTime))
		return FALSE;

	COleDateTime timeCopy(creationTime);
	oleTime=timeCopy;

	return TRUE;
}


BOOL COXProcess::GetKernelTime(DWORDLONG& timeSpent) const
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;
	
	FILETIME creationTime, exitTime, kernelTime, userTime;
	if(::GetProcessTimes(hProcess,&creationTime,&exitTime,&kernelTime,&userTime))
	{
		timeSpent=(((DWORDLONG)kernelTime.dwHighDateTime)<<32)+
			((DWORDLONG)kernelTime.dwLowDateTime);
		return TRUE;
	}

	return FALSE;
}


BOOL COXProcess::GetUserTime(DWORDLONG& timeSpent) const
{
	// Using the process ID, open up a handle to the process
	HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
		FALSE,m_dwProcessID);
	if(hProcess==NULL)
		return FALSE;
	
	FILETIME creationTime, exitTime, kernelTime, userTime;
	if(::GetProcessTimes(hProcess,&creationTime,&exitTime,&kernelTime,&userTime))
	{
		timeSpent=(((DWORDLONG)userTime.dwHighDateTime)<<32)+
			((DWORDLONG)userTime.dwLowDateTime);
		return TRUE;
	}

	return FALSE;
}

///////////////////////////////////////////////////////////////////


BOOL COXProcessIterator::MakeSnapshot()
{
	Cleanup();

	if(!InitializeProcessFunctions())
		return FALSE;

	if(m_bIsRunningNT)
	{
		// an array for 1024 processes should be enough :-)
		DWORD pidArray[1024];
		DWORD cbNeeded;
		// EnumProcesses returns an array of process IDs
		if(!pfnEnumProcesses(pidArray,sizeof(pidArray),&cbNeeded))
			return FALSE;

		// Iterate through each process in the array
		for(int nProcess=0; nProcess<(int)(cbNeeded/sizeof(DWORD)); nProcess++)
			m_arrProcesses.Add(pidArray[nProcess]);
	}
	else
	{
	    // Create a ToolHelp32 snapshot containing the process list
	    //  
	    HANDLE hSnapshotProcess;
	    hSnapshotProcess=pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	    if(hSnapshotProcess==NULL)
			return FALSE;

		// Iterate through each of the processes in the snapshot
		PROCESSENTRY32 procEntry={ sizeof(PROCESSENTRY32) };
		BOOL bProcessContinue;
		for(bProcessContinue=pfnProcess32First(hSnapshotProcess,&procEntry);
			bProcessContinue;
			bProcessContinue=pfnProcess32Next(hSnapshotProcess,&procEntry))
		{
			m_arrProcesses.Add(procEntry.th32ProcessID);
		}
    
		::CloseHandle(hSnapshotProcess);    // Done with process list snapshot
	}

	m_bCanIterate=TRUE;

	ASSERT(GetProcessCount()>0);
	m_nCurrentIndex=0;
	m_dwProcessID=m_arrProcesses[0];

	return TRUE;
}


BOOL COXProcessIterator::Next(UINT nOffset)
{
	if(!CanIterate())
		return FALSE;

	if(nOffset==0)
		return TRUE;

	if(m_nCurrentIndex+(int)nOffset>=GetProcessCount())
		return FALSE;

	m_nCurrentIndex+=nOffset;
	m_dwProcessID=m_arrProcesses[m_nCurrentIndex];

	return TRUE;
}


BOOL COXProcessIterator::Prev(UINT nOffset)
{
	if(!CanIterate())
		return FALSE;

	if(nOffset==0)
		return TRUE;

	if(m_nCurrentIndex-nOffset<0)
		return FALSE;

	m_nCurrentIndex-=nOffset;
	m_dwProcessID=m_arrProcesses[m_nCurrentIndex];

	return TRUE;
}





By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions