#include "stdafx.h"
#include "ProcessManager.h"
#include <tlhelp32.h>
#include <AtlBase.h>
#include <AtlConv.h>

k_ProcessManager::k_ProcessManager()
{

}


k_ProcessManager::~k_ProcessManager()
{
	while (!mk_ProcessStatusList.empty())
	{
		delete mk_ProcessStatusList[0];
		mk_ProcessStatusList.erase(mk_ProcessStatusList.begin());
	}
}


void k_ProcessManager::CheckProcesses()
{
	HANDLE lh_ProcessSnap;
	PROCESSENTRY32 lr_Pe32;

	// Take a snapshot of all processes in the system.
	lh_ProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if( lh_ProcessSnap == INVALID_HANDLE_VALUE )
	{
		return;
	}

	// Set the size of the structure before using it.
	lr_Pe32.dwSize = sizeof(PROCESSENTRY32);

	// Retrieve information about the first process,
	// and exit if unsuccessful
	if( !::Process32First(lh_ProcessSnap, &lr_Pe32))
	{
		::CloseHandle(lh_ProcessSnap);          // clean the snapshot object
		return;
	}

	// Now walk the snapshot of processes, and
	// display information about each process in turn
	std::vector<r_ProcessInfo*> lk_CurrentProcessList;
	do
	{
		r_ProcessInfo* lr_Process_ = this->get_ProcessInfo(lr_Pe32.th32ProcessID);
		if (lr_Process_ == NULL)
		{
			lr_Process_ = new r_ProcessInfo;
			lr_Process_->mdw_ProcessId = lr_Pe32.th32ProcessID;
			USES_CONVERSION;
			lr_Process_->ms_Name = A2W(lr_Pe32.szExeFile);
			lr_Process_->mb_Handled = false;
			lr_Process_->mh_InjectedDllHandle = 0;

			mk_ProcessStatusList.push_back(lr_Process_);
		}
		lk_CurrentProcessList.push_back(lr_Process_);
	}
	while( Process32Next( lh_ProcessSnap, &lr_Pe32 ) );

	// remove alle processinfos inside our list who are not listet in our current processlist (remove obsolete elements)
	std::vector<r_ProcessInfo*> lk_RemovedProcessList;
	for (unsigned int i = 0; i < mk_ProcessStatusList.size(); ++i)
		if (!this->IsProcessInsideList(lk_CurrentProcessList, mk_ProcessStatusList[i]))
			lk_RemovedProcessList.push_back(mk_ProcessStatusList[i]);
	while (!lk_RemovedProcessList.empty())
	{
		delete lk_RemovedProcessList[0];
		lk_RemovedProcessList.erase(lk_RemovedProcessList.begin());
	}
	mk_ProcessStatusList = lk_CurrentProcessList;

	::CloseHandle( lh_ProcessSnap );
}


std::vector<r_ProcessInfo*> k_ProcessManager::GetUnhandledProcesses() const
{
	std::vector<r_ProcessInfo*> lk_Return;
	for (unsigned int i = 0; i < mk_ProcessStatusList.size(); ++i)
		if (!mk_ProcessStatusList[i]->mb_Handled)
			lk_Return.push_back(mk_ProcessStatusList[i]);
	return lk_Return;
}


std::vector<r_ProcessInfo*> k_ProcessManager::GetHandledProcesses() const
{
	std::vector<r_ProcessInfo*> lk_Return;
	for (unsigned int i = 0; i < mk_ProcessStatusList.size(); ++i)
		if (mk_ProcessStatusList[i]->mb_Handled)
			lk_Return.push_back(mk_ProcessStatusList[i]);
	return lk_Return;
}


r_ProcessInfo* k_ProcessManager::get_ProcessInfo(DWORD adw_ProcessId)
{
	for (unsigned int i = 0; i < mk_ProcessStatusList.size(); ++i)
		if (mk_ProcessStatusList[i]->mdw_ProcessId == adw_ProcessId)
			return mk_ProcessStatusList[i];
	return NULL;
}


bool k_ProcessManager::IsProcessInsideList(const std::vector<r_ProcessInfo*>& ak_ProcessStatusList, r_ProcessInfo* ar_Process_)
{
	for (unsigned int i = 0; i < ak_ProcessStatusList.size(); ++i)
		if (ak_ProcessStatusList[i]->mdw_ProcessId == ar_Process_->mdw_ProcessId)
			return true;
	return false;
}
