/**********************************************************************
 * Copyright (c) 2005, 2007 Scapa Technologies Limited and others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * $Id: PerfmonAgent.cpp,v 1.2 2007/04/06 01:00:53 jkubasta Exp $
 * 
 * Contributors: 
 * Scapa Technologies Limited - Initial API and implementation
 **********************************************************************/

#include "PerfmonAgent.h"

#ifdef WIN32
//#include <winsock2.h> /* Bug 134924 */
#include <windows.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#include "hashtable.h"
#include "system.h"
#include "DataTransferInterface.h"
#include "DataCollectionInterface.h"


int PRINT_XML = FALSE;
int VERBOSE = FALSE;
int LOG_TO_FILE = FALSE;

int BATCH_XML_MESSAGES = TRUE;

HashTable* hasht_request;
HashTable* hasht_filters;
HashTable* hasht_variables;
HashTable* hasht_tree;

// Message Buffer Info
int buf_ptr = 0;
int buf_len = 204800;
char* buf;	//20k buffer

char digits[] = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};

static FILE* f = NULL;

static char filename[] = "PerfmonAgent.log";

void logToFile(const char*, ...);

void logToFile(const char* temp, ...)
{
	if (LOG_TO_FILE)
	{
		if (f == NULL)
			f = fopen(filename,  "w");
		va_list ap;
		va_start (ap, temp);
		vfprintf (f, temp, ap);
//		printf(temp,ap);
		va_end (ap);
		fflush(f);
	}
}

void longToString(XINT64 i, char* str) 
{
	int radix = 10;
	char buf[65];

	int charPos = 64;
	int negative = (i < 0);

	if (!negative) {
	    i = -i;
	}

	while (i <= -radix) 
	{
	    buf[charPos--] = digits[(int)(-(i % radix))];
	    i = i / radix;
	}
	buf[charPos] = digits[(int)(-i)];

	if (negative) {
	    buf[--charPos] = '-';
	}

	memcpy(str,&(buf[charPos]),(65 - charPos));
}

int increaseBufferSize(char** buf, int* buflen) {
	//double the size of the buffer
	int newlen = *buflen * 2;
	char* newbuf = (char*)malloc(newlen);

	memcpy(newbuf,*buf,*buflen);
	free(*buf);

	*buf = newbuf;
	*buflen = newlen;

	return newlen;
}

void clearData(char** array, int count)
{
	for (int i =0 ;i<count;i++) {
		free(array[i]);
	}
	free(array);
}

