
//..
//..Gold Module - Example template ..
//..developed by GTS..
//..
//..Intel(R) Corporation (C) 2015
//..

//..includes
#include "Include/Main.h"

//..defines
#ifdef __WIN_OS__
#include <Windows.h>
#endif
#ifdef __LIN_OS__
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#endif

/*
void WinRing0Fun(void)
{
#ifdef __WIN_OS__
	int iFD = 99;
	InitializeOls();
	iFD = GetDllStatus();
#endif
#ifdef __LIN_OS__
	int iFD = 0;
	off_t offT = 0;
	ssize_t sszT = 0;
	unsigned long long int iMSR = 0;
	iFD = open("/dev/cpu/0/msr", O_RDONLY);
#endif

#ifdef __WIN_OS__
	if (0 == iFD)
#endif
#ifdef __LIN_OS__
		if (iFD)
#endif
		{

#ifdef __WIN_64__
			std::cout << std::endl << "..loaded WinRing0x64 driver successfully.." << std::endl;
#endif
#ifdef __WIN_32__
			std::cout << std::endl << "..loaded WinRing0 driver successfully.." << std::endl;
#endif
#ifdef __LIN_OS__
			std::cout << std::endl << "../dev/cpu/0/msr accessible.." << std::endl;
#endif
		}
		else
		{
#ifdef __WIN_OS__
			std::cout << ".." << std::endl << "..WinRing0 encountered a problem loading windows driver.." << std::endl
				<< "..ensure app is executed with administrator privileges.." << std::endl << ".." << std::endl << std::endl;
			exit(1);
#endif
#ifdef __LIN_OS__
			std::cout << ".." << std::endl << "..could not open '/dev/cpu/0/msr' .." << std::endl
				<< "..ensure app is executed with root privileges.." << std::endl << ".." << std::endl << std::endl;
#endif
		}

	
#ifdef __WIN_OS__
		Rdmsr(0x17, &ulRetEAX, &ulRetEDX);
		DeinitializeOls();
#endif
#ifdef __LIN_OS__
		offT = lseek(iFD, 0x17, SEEK_SET);
		sszT = read(iFD, &iMSR, sizeof(iMSR));
		close(iFD);
		ulRetEAX = iMSR & 0xFFFFFFFF;
		ulRetEDX = iMSR >> 32;
#endif
	
		
		std::cout << "..ulRetEAX dec contents --> " << ulRetEAX << std::endl;
		std::cout << "..ulRetEDX dec contents --> " << ulRetEDX << std::endl;
		std::cout << "..ulRetEAX hex contents --> " << std::hex << ulRetEAX << std::endl;
		std::cout << "..ulRetEDX hex contents --> " << std::hex << ulRetEDX << std::endl;


}
*/

void ReadLocalTextConfig(void)
{
	TextData tdLocal;
	std::list<std::string> lLineArr;
	tdLocal.ReadFile("local_text_cfg.txt", lLineArr);
	for (std::list<string>::iterator li = lLineArr.begin(); li != lLineArr.end(); ++li)
	{
		std::cout << ' ' << *li << endl;
	}

}

void ReadLocalConfig(void)
{
	XMLParser localXMLObj;
	try
	{
		
		//Local config
		localXMLObj.LoadXMLFile("GoldModule_LocalConfig.xml");

		// Set up the root element
		localXMLObj.SetRootElem("LocalModuleConfig");

		string localStrItem = localXMLObj.ReadNodeKeyAsString("@LocalConfigItem", "");
if (iDebugFlag)
		{
		cout << "LocalConfigItem = " << localStrItem << endl;
	}
		
	}
	catch (...)
	{
		std::string sException;
		sException.append("\n-------------------------------\n");
		sException.append("Cannot locate config file: 'LocalConfig.xml'! \n");
		sException.append("Application terminated! \n");
		sException.append("\n-------------------------------\n");
		throw(sException);
	}
	return;
}

