/******************************************************************************
 *
 * Copyright (c) 2000	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	ToolHelp.cpp
 *
 *****************************************************************************/


// SOL++2000


#include <sol\ToolHelp.h>
#include <sol\ProcessInfo.h>
#include <sol\stdio.h>


ToolHelp::ToolHelp()
{
	hKernel = NULL;

	_createToolHelp = NULL;
	_firstThread    = NULL;
	_nextThread     = NULL;
	_firstProcess   = NULL;
	_nextProcess    = NULL;
	_firstModule    = NULL;
	_nextModule     = NULL;

	_firstHeap;
	_nextHeap;

	_firstHeapList	= NULL;
	_nextHeapList	= NULL;

	initialize();
}


ToolHelp::~ToolHelp()
{
	FreeLibrary(hKernel);
}


BOOL ToolHelp::getModuleEntry(DWORD processId, 
						DWORD dwModuleId, LPMODULEENTRY32 lpme32)
{
	MODULEENTRY32	me32;
	BOOL	result = FALSE;

	memset(&me32, 0, sizeof(me32));
	me32.dwSize = sizeof(me32);

	HANDLE hSnapshot = createToolHelp(TH32CS_SNAPMODULE, processId);
	if(hSnapshot == INVALID_HANDLE_VALUE){
		return result;
	}

	if(firstModule(hSnapshot, &me32)){
			do{
				if(dwModuleId == me32.th32ModuleID){
					CopyMemory(lpme32, &me32, sizeof(me32));
					result = TRUE;
					break;
				}
			}while(nextModule(hSnapshot, &me32));
	}	
	
	CloseHandle(hSnapshot);
		
	return result;
}


BOOL ToolHelp::getHeapSize(DWORD processID,
							 DWORD* size)
{
	BOOL rc = FALSE;
	HANDLE hSnapshot = createToolHelp(TH32CS_SNAPALL, 0);
	if(hSnapshot == INVALID_HANDLE_VALUE){
		return rc;
	}

	rc = TRUE;

	HEAPLIST32 hlist;
	memset(&hlist, 0, sizeof(hlist));
	hlist.dwSize = sizeof(hlist);
	DWORD heapID = 0;

	if (firstHeapList(hSnapshot, &hlist)){
			do{
				if(processID == hlist.th32ProcessID){
					heapID = hlist.th32HeapID;
					break;
				}
			}while(nextHeapList(hSnapshot, &hlist));
	}	
	CloseHandle(hSnapshot);

	*size = 0;
	HEAPENTRY32 hentry;
	memset(&hentry, 0, sizeof(hentry));
	hentry.dwSize = sizeof(hentry);
	hentry.dwFlags = (LF32_FIXED|LF32_FREE|LF32_MOVEABLE);
	if (firstHeap(&hentry, processID, heapID )){
			do{
				*size += hentry.dwBlockSize;	
			} while(nextHeap(&hentry));
	}		
	return rc;
}


void ToolHelp::getProcessList(LinkedList& list)
{
	PROCESSENTRY32	pe32;

	memset(&pe32, 0, sizeof(pe32));
	pe32.dwSize = sizeof(pe32);

	HANDLE hsnpProcess = createToolHelp(TH32CS_SNAPALL, 0);

	if(hsnpProcess == INVALID_HANDLE_VALUE){
		return;
	}

	if (firstProcess(hsnpProcess, &pe32)) {
		do{
				::CharUpper(pe32.szExeFile);
				char* name = pe32.szExeFile;
				char* delim = strrchr(name, '\\');
				if (delim) {
					name = ++delim;
				}

				list.add(new ProcessInfo( pe32.th32ProcessID,
										name));
		} while(nextProcess(hsnpProcess, &pe32));

		CloseHandle(hsnpProcess);

	}
}


BOOL ToolHelp::isWindowsNT() 
{
	BOOL rc = FALSE;

	OSVERSIONINFO ver;
	memset(&ver, 0, sizeof(ver));
	ver.dwOSVersionInfoSize = sizeof(ver);

	GetVersionEx(&ver);

	if (ver.dwPlatformId ==VER_PLATFORM_WIN32_WINDOWS) {
		rc = FALSE;
	}

	if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
		rc = TRUE;
	}
	return rc;
}



void ToolHelp::initialize()
{
	if (isWindowsNT() == FALSE) {
		hKernel = GetModuleHandle("kernel32.dll");
	
		_createToolHelp= (SNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot");
		_firstThread  = (SNAPSHOT_THREAD)GetProcAddress(hKernel, "Thread32First");
		_nextThread   = (SNAPSHOT_THREAD)GetProcAddress(hKernel, "Thread32Next");
		_firstProcess = (SNAPSHOT_PROCESS)GetProcAddress(hKernel, "Process32First");
		_nextProcess  = (SNAPSHOT_PROCESS)GetProcAddress(hKernel, "Process32Next");
		_firstModule  = (SNAPSHOT_MODULE)GetProcAddress(hKernel, "Module32First");
		_nextModule   = (SNAPSHOT_MODULE)GetProcAddress(hKernel, "Module32Next");

		_firstHeap	 = (SNAPSHOT_HEAP)GetProcAddress(hKernel, "Heap32First");
		_nextHeap    = (SNAPSHOT_HEAPNEXT)GetProcAddress(hKernel, "Heap32Next");

		_firstHeapList  = (SNAPSHOT_HEAPLIST)GetProcAddress(hKernel, "Heap32ListFirst");
		_nextHeapList   = (SNAPSHOT_HEAPLIST)GetProcAddress(hKernel, "Heap32ListNext");

	}
}