void fetchTree(LPGETTREE getTree, LPCOMSENDMESSAGE comSendMessage)
{
	char** treedata;
	int numstrings=0;
	int i=0, ret=0;
	int buf_ptr = 0;
	int total_dat;

	//////////////////////////////////////////////
	// TREE BUILDING - descriptors				//
	//////////////////////////////////////////////
	//
	// Get the names of all the counters, treedata contains the names, numstrings the number...
	//

	logToFile("Retrieving tree data..\n");	
	treedata = getTree(&numstrings);
	logToFile("Parsing tree data.. Got %d strings \n", numstrings);
	//
	// go through each of the strings and create XML
	//
	for (i = 0; i < numstrings; i++) 
	{
		char* dat[6];
		char* currdat = treedata[i];

		int keyindex = 1;
		int datindex = 0;

		logToFile("Parsing %d of %d\n", i, numstrings);

		//dat[0] = pid, dat[1] = id, dat[2] = name, dat[3] = help, dat[4] = suffix (not used)
		//check to see if this is the child of a requested parent
		if ((tableGet(hasht_variables,REGET_CHILDREN) && currdat[0] == '\0') || (tableGet(hasht_tree,currdat) == 1) ) 
		{			
			logToFile("This has been requested");
			// check if buffer size is > 5 or 10k here and send it back as
			// one message if it is - rather than sending a 4000k message
			if (BATCH_XML_MESSAGES) 
				if (buf_ptr > 10240) 
				{
					ret = comSendMessage(buf, 0, buf_ptr);
					total_dat += buf_ptr;
					buf_ptr = 0;
				}

			//
			// Parse out all the strings for this counter
			//
			dat[0] = currdat;

			while (TRUE) 
			{
				//filter out non-XML characters
				if (currdat[datindex] == '\"' || currdat[datindex] == '\'') 
					currdat[datindex] = '_';
				if (currdat[datindex] < 0)
					currdat[datindex] = ' ';
				if (currdat[datindex] == '\0') 
				{
					if (keyindex == 6) 
						break;	//this means we check all the strings
					dat[keyindex++] = &currdat[datindex+1];
				}
				datindex++;
			}

			if (tableGet(hasht_request,dat[1]) == 0) 
			{
				tablePut(hasht_request,dat[1],1);

				logToFile("%s, %s, %s, (help), %s\n",dat[0],dat[1],dat[2],dat[4]);

				while (TRUE) 
				{
					if (dat[0][0] == '\0') 
					{
						//no help = no description
						if (dat[3][0] == '\0')
						{
							//not sending back help strings drops data from 3.7M to 1.2M
							//new IDs should drop it down to around 800k with no help strings
							if (dat[5][0] == '0')
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<Descriptor id=\"%s\" name=\"%s\" />\n",dat[1],dat[2],dat[3]);
							else								
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<CounterDescriptor id=\"%s\" name=\"%s\" />\n",dat[1],dat[2],dat[3]);
						}
						else
						{
							if (dat[5][0] == '0')
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<Descriptor id=\"%s\" name=\"%s\" >\n<description>%s</description>\n</Descriptor>\n",dat[1],dat[2],dat[3]);
							else								
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<CounterDescriptor id=\"%s\" name=\"%s\" >\n<description>%s</description>\n</CounterDescriptor>\n",dat[1],dat[2],dat[3]);
						}

					} 
					else 
					{
						//no help = no description
						if (dat[3][0] == '\0') 
						{
							//not sending back help strings drops data from 3.7M to 1.2M
							//new IDs should drop it down to around 800k with no help strings
							if (dat[5][0] == '0')
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<Descriptor parent=\"%s\" id=\"%s\" name=\"%s\" />\n",dat[0],dat[1],dat[2],dat[3]);
							else								
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<CounterDescriptor parent=\"%s\" id=\"%s\" name=\"%s\" />\n",dat[0],dat[1],dat[2],dat[3]);
						}
						else 
						{
							if (dat[5][0] == '0')
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<Descriptor parent=\"%s\" id=\"%s\" name=\"%s\" >\n<description>%s</description>\n</Descriptor>\n",dat[0],dat[1],dat[2],dat[3]);
							else								
								ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<CounterDescriptor parent=\"%s\" id=\"%s\" name=\"%s\" >\n<description>%s</description>\n</CounterDescriptor>\n",dat[0],dat[1],dat[2],dat[3]);
						}
					}

					if (ret < 0)
						increaseBufferSize(&buf,&buf_len);
					else 
					{
						buf_ptr += ret;
						break;
					}

				}


				if (!BATCH_XML_MESSAGES) 
				{
					ret = comSendMessage(buf, 0, buf_ptr);
					total_dat += buf_ptr;
					buf_ptr = 0;
				}
				
				if (PRINT_XML) logToFile("XML = %s\n\n",buf);
			}
		}
	}

	tablePut(hasht_variables, REGET_CHILDREN,(XINT64) 0);
	//
	// print out how many messages we sent and the total number of bytes we sent
	//
	logToFile("%d descriptors, total bytes = %d bytes\n\n",numstrings,total_dat);

	//
	// deallocate the strings
	//
	clearData(treedata,numstrings);
	//
	// Send any remaining buffer data
	//
	if (BATCH_XML_MESSAGES) 
	{
		logToFile("Sending data back to the workbench...\n");

		ret = comSendMessage(buf, 0, buf_ptr);

		total_dat += buf_ptr;
		buf_ptr = 0;
	}


	if (PRINT_XML) 
		logToFile("XML = %s\n\n",buf);
}

void setVariables(HashTable* hasht_variables)
{
	//variables hashtable initialisation
	tablePut(hasht_variables,DC_KEY_MONITORING,DC_VAL_FALSE);
	tablePut(hasht_variables,DC_KEY_FINISHED,DC_VAL_FALSE);
	tablePut(hasht_variables,DC_KEY_WAITTIME,(XINT64)1000);
	tablePut(hasht_variables,DC_KEY_TREE_REQUESTED,DC_VAL_FALSE);
}