// ---------------------------------------------------------------------------
//  PopulateData -- A routine to populate configuration variables
// ---------------------------------------------------------------------------
/*
void PopulateData(RapidXMLData& xd, GlobalConfig& globalConfig)
{
	try
	{
		//Global config
		// Set up the root element
		xd.SetRootElem("GlobalModuleConfig");

		globalConfig.setGlobalConfigItem(xd.ReadNodeKeyAsString("@GlobalConfigItem", ""));
		globalConfig.setFMS_family(xd.ReadNodeKeyAsString("@family", ""));
		globalConfig.setFMS_model(xd.ReadNodeKeyAsString("@model", ""));
		globalConfig.setFMS_stepping(xd.ReadNodeKeyAsString("@stepping", ""));
		globalConfig.setQPIDeviceID(xd.ReadNodeKeyAsString("@QPIDeviceID", ""));
		globalConfig.setQPIRegValue(xd.ReadNodeKeyAsString("@QPIRegValue", ""));
		globalConfig.setQPIRate(xd.ReadNodeKeyAsString("@QPIRate", ""));
		
		globalConfig.setPCHS7_LPCDeviceID(xd.ReadNodeKeyAsString("@S7_LPCDeviceID", ""));
		globalConfig.setPCHS7_PCHName(xd.ReadNodeKeyAsString("@S7_PCHName", ""));
		globalConfig.setPCHS7_PCHNameDefault(xd.ReadNodeKeyAsString("@S7_PCHNameDefault", ""));

		globalConfig.setPCHS5_LPCDeviceID(xd.ReadNodeKeyAsString("@S5_LPCDeviceID", ""));
		globalConfig.setPCHS5_PCHName(xd.ReadNodeKeyAsString("@S5_PCHName", ""));
		globalConfig.setPCHS5_PCHNameDefault(xd.ReadNodeKeyAsString("@S5_PCHNameDefault", ""));
		

		
		if (igPrintConfig)
		{
			std::cout << "Data has been populated!" << std::endl;
			std::cout << "GlobalConfigItem: " << globalConfig.getGlobalConfigItem() << std::endl;
			std::cout << "FMS_family: " << globalConfig.getFMS_family() << std::endl;

			string sResult = globalConfig.getFMS_model();
			vector<string> svResult;
			SplitString(sResult, svResult, '|');
			std::cout << "FMS_model raw string: " << sResult << std::endl;
			std::cout << "FMS_model unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "FMS_model unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}

			std::cout << "FMS_stepping: " << globalConfig.getFMS_stepping() << std::endl;


			sResult = globalConfig.getQPIDeviceID();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "QPIDeviceID raw string: " << sResult << std::endl;
			std::cout << "QPIDeviceID unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "QPIDeviceID unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}

			sResult = globalConfig.getQPIRegValue();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "QPIRegValue raw string: " << sResult << std::endl;
			std::cout << "QPIRegValue unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "QPIRegValue unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}
			
			sResult = globalConfig.getQPIRate();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "QPIRate raw string: " << sResult << std::endl;
			std::cout << "QPIRate unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "QPIRate unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}

			std::cout << "PCHS5_PCHNameDefault: " << globalConfig.getPCHS5_PCHNameDefault() << std::endl;

			sResult = globalConfig.getPCHS5_LPCDeviceID();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "PCHS5_LPCDeviceID raw string: " << sResult << std::endl;
			std::cout << "PCHS5_LPCDeviceID unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "PCHS5_LPCDeviceID unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}

			sResult = globalConfig.getPCHS5_PCHName();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "PCHS5_PCHName raw string: " << sResult << std::endl;
			std::cout << "PCHS5_PCHName unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "PCHS5_PCHName unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}

			std::cout << "PCHS7_PCHNameDefault: " << globalConfig.getPCHS7_PCHNameDefault() << std::endl;

			sResult = globalConfig.getPCHS7_LPCDeviceID();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "PCHS7_LPCDeviceID raw string: " << sResult << std::endl;
			std::cout << "PCHS7_LPCDeviceID unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "PCHS7_LPCDeviceID unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}


			sResult = globalConfig.getPCHS7_PCHName();
			svResult.clear();
			SplitString(sResult, svResult, '|');

			std::cout << "PCHS7_PCHName raw string: " << sResult << std::endl;
			std::cout << "PCHS7_PCHName unrolled string method 1: " << std::endl;
			for (int i = 0; i < svResult.size(); i++)
			{
				std::cout << svResult[i] << " index = " << i << endl;
			}
			std::cout << "PCHS7_PCHName unrolled string method 2: " << std::endl;
			for (std::vector<string>::iterator it = svResult.begin(); it != svResult.end(); ++it)
			{
				std::cout << ' ' << *it << endl;
			}
		}
	}
	catch (...)
	{
		std::string sException;
		sException.append("\n-------------------------------\n");
		sException.append("Cannot locate config file: 'GlobalConfig.xml'! \n");
		sException.append("Application terminated! \n");
		sException.append("\n-------------------------------\n");
		throw(sException);
	}
	return;
}
*/

