#include <common/snapshot.hpp>

Snapshot::Snapshot(void)
: mhSnapshot(0), mKernelLib("KERNEL32"), mpfnCreateToolhelp32Snapshot(0),
  mpfnProcess32First(0), mpfnProcess32Next(0)
{
  initialize();
}

Snapshot::Snapshot(const Snapshot &snapshot)
: mhSnapshot(0)
{  // private implementation
  *this=snapshot;
}

Snapshot::~Snapshot()
{
  destroy();
}

BOOL Snapshot::create(SnapshotFlags snapshotFlags,DWORD processID)
{
  destroy();
	if(!mpfnCreateToolhelp32Snapshot)return FALSE;
	mhSnapshot=mpfnCreateToolhelp32Snapshot(snapshotFlags,processID);
	return isOkay();
}

BOOL Snapshot::process32First(ProcessEntry &processEntry)
{
  if(!isOkay()||!mpfnProcess32First)return FALSE;
	return mpfnProcess32First(mhSnapshot,&processEntry.getProcessEntry());
}

BOOL Snapshot::process32Next(ProcessEntry &processEntry)
{
  if(!isOkay()||!mpfnProcess32Next)return FALSE;
	return mpfnProcess32Next(mhSnapshot,&processEntry.getProcessEntry());
}

Snapshot &Snapshot::operator=(const Snapshot &snapshot)
{ // private implementation
  return *this;
}

void Snapshot::destroy(void)
{
  if(!isOkay())return;
	::CloseHandle(mhSnapshot);
	mhSnapshot=0;
}

BOOL Snapshot::initialize(void)
{
  WinVersionInfo winVersion;

	if(winVersion.isWinNT()&&winVersion.majorVersion()<=4)return FALSE;
	if(!mKernelLib.isOkay())return FALSE;
	mpfnCreateToolhelp32Snapshot=(PFNCREATETOOLHELP32SNAPSHOT)mKernelLib.procAddress("CreateToolhelp32Snapshot");
	if(!mpfnCreateToolhelp32Snapshot)return FALSE;
	mpfnProcess32First=(PFNPROCESS32FIRST)mKernelLib.procAddress("Process32First");
	if(!mpfnProcess32First)return FALSE;
	mpfnProcess32Next=(PFNPROCESS32NEXT)mKernelLib.procAddress("Process32Next");
	if(!mpfnProcess32Next)return FALSE;
	return TRUE;
}

BOOL Snapshot::isOkay(void)const
{
  return (mpfnCreateToolhelp32Snapshot&&mpfnProcess32First&&mpfnProcess32Next);
}