int manageResources(LPSTARTUP resStartup, LPSHUTDOWN resShutdown, LPGETTREE getTree, LPGETRESULTS getResults,
					LPCOMSTARTUP comStartup, LPCOMSHUTDOWN comShutdown, LPCOMSENDMESSAGE comSendMessage)
{
	XClock x_clock;
	int memdiff = 5;
	char** results;
	XINT64 ctime;
	int ret,i;

	// Time Buffer Info
	char timebuf[64];	//print time into here
	XINT64 javatime;
	int total_dat = 0, numresults=0;

	hasht_request = tableCreate();
	hasht_filters = tableCreate();
	hasht_variables = tableCreate();
	hasht_tree = tableCreate();

	setVariables(hasht_variables);

	//
	// Startup the COMM and RES
	//
	ret = comStartup( hasht_variables, hasht_filters, hasht_tree );
	if (ret != 0) 
	{
		logToFile("Failed to start up Communications\n");
		return -1;
	}
	resStartup( hasht_variables, hasht_filters, hasht_tree);

	//
	// Set up the XML buffer
	//
	logToFile("Allocating buffer\n");
	buf = (char*)malloc(sizeof(char) * buf_len);

	//
	// Create our x_clock
	//
    XClockCreate(&x_clock);
	XClockRead(&x_clock,&ctime);

	//
	//finished when an agent detaches from us
	// Bug 99153
	while (!tableGet(hasht_variables,DC_KEY_FINISHED) && !tableGet(hasht_variables,DC_AGENT_CONTROLLER_STOPPED)) 
	{
		XINT64 ctime_tmp = 0;
		XINT64 ctime_max = 0;

		XINT32 WAIT_TIME = (XINT32)tableGet(hasht_variables,DC_KEY_WAITTIME);
		XINT32 TREE_REQUESTED = (XINT32)tableGet(hasht_variables,DC_KEY_TREE_REQUESTED);

		//
		// Clean up the XML buffer
		//
		memset(buf,'\0',buf_len);
		buf_ptr = 0;

		ctime_max = ctime + WAIT_TIME;
		XClockRead(&x_clock,&ctime_tmp);
		
		while ((ctime_max - ctime_tmp > 0) && !tableGet(hasht_variables,DC_KEY_FINISHED)) 
		{
			ctime_tmp += 50;
			XClockWait(&x_clock,ctime_tmp);

			WAIT_TIME = (XINT32)tableGet(hasht_variables,DC_KEY_WAITTIME);
			ctime_max = ctime + WAIT_TIME;			

			// Lets return the tree as soon as we can
			if (tableGet(hasht_variables, DC_KEY_MONITORING))
			{
				TREE_REQUESTED = (XINT32)tableGet(hasht_variables,DC_KEY_TREE_REQUESTED);
				if (TREE_REQUESTED)
				{
					fetchTree(getTree, comSendMessage);
					TREE_REQUESTED = FALSE;
					tablePut(hasht_variables,DC_KEY_TREE_REQUESTED,TREE_REQUESTED);
				}
			}
		}

		if (tableGet(hasht_variables,DC_KEY_FINISHED)) 
			break;

		ctime += WAIT_TIME;

		//
		// Wait for a bit
		//
		XClockWait(&x_clock,ctime);
		XClockRead(&x_clock,&ctime);

		if (!tableGet(hasht_variables,DC_KEY_MONITORING)) 
		{
			logToFile("No agent monitoring yet (freq:%dms)\n",tableGet(hasht_variables,DC_KEY_WAITTIME));
			tablePut(hasht_variables, REGET_CHILDREN,(XINT64) 1);
			TREE_REQUESTED = TRUE;
			tablePut(hasht_variables,DC_KEY_TREE_REQUESTED,TREE_REQUESTED);

			// We clear this so that we send back ALL the tree information again...
			tableClear(hasht_request);

			continue;
		}
		//
		// Get the current time in java System.currentTimeMillis() format
		//

		if (TREE_REQUESTED) 
		{			
			fetchTree(getTree, comSendMessage);
			TREE_REQUESTED = FALSE;
			tablePut(hasht_variables,DC_KEY_TREE_REQUESTED,TREE_REQUESTED);
		}

		XClockMillis(&javatime);
		memset(timebuf,'\0',64);
		longToString(javatime,timebuf);

		results = getResults(&numresults);
		logToFile("NUMRESULTS = %d, results=%08X\n",numresults,results);
		//
		// go through each of the strings and create and create an XML
		//
		for (i = 0; results!=NULL && i < numresults; i++) 
		{

			char* dat[2];
			char* currdat = results[i];

			int keyindex = 1;
			int datindex = 0;

			//
			// check if buffer size is > 5 or 10k here and send it back as
			// one message if it is - rather than sending a 4000k message
			//

			if (BATCH_XML_MESSAGES) {
				if (buf_ptr > 10240) 
				{
					ret = comSendMessage(buf, 0, buf_ptr);
					total_dat += buf_ptr;
					buf_ptr = 0;
				}

				if (PRINT_XML) logToFile("XML = %s\n\n",buf);
			}


			//
			// Parse out all the strings for this counter
			//
			dat[0] = currdat;
			while (TRUE) 
			{
				//filter out non-XML characters
				if (currdat[datindex] == '\"' || currdat[datindex] == '\'') 
					currdat[datindex] = '_';
				if (currdat[datindex] < 0)
					currdat[datindex] = ' ';
				if (currdat[datindex] == '\0')
				{
					if (keyindex == 2) 
						break;	//this means we check all the strings
					dat[keyindex++] = &currdat[datindex+1];
				}
				datindex++;
			}

			//dat[0] = id
			//dat[1] = value (string)

			logToFile("--[%s,%s]--\n",dat[0],dat[1]);

			while (TRUE) 
			{
				ret = XSNPrintf( &buf[buf_ptr], buf_len-buf_ptr, "<ContiguousObservation memberDescriptor=\"%s\" time=\"%s\" value=\"%s\" />\n",dat[0],timebuf,dat[1]);

				if (ret < 0)
					increaseBufferSize(&buf,&buf_len);
				else 
				{
					buf_ptr += ret;
					break;
				}
			}

			if (!BATCH_XML_MESSAGES) 
			{
				ret = comSendMessage(buf, 0, buf_ptr);
				total_dat += buf_ptr;
				buf_ptr = 0;
			}

			if (PRINT_XML) 
				logToFile("XML = %s\n\n",buf);
		}

		//
		// Send any remaining buffer data
		//

		if (BATCH_XML_MESSAGES) 
		{
			ret = comSendMessage(buf, 0, buf_ptr);
			total_dat += buf_ptr;
			buf_ptr = 0;
		}

		if (PRINT_XML) 
			logToFile("XML = %s\n\n",buf);
	}

	//
	// We are finished - shutdown the RES and COM and unload the libraries
	//
	resShutdown();
	ret = comShutdown();
	if (ret != 0) 
	{
		logToFile("Failed to shut down Communications agent\n");
		return -1;
	}

	//
	// Cleanup stuff we allocated
	//
	tableDelete(hasht_request);
	tableDelete(hasht_filters);
	tableDelete(hasht_variables);
	tableDelete(hasht_tree);

	free(buf);
	return 0;
}