void Init(void)
{
	
	tStartTime = std::time(nullptr);
	if (iDebugFlag)
	{
		std::string sTemp = std::asctime(std::localtime(&tStartTime));
		std::cout << "tStartTime = " << sTemp << std::endl;
	}
	//xd.LoadXMLFile("GlobalConfig.xml");
	

	// Logic needs to be done to determine if this test is a pass or fail.  
	//If indeterminate, it means that the test was interrupted
	igPassFailStatus = ReturnValueDef::Success;  // Success
	//igPassFailStatus = 1;  // Fail
	//igPassFailStatus = 2;  // Indeterminate 
	iColorText = 0;
	iSec = 0;
	iMin = 0;
	iHour = 0;
	iOptionValid = 0;
	iRun = 1;
	iArgIndex = 0;
	iPrintVersionFlag = 1;
	iPrintSuccessFlag = 1;

}

void PrintVersion(void)
{
	std::cout << std::endl << "--- Genuine Intel Test ---" << std::endl << "..." << std::endl << "Version: " << sgGoldModuleVersion << std::endl << "..." << std::endl << std::endl;
}

void SignalFun(int iSigNum)
{
	// If you want to print out the signal, do the following
	cout << "Signal is:" << iSigNum << endl;

	// Depending on your routine, you may want to have some sort of exit message ... however you may also want to comment these out
	cout << endl << "Do the soft clean up here" << endl;
	
	// Do cleanup and close up stuff here 
	CleanUp();

	// Exit the program with one of the accepted error levels. 
	//0 = Success
	//1 = Fail
	//2 = Indeterminate 
	igPassFailStatus = ReturnValueDef::Indeterminate;

    // if you get to this logic, most likely your answer should always be a 2
	std::string sTemp = "Error: " + UtilConvert(igPassFailStatus) + " Indeterminate!";
	PrintColorMsg(sTemp, TextColor::Yellow);
	exit(igPassFailStatus);

}

void CleanUp()
{
	td.RemoveFile(sgGoldModuleResultsFile);
}

