//--------------------------------------------------------------------------- // ModuleInstance.cpp // // AUTHOR: Ivo Ivanov (ivopi@hotmail.com) // ver 1.02 // 05 September 2001 //--------------------------------------------------------------------------- #include "Common.h" #include "ModuleInstance.h" #include "SysUtils.h" //--------------------------------------------------------------------------- // // class CElements // //--------------------------------------------------------------------------- CElements::CElements(): CModuleList() { } CElements::~CElements() { } //--------------------------------------------------------------------------- // // class CLibHandler // //--------------------------------------------------------------------------- CLibHandler::CLibHandler(CRunningProcesses* pProcesses): m_pProcesses(pProcesses) { } CLibHandler::~CLibHandler() { } //--------------------------------------------------------------------------- // // class CTaskManager // //--------------------------------------------------------------------------- CTaskManager::CTaskManager(): m_pLibHandler(NULL) { m_pProcesses = new CRunningProcesses(); if (IsPsapiSupported()) m_pLibHandler = new CPsapiHandler(m_pProcesses); else if (IsToolHelpSupported()) m_pLibHandler = new CToolhelpHandler(m_pProcesses); } CTaskManager::~CTaskManager() { delete m_pLibHandler; delete m_pProcesses; } //--------------------------------------------------------------------------- // Populate // // Populate the process and modules list using PSAPI or ToolHlp32 //--------------------------------------------------------------------------- BOOL CTaskManager::Populate(BOOL bPopulateModules) { m_pProcesses->ReleaseAll(); return m_pLibHandler->PopulateProcesses(bPopulateModules); } //--------------------------------------------------------------------------- // PopulateProcess // // Populate the module list using PSAPI or ToolHlp32 //--------------------------------------------------------------------------- BOOL CTaskManager::PopulateProcess(DWORD dwProcessId, BOOL bPopulateModules) { m_pProcesses->ReleaseAll(); return m_pLibHandler->PopulateProcess(dwProcessId, bPopulateModules); } //--------------------------------------------------------------------------- // GetProcessCount // // Returns a number of currently loaded processes //--------------------------------------------------------------------------- DWORD CTaskManager::GetProcessCount() const { return m_pProcesses->GetCount(); } //--------------------------------------------------------------------------- // GetProcessByIndex // // Returns a process from the container //--------------------------------------------------------------------------- CExeModuleInstance* CTaskManager::GetProcessByIndex(DWORD dwIndex) { return static_cast<CExeModuleInstance*>(m_pProcesses->GetModule(dwIndex)); } //--------------------------------------------------------------------------- // GetProcessById // // Returns a process by its ID //--------------------------------------------------------------------------- CExeModuleInstance* CTaskManager::GetProcessById(DWORD dwProcessId) { return static_cast<CExeModuleInstance*> (m_pProcesses->GetProcessById(dwProcessId)); } //--------------------------------------------------------------------------- // // class CLoadedModules // //--------------------------------------------------------------------------- CLoadedModules::CLoadedModules(DWORD dwProcessId): CElements(), m_dwProcessId(dwProcessId) { } CLoadedModules::~CLoadedModules() { } //--------------------------------------------------------------------------- // // class CRunningProcesses // //--------------------------------------------------------------------------- CRunningProcesses::CRunningProcesses(): CElements() { } CRunningProcesses::~CRunningProcesses() { } CExeModuleInstance* CRunningProcesses::GetProcessById(DWORD dwProcessId) { CExeModuleInstance* pResult = NULL; CExeModuleInstance* pProcess; for (long i = 0; i < GetCount(); i++) { pProcess = static_cast<CExeModuleInstance*>( GetModule(i) ); if (pProcess->Get_ProcessId() == dwProcessId) { pResult = pProcess; break; } // if } // for return pResult; } //--------------------------------------------------------------------------- // // class CPsapiHandler // //--------------------------------------------------------------------------- CPsapiHandler::CPsapiHandler(CRunningProcesses* pProcesses): CLibHandler(pProcesses), m_hModPSAPI(NULL), m_pfnEnumProcesses(NULL), m_pfnEnumProcessModules(NULL), m_pfnGetModuleFileNameExA(NULL) { } CPsapiHandler::~CPsapiHandler() { Finalize(); } //--------------------------------------------------------------------------- // Initialize // //--------------------------------------------------------------------------- BOOL CPsapiHandler::Initialize() { BOOL bResult = FALSE; // // Get to the 3 functions in PSAPI.DLL dynamically. We can't // be sure that PSAPI.DLL has been installed // if (NULL == m_hModPSAPI) m_hModPSAPI = ::LoadLibraryA("PSAPI.DLL"); if (NULL != m_hModPSAPI) { m_pfnEnumProcesses = (PFNENUMPROCESSES) ::GetProcAddress(m_hModPSAPI,"EnumProcesses"); m_pfnEnumProcessModules = (PFNENUMPROCESSMODULES) ::GetProcAddress(m_hModPSAPI, "EnumProcessModules"); m_pfnGetModuleFileNameExA = (PFNGETMODULEFILENAMEEXA) ::GetProcAddress(m_hModPSAPI, "GetModuleFileNameExA"); } bResult = m_pfnEnumProcesses && m_pfnEnumProcessModules && m_pfnGetModuleFileNameExA; return bResult; } //--------------------------------------------------------------------------- // Finalize // //--------------------------------------------------------------------------- void CPsapiHandler::Finalize() { if (NULL != m_hModPSAPI) ::FreeLibrary(m_hModPSAPI); } //--------------------------------------------------------------------------- // PopulateModules // // Populate the module list using PSAPI //--------------------------------------------------------------------------- BOOL CPsapiHandler::PopulateModules(CModuleInstance* pProcess) { BOOL bResult = TRUE; CModuleInstance *pDllModuleInstance = NULL; if (TRUE == Initialize()) { DWORD pidArray[1024]; DWORD cbNeeded; DWORD nProcesses; // EnumProcesses returns an array with process IDs if (m_pfnEnumProcesses(pidArray, sizeof(pidArray), &cbNeeded)) { // Determine number of processes nProcesses = cbNeeded / sizeof(DWORD); // Release the container pProcess->ReleaseModules(); for (DWORD i = 0; i < nProcesses; i++) { HMODULE hModuleArray[1024]; HANDLE hProcess; DWORD pid = pidArray[i]; DWORD nModules; // Let's open the process hProcess = ::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); if (!hProcess) continue; if (static_cast<CExeModuleInstance*>(pProcess)->Get_ProcessId() != pid) { ::CloseHandle(hProcess); continue; } // EnumProcessModules function retrieves a handle for // each module in the specified process. if (!m_pfnEnumProcessModules( hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded)) { ::CloseHandle(hProcess); continue; } // Calculate number of modules in the process nModules = cbNeeded / sizeof(hModuleArray[0]); for (DWORD j = 0; j < nModules; j++) { HMODULE hModule = hModuleArray[j]; char szModuleName[MAX_PATH]; m_pfnGetModuleFileNameExA( hProcess, hModule, szModuleName, sizeof(szModuleName) ); if (0 == j) // First module is the EXE. { // Do nothing. } // if else // Not the first module. It's a DLL { pDllModuleInstance = new CModuleInstance( szModuleName, hModule ); pProcess->AddModule(pDllModuleInstance); } // else } // for ::CloseHandle(hProcess); // We're done with this process handle } // for bResult = TRUE; } // if else { bResult = FALSE; } } // if else { bResult = FALSE; } return bResult; } //--------------------------------------------------------------------------- // PopulateProcesses // // Populate the process list using PSAPI //--------------------------------------------------------------------------- BOOL CPsapiHandler::PopulateProcesses(BOOL bPopulateModules) { BOOL bResult = TRUE; CExeModuleInstance* pProcessInfo; char szModuleName[MAX_PATH]; if (TRUE == Initialize()) { DWORD pidArray[1024]; DWORD cbNeeded; DWORD nProcesses; if (m_pfnEnumProcesses(pidArray, sizeof(pidArray), &cbNeeded)) { // Determine number of processes nProcesses = cbNeeded / sizeof(DWORD); m_pProcesses->ReleaseAll(); for (DWORD i = 0; i < nProcesses; i++) { HMODULE hModuleArray[1024]; HANDLE hProcess; DWORD pid = pidArray[i]; DWORD nModules; hProcess = ::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid ); if (!hProcess) continue; if (!m_pfnEnumProcessModules(hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded)) { ::CloseHandle(hProcess); continue; } // Calculate number of modules in the process nModules = cbNeeded / sizeof(hModuleArray[0]); for (DWORD j = 0; j < nModules; j++) { HMODULE hModule = hModuleArray[j]; m_pfnGetModuleFileNameExA( hProcess, hModule, szModuleName, sizeof(szModuleName) ); if (0 == j) // First module is the EXE. Just add it to the map { pProcessInfo = new CExeModuleInstance( this, szModuleName, hModule, pid ); m_pProcesses->Add(*pProcessInfo); if (bPopulateModules) pProcessInfo->PopulateModules(); break; } // if } // for ::CloseHandle(hProcess); } // for bResult = TRUE; } // if else { bResult = FALSE; } } // if else { bResult = FALSE; } return bResult; } //--------------------------------------------------------------------------- // PopulateProcess // // Populate all modules of a single process // //--------------------------------------------------------------------------- BOOL CPsapiHandler::PopulateProcess(DWORD dwProcessId, BOOL bPopulateModules) { BOOL bResult = TRUE; CExeModuleInstance* pProcessInfo; if (TRUE == Initialize()) { m_pProcesses->ReleaseAll(); HMODULE hModuleArray[1024]; HANDLE hProcess; DWORD nModules; DWORD cbNeeded; hProcess = ::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); if (hProcess) { if (!m_pfnEnumProcessModules( hProcess, hModuleArray, sizeof(hModuleArray), &cbNeeded )) ::CloseHandle(hProcess); else { // Calculate number of modules in the process nModules = cbNeeded / sizeof(hModuleArray[0]); for (DWORD j = 0; j < nModules; j++) { HMODULE hModule = hModuleArray[j]; char szModuleName[MAX_PATH]; m_pfnGetModuleFileNameExA( hProcess, hModule, szModuleName, sizeof(szModuleName) ); if (0 == j) // First module is the EXE. Just add it to the map { pProcessInfo = new CExeModuleInstance( this, szModuleName, hModule, dwProcessId ); m_pProcesses->Add(*pProcessInfo); if (bPopulateModules) pProcessInfo->PopulateModules(); break; } // if } // for ::CloseHandle(hProcess); } // if } // if } // if else { bResult = FALSE; } return bResult; } //--------------------------------------------------------------------------- // // class CToolhelpHandler // //--------------------------------------------------------------------------- CToolhelpHandler::CToolhelpHandler(CRunningProcesses* pProcesses): CLibHandler(pProcesses) { } CToolhelpHandler::~CToolhelpHandler() { } //--------------------------------------------------------------------------- // Initialize // //--------------------------------------------------------------------------- BOOL CToolhelpHandler::Initialize() { BOOL bResult = FALSE; HINSTANCE hInstLib; hInstLib = ::LoadLibraryA("Kernel32.DLL"); if (NULL != hInstLib) { // // We must link to these functions of Kernel32.DLL explicitly. Otherwise // a module using this code would fail to load under Windows NT, which does not // have the Toolhelp32 functions in the Kernel32. // m_pfnCreateToolhelp32Snapshot = (PFNCREATETOOLHELP32SNAPSHOT) ::GetProcAddress(hInstLib, "CreateToolhelp32Snapshot"); m_pfnProcess32First = (PFNPROCESS32FIRST) ::GetProcAddress(hInstLib, "Process32First"); m_pfnProcess32Next = (PFNPROCESS32NEXT) ::GetProcAddress(hInstLib, "Process32Next"); m_pfnModule32First = (PFNMODULE32FIRST) ::GetProcAddress(hInstLib, "Module32First"); m_pfnModule32Next = (PFNMODULE32NEXT) ::GetProcAddress(hInstLib, "Module32Next"); ::FreeLibrary( hInstLib ); bResult = m_pfnCreateToolhelp32Snapshot && m_pfnProcess32First && m_pfnProcess32Next && m_pfnModule32First && m_pfnModule32Next; } // if return bResult; } //--------------------------------------------------------------------------- // PopulateModules // // Populate the module list using ToolHelp32 //--------------------------------------------------------------------------- BOOL CToolhelpHandler::PopulateModules(CModuleInstance* pProcess) { BOOL bResult = TRUE; CModuleInstance *pDllModuleInstance = NULL; HANDLE hSnapshot = INVALID_HANDLE_VALUE; hSnapshot = m_pfnCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, static_cast<CExeModuleInstance*>(pProcess)->Get_ProcessId()); MODULEENTRY32 me = { sizeof(me) }; for (BOOL bOk = ModuleFirst(hSnapshot, &me); bOk; bOk = ModuleNext(hSnapshot, &me)) { // We don't need to add to the list the process itself. // The module list should keep references to DLLs only if (0 != stricmp(pProcess->GetBaseName(), me.szModule)) { pDllModuleInstance = new CModuleInstance(me.szExePath, me.hModule); pProcess->AddModule(pDllModuleInstance); } else // // However, we should fix up the module of the EXE, because // th32ModuleID member has meaning only to the tool help functions // and it is not usable by Win32 API elements. // { pProcess->Set_Module( me.hModule ); } } // for if (hSnapshot != INVALID_HANDLE_VALUE) ::CloseHandle(hSnapshot); return bResult; } BOOL CToolhelpHandler::ModuleFirst(HANDLE hSnapshot, PMODULEENTRY32 pme) const { return m_pfnModule32First(hSnapshot, pme); } BOOL CToolhelpHandler::ModuleNext(HANDLE hSnapshot, PMODULEENTRY32 pme) const { return m_pfnModule32Next(hSnapshot, pme); } BOOL CToolhelpHandler::ProcessFirst(HANDLE hSnapshot, PROCESSENTRY32* pe32) const { return m_pfnProcess32First(hSnapshot, pe32); } BOOL CToolhelpHandler::ProcessNext(HANDLE hSnapshot, PROCESSENTRY32* pe32) const { return m_pfnProcess32Next(hSnapshot, pe32); } //--------------------------------------------------------------------------- // PopulateProcesses // // Populate the process list using Toolhelp //--------------------------------------------------------------------------- BOOL CToolhelpHandler::PopulateProcesses(BOOL bPopulateModules) { return PopulateProcess(NULL, bPopulateModules); } //--------------------------------------------------------------------------- // PopulateProcess // // Populate all modules of a single process // //--------------------------------------------------------------------------- BOOL CToolhelpHandler::PopulateProcess(DWORD dwProcessId, BOOL bPopulateModules) { BOOL bResult = FALSE; CExeModuleInstance* pProcessInfo; HANDLE hSnapshot = INVALID_HANDLE_VALUE; if (TRUE == Initialize()) { hSnapshot = m_pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, dwProcessId); PROCESSENTRY32 pe32 = { sizeof(pe32) }; for (BOOL bOk = ProcessFirst(hSnapshot, &pe32); bOk; bOk = ProcessNext(hSnapshot, &pe32)) { if ( (dwProcessId != NULL) && (dwProcessId != pe32.th32ProcessID) ) continue; pProcessInfo = new CExeModuleInstance( this, pe32.szExeFile, NULL, // We will fix up later this value pe32.th32ProcessID ); m_pProcesses->Add(*pProcessInfo); if (bPopulateModules) pProcessInfo->PopulateModules(); if (dwProcessId != NULL) break; } // for if (hSnapshot != INVALID_HANDLE_VALUE) ::CloseHandle(hSnapshot); bResult = TRUE; } return bResult; } //--------------------------------------------------------------------------- // // class CModuleList // //--------------------------------------------------------------------------- CModuleList::CModuleList() { } CModuleList::~CModuleList() { ReleaseAll(); } //--------------------------------------------------------------------------- // Add // // Add new object to the container //--------------------------------------------------------------------------- void CModuleList::Add(CModuleInstance &moduleInstance) { push_back(&moduleInstance); } //--------------------------------------------------------------------------- // ReleaseAll // // Release all objects and clear the list //--------------------------------------------------------------------------- void CModuleList::ReleaseAll() { CModuleList::iterator itr; CModuleInstance *pModuleInstance; for (itr = begin(); itr != end(); ++itr) { pModuleInstance = *itr; delete pModuleInstance; } // for clear(); } //--------------------------------------------------------------------------- // GetModule // // Return a module object by its index (Pascal-like style) //--------------------------------------------------------------------------- CModuleInstance* CModuleList::GetModule(DWORD dwIndex) const { return at(dwIndex); } //--------------------------------------------------------------------------- // GetCount // // Return number of items in the container //--------------------------------------------------------------------------- DWORD CModuleList::GetCount() const { return size(); } //--------------------------------------------------------------------------- // // class CModuleInstance // //--------------------------------------------------------------------------- CModuleInstance::CModuleInstance(char *pszName, HMODULE hModule): m_pszName(NULL), m_hModule(NULL), m_pInternalList(NULL) { Set_Name(pszName); Set_Module(hModule); } CModuleInstance::~CModuleInstance() { delete m_pInternalList; if (NULL != m_pszName) delete [] m_pszName; } void CModuleInstance::AddModule(CModuleInstance* pModuleInstance) { if (NULL == m_pInternalList) m_pInternalList = new CModuleList(); m_pInternalList->Add(*pModuleInstance); } void CModuleInstance::ReleaseModules() { if (NULL != m_pInternalList) m_pInternalList->ReleaseAll(); } char* CModuleInstance::Get_Name() const { return m_pszName; } char* CModuleInstance::GetBaseName() const { char *pdest; int ch = '\\'; // Search backward pdest = strrchr(m_pszName, ch); if(pdest != NULL) return &pdest[1]; else return m_pszName; } void CModuleInstance::Set_Name(char *pszName) { if (NULL != m_pszName) delete [] m_pszName; if ((NULL != pszName) && (strlen(pszName))) { m_pszName = new char[strlen(pszName) + 1]; strcpy(m_pszName, pszName); } else { m_pszName = new char[strlen("\0") + 1]; strcpy(m_pszName, "\0"); } } HMODULE CModuleInstance::Get_Module() const { return m_hModule; } void CModuleInstance::Set_Module(HMODULE module) { m_hModule = module; } //--------------------------------------------------------------------------- // // class CExeModuleInstance // //--------------------------------------------------------------------------- CExeModuleInstance::CExeModuleInstance( CLibHandler* pLibHandler, char* pszName, HMODULE hModule, DWORD dwProcessId ): CModuleInstance(pszName, hModule), m_pLibHandler(pLibHandler), m_dwProcessId(dwProcessId) { } CExeModuleInstance::~CExeModuleInstance() { } DWORD CExeModuleInstance::Get_ProcessId() const { return m_dwProcessId; } BOOL CExeModuleInstance::PopulateModules() { return m_pLibHandler->PopulateModules(this); } DWORD CExeModuleInstance::GetModuleCount() { return m_pInternalList ? m_pInternalList->GetCount() : 0; } CModuleInstance* CExeModuleInstance::GetModuleByIndex(DWORD dwIndex) { return m_pInternalList ? m_pInternalList->GetModule(dwIndex) : NULL; } //----------------------------End of the file -------------------------------
By viewing downloads associated with this article you agree to the Terms of use 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.
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Math Primers for Programmers