void showInfo()
{
	logToFile("PerfmonAgent\n\n");
	logToFile("Usage:   PerfmonAgent.exe [-v] [Resource DLL] [Communications DLL]\n");
	logToFile("Default: PerfmonAgent.exe sysperf.dll rac.dll\n");
	logToFile("\n-v\t: Enable verbose output\n");
}

//
//	Load the DLL functions for the resource gatherer and communciator.
//	If successful, pass these functions to the manageresource method.
//
int process(char* resDLLname, char* commDLLname)
{	
	LPSTARTUP resStartup;
	LPSHUTDOWN resShutdown;
	LPGETTREE getTree;
	LPGETRESULTS getResults;
	LPGETAGENTNAME getAgentName = NULL;
	int rt;

	LPCOMSTARTUP COMStartup;
	LPCOMSHUTDOWN COMShutdown;
	LPCOMSENDMESSAGE COMSendMessage;
	LPCOMSETAGENTNAME COMSetAgentName = NULL;

#ifdef LINUX
  const char *error;
  void *resmodule;
	void *commodule;

	// First lets try and open the two libraries
	logToFile("trying to open resource library %s\n",resDLLname);
	resmodule = dlopen(resDLLname, RTLD_LAZY);
	if (!resmodule) 
	{
		fprintf(stderr, "Couldn't open reslibrary: %s\n",dlerror());
		logToFile("Couldn't open reslibrary: %s\n",dlerror());
		exit(1);
	}
	printf("trying to open communiction library %s\n",commDLLname);

	commodule = dlopen(commDLLname, RTLD_LAZY);
	if (!commodule) 
	{
		dlclose(resmodule);
		fprintf(stderr, "Couldn't open commlibrary: %s\n",dlerror());
		logToFile("Couldn't open commlibrary: %s\n",dlerror());
		exit(1);
	}

	logToFile("Address %08x\n",commodule);

	//Okay, we must now try and get all the methods we need!

	dlerror();
	resStartup = (LPSTARTUP) dlsym(resmodule, "DC_CollectionStartup");
	if ((error = dlerror())) 
	{
		dlclose(resmodule);
		dlclose(commodule);

		fprintf(stderr, "Couldn't find DC_CollectionStartup: %s\n", error);
		logToFile("Couldn't find DC_CollectionStartup: %s\n", error);
		exit(1);
	}
	dlerror();
	resShutdown = (LPSHUTDOWN) dlsym(resmodule, "DC_CollectionShutdown");
	if ((error = dlerror())) 
	{
		dlclose(resmodule);
		dlclose(commodule);

  		fprintf(stderr, "Couldn't find DC_CollectionShutdown: %s\n", error);
		logToFile("Couldn't find DC_CollectionShutdown: %s\n", error);
		exit(1);
	}
	dlerror();
	getTree = (LPGETTREE) dlsym(resmodule, "DC_CollectionGetTree");
	if ((error = dlerror())) 
	{
		dlclose(resmodule);
		dlclose(commodule);
		
  		fprintf(stderr, "Couldn't find DC_CollectionGetTree: %s\n", error);
		logToFile("Couldn't find DC_CollectionGetTree: %s\n", error);
		exit(1);
	}
	dlerror();
	getResults = (LPGETRESULTS) dlsym(resmodule, "DC_CollectionGetResults");
	if ((error = dlerror())) 
	{
		dlclose(resmodule);
		dlclose(commodule);
		
  		fprintf(stderr, "Couldn't find DC_CollectionGetResults: %s\n", error);
  		logToFile("Couldn't find DC_CollectionGetResults: %s\n", error);
		exit(1);
	}
	dlerror();
	getAgentName = (LPGETAGENTNAME) dlsym(resmodule, "DC_CollectionGetAgentName");
	if ((error = dlerror())) 
	{
		dlclose(resmodule);
		dlclose(commodule);
		
  		fprintf(stderr, "Couldn't find DC_CollectionGetAgentName: %s\n", error);
		logToFile("Couldn't find DC_CollectionGetAgentName: %s\n", error);
		exit(1);
	}

	COMStartup = (LPCOMSTARTUP) dlsym(commodule, "DC_TransferStartup");
	if ((error = dlerror()))
	{
		dlclose(resmodule);
		dlclose(commodule);
		
		fprintf(stderr, "Couldn't find DC_TransferStartup: %s\n", error);
		logToFile("Couldn't find DC_TransferStartup: %s\n", error);
		exit(1);
	}

	COMShutdown = (LPCOMSHUTDOWN) dlsym(commodule, "DC_TransferShutdown");
	if ((error = dlerror()))
	{
		dlclose(resmodule);
		dlclose(commodule);
		
		fprintf(stderr, "Couldn't find DC_TransferShutdown: %s\n", error);
		logToFile("Couldn't find DC_TransferShutdown: %s\n", error);
		exit(1);
	}
	COMSendMessage = (LPCOMSENDMESSAGE) dlsym(commodule, "DC_SendMessage");
	if ((error = dlerror()))
	{
		dlclose(resmodule);
		dlclose(commodule);
		
		fprintf(stderr, "Couldn't find DC_SendMessage: %s\n", error);
		logToFile("Couldn't find DC_SendMessage: %s\n", error);
		exit(1);
	}

	COMSetAgentName = (LPCOMSETAGENTNAME) dlsym(commodule, "DC_TransferSetAgentName");
	if ((error = dlerror()))
	{
		dlclose(resmodule);
		dlclose(commodule);
		
		fprintf(stderr, "Couldn't find DC_SetAgentName: %s\n", error);
		logToFile("Couldn't find DC_SetAgentName: %s\n", error);
		exit(1);
	}

	// Lets pass on the agentname from the collection dLL to the resource DLL
	char* agentName = getAgentName();
	COMSetAgentName(agentName);

	// Perform processing
	rt = manageResources(resStartup, resShutdown, getTree, getResults,COMStartup,COMShutdown,COMSendMessage);

 /* All done, close things cleanly */
	dlclose(resmodule);
	dlclose(commodule);
	return 0;

#else
				
	HINSTANCE hResDLL;               
	HINSTANCE hCommDLL;               


	// LOAD THE RESOURCE DLL FUNCTIONS
	hResDLL = LoadLibrary(resDLLname);
	if (hResDLL == NULL)
	{
		logToFile("Error encountered: %s is not a valid DLL\n",resDLLname);		
		MessageBox(NULL,"Error Loading resourceDLL","Error Loading resourceDLL",MB_OK);
		return -1;
	}

	resStartup	= (LPSTARTUP)	GetProcAddress(hResDLL, "DC_CollectionStartup");
	resShutdown	= (LPSHUTDOWN)	GetProcAddress(hResDLL, "DC_CollectionShutdown");
	getTree		= (LPGETTREE)	GetProcAddress(hResDLL, "DC_CollectionGetTree");
	getResults	= (LPGETRESULTS)GetProcAddress(hResDLL, "DC_CollectionGetResults");
	getAgentName = (LPGETAGENTNAME) GetProcAddress(hResDLL, "DC_CollectionGetAgentName");

	if (!resStartup)
		logToFile("resStartup\n");
	if (!resShutdown)
		logToFile("resShutdown\n");
	if (!getTree)
		logToFile("getTree\n");
	if (!getResults)
		logToFile("getResults\n");
	if (!getAgentName)
		logToFile("getAgentName\n");

	if (!resStartup || !resShutdown || !getTree || !getResults || !getAgentName)
	{
		// handle the error
		FreeLibrary(hResDLL);       
		logToFile("Unable to load function(s) from Resource DLL.\n");
		MessageBox(NULL,"Error Loading Functions (RESOURCEDLL)","Error Loading Functions (RESOURCEDLL)",MB_OK);
	    return -1;
	}

	// LOAD THE COMM DLL FUNCTIONS
	hCommDLL = LoadLibrary(commDLLname);
	if (hCommDLL == NULL)
	{
		FreeLibrary(hResDLL);
		logToFile("Error encountered: %s is not a valid DLL\n",commDLLname);
		MessageBox(NULL,"Error Loading commDLL","Error Loading commDLL",MB_OK);
		return -1;
	}

	COMStartup		= (LPCOMSTARTUP)		GetProcAddress(hCommDLL, "DC_TransferStartup");
	COMShutdown		= (LPCOMSHUTDOWN)		GetProcAddress(hCommDLL, "DC_TransferShutdown");
	COMSendMessage	= (LPCOMSENDMESSAGE)	GetProcAddress(hCommDLL, "DC_SendMessage");
	COMSetAgentName = (LPCOMSETAGENTNAME)	GetProcAddress(hCommDLL, "DC_TransferSetAgentName");

	if (!COMStartup || !COMShutdown || !COMSendMessage || !COMSetAgentName)
	{
		// handle the error
		FreeLibrary(hResDLL);       
		FreeLibrary(hCommDLL);
		logToFile("Unable to load function(s) from Communications DLL.\n");
		MessageBox(NULL,"Error Loading Functions (COMDLL)","Error Loading Functions (COMDLL)",MB_OK);
	    return -1;
	}

	// Lets pass on the agentname from the collection dLL to the resource DLL
	char* agentName = getAgentName();
	logToFile("PerfmonAgent received agentname of %s\n",agentName);
	COMSetAgentName(agentName);

	rt = manageResources(resStartup, resShutdown, getTree, getResults,COMStartup,COMShutdown,COMSendMessage);

	FreeLibrary(hResDLL);       
	FreeLibrary(hCommDLL);
	return rt;
#endif
}

//
//	Main Agent Method : Parse the command line arguments and set DLL names
//
int main(int argc, char** argv)
{
	char* resDLLname = NULL;
	char* commDLLname = NULL;

	for (int i = 1; i < argc; i++)
	{
		if (argv[i][0] == '\0')
			continue;
		if (strcmp(argv[i],"-v")==0)
			VERBOSE = TRUE;
		else if ((strcmp(argv[i],"--help")==0) || (strcmp(argv[i],"/?")==0) || (strcmp(argv[i],"-h")==0))
		{
			showInfo();
			return 0;
		}
		else if (resDLLname == NULL)
		{
			resDLLname = argv[i];
		}
		else if (commDLLname == NULL)
		{
			commDLLname = argv[i];
		}
	}
	if (resDLLname == NULL) resDLLname = DEFAULT_RES;
	if (commDLLname == NULL) commDLLname = DEFAULT_COM;

	logToFile("Using Resource DLL \"%s\", Communications DLL \"%s\"\n",resDLLname, commDLLname);
	return process(resDLLname, commDLLname);
}