void WriteResultsFile(int iPassFailStatus, string sCV)  
{

	// pass fail logic using iPassFailStatus  with 0=pass, 1=fail, 2=indeterminate

	// Write Results File

	td.WriteToFile(sgGoldModuleResultsFile, "Genuine Intel CPU Test");	//test module name
	std::string sTemp = "Module Version: " + sgGoldModuleVersion;
	td.WriteToFile(sgGoldModuleResultsFile, sTemp);
	sTemp = "Start Time: ";
	sTemp.append(std::asctime(std::localtime(&tStartTime)));
	td.WriteToFileNoEndL(sgGoldModuleResultsFile, sTemp);

	if (iPassFailStatus == 0)
	{
		td.WriteToFile(sgGoldModuleResultsFile, "Test Result - PASS ");	//pass
		td.WriteToFile(sgGoldModuleResultsFile, "Expected: GenuineIntel");
		td.WriteToFile(sgGoldModuleResultsFile, "Detected: " + sCV);

	}
	if (iPassFailStatus == 1)
	{
		td.WriteToFile(sgGoldModuleResultsFile, "Test Result - FAIL");	//fail
		td.WriteToFile(sgGoldModuleResultsFile, "Expected: GenuineIntel");
		td.WriteToFile(sgGoldModuleResultsFile, "Detected: " + sCV);

	}
	if (iPassFailStatus == 2)
	{
		td.WriteToFile(sgGoldModuleResultsFile, "Test Result - Indeterminate"); //aborted
	}
	if (iPassFailStatus == 3)
	{
		td.WriteToFile(sgGoldModuleResultsFile, "Test Result - No Compare Option Used"); //-nc option used
	}


	if (igPauseApp)
	{
		PauseWQuit();
	}

	tEndTime = std::time(nullptr);
	sTemp = "End Time: ";
	sTemp.append(std::asctime(std::localtime(&tEndTime)));
	td.WriteToFileNoEndL(sgGoldModuleResultsFile, sTemp);

	double seconds = difftime(tEndTime, tStartTime);
	sTemp = "Total Time: ";
	sTemp.append(" seconds: ");
	sTemp.append(UtilConvert(seconds));
	

	td.WriteToFileNoEndL(sgGoldModuleResultsFile, sTemp);
}


	void HelpUseage(void)
	{
		std::cout << "Test Information:" << std::endl;
		std::cout << " GenIntel.exe reads the General Specific Register" << std::endl;
		std::cout << " and compares it to \"GenuineIntel\".  If the read value" << std::endl;
		std::cout << " matches the expected value, the test will pass." << std::endl << std::endl;
		std::cout << "Possible options are as follows:" << std::endl;
		std::cout << " -h          = Help or Usage (this message)" << std::endl;
		std::cout << "               Example:" << std::endl;
		std::cout << "               GenIntel.exe -h" << std::endl << std::endl;
		std::cout << " -info       = Information switch publishes parallel information" << std::endl;
		std::cout << "               using the following scheme:" << std::endl;
		std::cout << "               \"parallel:yes|socket:yes|core:yes\"" << std::endl;
		std::cout << "               Example:" << std::endl;
		std::cout << "               GenIntel.exe -info" << std::endl << std::endl;
		std::cout << " -resultName = The resultName switch provides a way to name " << std::endl;
		std::cout << "               the results file as desired." << std::endl;
		std::cout << "               This is for the convenience of the control program. " << std::endl;
		std::cout << "               Example:" << std::endl;
		std::cout << "               GenIntel.exe -resultName GenIntel_results_01.txt " << std::endl << std::endl;
		std::cout << " -c          = If present, this option will display text in various colors" << std::endl;
		std::cout << "               Example:" << std::endl;
		std::cout << "               GenIntel.exe -c" << std::endl << std::endl;
		//     std::cout << " -hrs        = hours option ... " << std::endl;
		//     std::cout << "               Use: GoldModuleTemplate -hrs <integer value> " << std::endl;
		//     std::cout << "               Indicating the number of hours GoldModuleTemplate should run" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -hrs" << std::endl << std::endl;
		//     std::cout << " -m          = minutes option ... " << std::endl;
		//     std::cout << "               Use: GoldModuleTemplate -m <integer value> " << std::endl;
		//     std::cout << "               Indicating the number of minutes GoldModuleTemplate should run" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -m" << std::endl << std::endl;
		//     std::cout << " -s          = seconds option ... " << std::endl;
		//     std::cout << "               Use: GoldModuleTemplate -s <integer value> " << std::endl;
		//     std::cout << "               Indicating the number of seconds GoldModuleTemplate should run" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -s" << std::endl << std::endl;
		//     std::cout << " -d          = debug option" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -d" << std::endl << std::endl;
		//     std::cout << " -pa         = pause app option" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -pa" << std::endl << std::endl;
		//     std::cout << " -plx        = Read and print local config XML opt" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -plx" << std::endl << std::endl;
		//     std::cout << " -plt        = Read and print local config text opt" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -plt" << std::endl << std::endl;
		//     std::cout << " -pa         = pause app opt" << std::endl;     
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -pa" << std::endl << std::endl;
		//     std::cout << " -r          = Win Ring 0 opt" << std::endl;
		//     std::cout << "               Example:" << std::endl;
		//     std::cout << "               GoldModuleTemplate.exe -r" << std::endl << std::endl;

		std::cout << "Dependencies:" << std::endl;
//		std::cout << " << std::endl << std::endl;
		std::cout << std::endl << "Copyright (C) 2015, Intel Corporation" << std::endl;
	}


// begin assembly code
const int iGImax = 13;

std::string sGI = "GenuineIntel";

std::string sOJK;

std::string getCPUmfg()
{

	char sSysType[iGImax] = { 0 };
#if defined (__INTEL_COMPILER)

	__asm
	{
		//Get CPU Manufacturer by setting EAX = 0 using CPUID
		xor eax, eax
			cpuid

			//Get the first part of the Manufacturer name which is stored in EBX
			mov eax, ebx
			mov sSysType[0], al
			mov sSysType[1], ah
			shr eax, 16
			mov sSysType[2], al
			mov sSysType[3], ah

			//Get the second part of the name which is stored in EDX
			mov eax, edx
			mov sSysType[4], al
			mov sSysType[5], ah
			shr eax, 16
			mov sSysType[6], al
			mov sSysType[7], ah

			//Get the third part of the name which is stored in ECX
			mov eax, ecx
			mov sSysType[8], al
			mov sSysType[9], ah
			shr eax, 16
			mov sSysType[10], al
			mov sSysType[11], ah
			mov sSysType[12], 00
	}
	sOJK.assign(sSysType);

	return sOJK;

#else
	//printf(("\n\nPlease compile this program with Intel C++ Compiler\n");
	//cout << endl << "Please compile this program with an Intel C++ Compiler" << endl;
	std::cout << std::endl << "Please compile this program with an Intel C++ Compiler" << std::endl;


#endif
}
// end assembly code

void PauseWQuit(void)
{
	// Pause code
	std::cout << "Please press 'q' <ENTER> to quit: ";
	std::string PauseStr;
	std::cin >> PauseStr;
}

void PrintColorMsg(std::string sMsg, TextColor iColor)
{
	if (iColorText == 0)
	{
		std::cout << std::endl << sMsg << std::endl;
	}
	else
	{
		if (iColor == TextColor::Red)
		{
#ifdef __WIN_OS__
			HANDLE hCommandWindowTextColor = GetStdHandle(STD_OUTPUT_HANDLE);
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_INTENSITY));
			std::cout << std::endl << sMsg << std::endl;
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN));
#endif
#ifdef __LIN_OS__
			std::cout << "\033[0;31m";
			std::cout << std::endl << sMsg << std::endl;
			std::cout << "\033[0m";
#endif
		}
		if (iColor == TextColor::Green)
		{

#ifdef __WIN_OS__
			HANDLE hCommandWindowTextColor = GetStdHandle(STD_OUTPUT_HANDLE);
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_GREEN | FOREGROUND_INTENSITY));
			std::cout << std::endl << sMsg << std::endl;
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN));
#endif
#ifdef __LIN_OS__
			std::cout << "\033[0;32m";
			std::cout << std::endl << sMsg << std::endl;
			std::cout << "\033[0m";
#endif
		}
		if (iColor == TextColor::Yellow)
		{
#ifdef __WIN_OS__
			HANDLE hCommandWindowTextColor = GetStdHandle(STD_OUTPUT_HANDLE);
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY));
			std::cout << std::endl << sMsg << std::endl;
			SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN));
#endif
#ifdef __LIN_OS__
			std::cout << "\033[0;33m";
			std::cout << std::endl << sMsg << std::endl;
			std::cout << "\033[0m";
#endif
		}

	}
}
bool is_integer(const std::string & s){
	return std::regex_match(s, std::regex("[0-9]+"));
}
bool isOptionValid(int iArgLocal, int argcLocal, char *argvLocal[], VarType vt)
{
	// Start out as Valid
	bool iRetVal = true;
	std::string sMsg = "";
	std::string sTemp = argvLocal[iArgLocal];

	if (((iArgLocal + 1) < argcLocal) && strlen(argvLocal[iArgLocal + 1]) > 0)
	{
		if (vt == VarType::vtINT)
		{
			if (!is_integer(argvLocal[iArgLocal + 1]))
			{
				iRetVal = false;
				sMsg = "Wrong argument type format for argument: '" + sTemp + "'!";
			}
		}
	}
	else
	{
		// invalid
		iRetVal = false;
		sMsg = "No argument for '" + sTemp + "' detected!";
	}
	// if there was an invalid argument
	if (iRetVal == false)
	{
		PrintColorMsg(sMsg, TextColor::Red);
	}
	return iRetVal;
}

void handleArgs(int argc, char *argv[])
{

	// Optional args
	// Make sure the options can only be run one time
	// Load up all the possible args
	std::vector <string> sArgs_v;
	sArgs_v.push_back("-h");
	sArgs_v.push_back("-info");
	sArgs_v.push_back("-resultName");
//	sArgs_v.push_back("-hrs");
//	sArgs_v.push_back("-m");
//	sArgs_v.push_back("-s");
//	sArgs_v.push_back("-d");
//	sArgs_v.push_back("-p");
//	sArgs_v.push_back("-plx");
//	sArgs_v.push_back("-plt");
//	sArgs_v.push_back("-pa");
	sArgs_v.push_back("-c");
//	sArgs_v.push_back("-r");

	if (argc > 1)
	{
		for (int iArg = 1; iArg < argc; iArg++)
		{
			for (int iVec = 0; iVec < sArgs_v.size(); iVec++)
			{
				if (argv[iArg] == sArgs_v[iVec])
				{
					// Only the options that need to be processed before all the other ones need to be in this list
					if (sArgs_v[iVec] == std::string("-c"))
					{
						iColorText = 1;
					}
				}
			}
		}
		for (int iArg = 1; iArg < argc; iArg++)
		{
			iArgIndex = iArg;
			iOptionValid = 0;
			for (int iVec = 0; iVec < sArgs_v.size(); iVec++)
			{
				if (argv[iArg] == sArgs_v[iVec])
				{
					iOptionValid = 1;
					if (sArgs_v[iVec] == std::string("-h"))
					{
						iRun = 0;
						PrintVersion();
						HelpUseage();
					}
					if (sArgs_v[iVec] == std::string("-info"))
					{
						iRun = 0;
						iPrintVersionFlag = 0;
						iPrintSuccessFlag = 0;
						std::cout << "\"parallel:yes|socket:yes|core:yes\"" << std::endl;
					}
					if (sArgs_v[iVec] == std::string("-resultName"))
					{
						PrintVersion();
						sgGoldModuleResultsFile = argv[++iArg];
						sCompVal = getCPUmfg();
						//std::cout << sCompVal << std::endl;

						if (sCompVal == "GenuineIntel")
						{
							std::cout << "Expected --> GenuineIntel" << std::endl;
							std::cout << "Detected --> " << sCompVal << std::endl;
							//std::cout << "Genuine Intel Test Passed!!!" << std::endl;

							igPassFailStatus = 0;
						}
						else
						{
							std::cout << "Expected --> GenuineIntel" << std::endl;
							std::cout << "Detected --> " << sCompVal << std::endl;
							//std::cout << "Genuine Intel Test Failed!!!" << std::endl;
							igPassFailStatus = 1;
						}
					}
					if (sArgs_v[iVec] == std::string("-hrs"))
					{
						// Hours
						if (isOptionValid(iArg, argc, argv, VarType::vtINT))
						{
							iHour = CustomAsciiToInteger(argv[++iArg]);
						}
						else
						{
							iRun = 0;
							iOptionValid = 0;
						}

					}
					if (sArgs_v[iVec] == std::string("-m"))
					{
						// Minutes
						if (isOptionValid(iArg, argc, argv, VarType::vtINT))
						{
							iMin = CustomAsciiToInteger(argv[++iArg]);
						}
						else
						{
							iRun = 0;
							iOptionValid = 0;
						}
					}
					if (sArgs_v[iVec] == std::string("-s"))
					{
						// Seconds
						if (isOptionValid(iArg, argc, argv, VarType::vtINT))
						{
							iSec = CustomAsciiToInteger(argv[++iArg]);
						}
						else
						{
							iRun = 0;
							iOptionValid = 0;
						}
					}
					if (sArgs_v[iVec] == std::string("-d"))
					{
						// debug
						iDebugFlag = 1;
					}
					if (sArgs_v[iVec] == std::string("-p"))
					{
						std::cout << std::endl << "Entering print opt" << std::endl;
						igPrintConfig = 1;
					}
					if (sArgs_v[iVec] == std::string("-plx"))
					{
						std::cout << std::endl << "Entering Read Local Config XML opt" << std::endl;
						ReadLocalConfig();
					}
					if (sArgs_v[iVec] == std::string("-plt"))
					{
						std::cout << std::endl << "Entering Read Local Config text opt" << std::endl;
						ReadLocalTextConfig();
					}
					if (sArgs_v[iVec] == std::string("-pa"))
					{
						std::cout << std::endl << "Entering pause app opt" << std::endl;
						igPauseApp = 1;
					}
					if (sArgs_v[iVec] == std::string("-c"))
					{
						PrintVersion();
						std::cout << std::endl << "Entering color text opt" << std::endl;
						#ifdef __WIN_OS__
						HANDLE hCommandWindowTextColor = GetStdHandle(STD_OUTPUT_HANDLE);
						SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_GREEN | FOREGROUND_INTENSITY));
						//std::cout << "Some green text ..." << std::endl << std::endl;
						SetConsoleTextAttribute(hCommandWindowTextColor, (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN));
						#endif
						#ifdef __LIN_OS__
						std::cout << "\033[1;32m";
						//std::cout << std::endl << ".." << std::endl << "Some green text ..." << std::endl << std::endl;
						std::cout << "\033[0m";
						#endif

						if (iRun)
						{
							sCompVal = getCPUmfg();

							if (sCompVal == "GenuineIntel")
							{
								std::cout << "Expected --> GenuineIntel" << std::endl;
								std::cout << "Detected --> " << sCompVal << std::endl;
								//std::cout << "Genuine Intel Test Passed!!!" << std::endl;

								igPassFailStatus = 0;
							}
							else
							{
								std::cout << "Expected --> GenuineIntel" << std::endl;
								std::cout << "Detected --> " << sCompVal << std::endl;
								//std::cout << "Genuine Intel Test Failed!!!" << std::endl;
								igPassFailStatus = 1;
							}
						}						
						
					}
					//if (sArgs_v[iVec] == std::string("-r"))
					//{
					//	std::cout << std::endl << "Entering Win Ring 0 opt" << std::endl;
					//	WinRing0Fun();
					//}


					// Erase current vector so the option doesn't repeat
					sArgs_v.erase(sArgs_v.begin() + (iVec));
				}

			}
			if (iDebugFlag)
			{
				std::cout << std::endl << "iOptionValid = " << iOptionValid << std::endl;
			}
			if (iOptionValid == 0)
			{
				break;
			}
		}
		if (iOptionValid == 0)
		{
			std::string sArgTemp = argv[iArgIndex];
			std::string sTempMsg = "Option " + sArgTemp + " invalid!";
			PrintColorMsg(sTempMsg, TextColor::Red);
			iRun = 0;
			igPassFailStatus = ReturnValueDef::InvalidArgs;
			HelpUseage();

		}
	}
	else
	{
		// Default message if no arguments are used  ... it may be the useage message or it may be OK that no args are used
		PrintVersion();
		std::cout << "No args used!!" << std::endl;
		if (iRun)
		{
			sCompVal = getCPUmfg();
			//std::cout << sCompVal << std::endl;

			if (sCompVal == "GenuineIntel")
			{
				std::cout << "Expected --> GenuineIntel" << std::endl;
				std::cout << "Detected --> " << sCompVal << std::endl;
				//std::cout << "Genuine Intel Test Passed!!!" << std::endl;

				igPassFailStatus = 0;
			}
			else
			{
				std::cout << "Expected --> GenuineIntel" << std::endl;
				std::cout << "Detected --> " << sCompVal << std::endl;
				//std::cout << "Genuine Intel Test Failed!!!" << std::endl;
				igPassFailStatus = 1;
			}
		}
	}

}

void PrintSuccess(void)
{
	if (iRun)
	{
		if (igPassFailStatus == ReturnValueDef::Success)
		{
			PrintColorMsg("Genuine Intel CPU Module Success!", TextColor::Green);
		}
		if (igPassFailStatus == ReturnValueDef::Fail)
		{
			PrintColorMsg("Genuine Intel CPU Module Fail!", TextColor::Red);
		}
		if (igPassFailStatus == ReturnValueDef::Indeterminate)
		{
			PrintColorMsg("Genuine Intel CPU Module Interrupted!", TextColor::Yellow);
		}
		if (igPassFailStatus == ReturnValueDef::InvalidArgs)
		{
			PrintColorMsg("Genuine Intel CPU Module has invalid arguments!", TextColor::Red);
		}
		if (igPassFailStatus == ReturnValueDef::ConfigMismatch)
		{
			PrintColorMsg("Genuine Intel CPU Modulee has a configuration mismatch!", TextColor::Yellow);
		}	
		if(igPassFailStatus != ReturnValueDef::Success)
		{
			cout << "Return Status = " << igPassFailStatus << endl;
		}
	}

}
//..main

int main(int argc, char *argv[])
{
	
	// .W // windows 
#if defined __WIN_64__ 
	sgGoldModuleVersion = "1.0.16.64b.W";
#endif

	#if defined __WIN_32__ 
	sgGoldModuleVersion = "1.0.16.32b.W";
	#endif

	// .L linux
#if defined __LIN_64__
	sgGoldModuleVersion = "1.0.16.64b.L";
#endif
#if defined __LIN_32__
	sgGoldModuleVersion = "1.0.16.32b.L";
#endif


	// Need to include signal for Softkill functions
	// If this thread is sent a signal SIGINT, we need to send it to the signal function 
	signal(SIGINT, SignalFun);


	// Print out version
	//if (iPrintVersionFlag != 0)
	//{
	//	PrintVersion();
	//}

	// Parse both text local config style and xml style
	
	Init();
	handleArgs(argc, argv);

	//..clean up result files ... Clean file before another one is written
	CleanUp();

	//if (iRun)
	//{
	//	PopulateData(xd, gGlobalConfig);
	//}

	if (iRun)
	{		
		WriteResultsFile(igPassFailStatus, sCompVal);
	}
	
	if (iPrintSuccessFlag != 0)
	{
		PrintSuccess();
	}
	if (igPauseApp)
	{
		PauseWQuit();
	}

	return igPassFailStatus;
}
