#include <Windows.h>
#include <intrin.h>

#include "Events.h"
#include "..\Runtime\Runtime.h"
#include "..\common\uthash_runtime.h"




#pragma comment( linker, "/subsystem:console" )
#pragma section("loader", read,execute)
#pragma code_seg("loader")

void* test_callback(PRUNTIME pRuntime, void* args)
{
	OUTPUTDEBUG("[*] callback: %s\n", (LPSTR)args);
	
	return NULL;
}

void go(){
	
	/* 1] prepare a runtime */
	PRUNTIME pRuntime = LoadRuntime();

	/* event variables */
	PMODULE_SPECIFIC_DATA peventSpecificData = (PMODULE_SPECIFIC_DATA)malloc(sizeof(MODULE_SPECIFIC_DATA));

	pRuntime->pModuleSpecificData[INDEX_EVENTS] = peventSpecificData;

	PVARIABLES_EVENTS pVariablesevent = (PVARIABLES_EVENTS)malloc(sizeof(VARIABLES_EVENTS));
	pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpVariables = pVariablesevent;


	/* event strings */
	STRINGS_EVENTS eventStrings =
	{
		{ '%', 'S', 0x0 },
		{ 'n', 'a', 'm', 'e', ' ', '%', 'S', '\n', 0x0 },
		{ 'p', 'S', 'i', 'n', 'k', ' ', '%', 'p', '	', 0x0 },
		{ 'T', 'a', 'r', 'g', 'e', 't', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 0x0 },
		{ 'N', 'a', 'm', 'e', ' ', ':', ' ', 0x0 },
		{ 'P', 'r', 'o', 'c', 'e', 's', 's', 'I', 'd', 0x0 },
		{ 'S', 'i', 'n', 'k', 'S', 'e', 't', 'S', 't', 'a', 't', 'u', 's', '\n', 0x0 },
		{ 'E', 'x', 'e', 'c', 'N', 'o', 't', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'Q', 'u', 'e', 'r', 'y', 'A', 's', 'y', 'n', 'c', ' ', 'f', 'a', 'i', 'l', 'e', 'd', ' ', 'w', 'i', 't', 'h', ' ', '=', ' ', '0', 'x', '%', 'X', '\n', 0x0 },
		{ '%', 'S', ' ', '%', 'd', '\n',  0x0 },
		{ 'S', 'E', 'L', 'E', 'C', 'T', ' ', '*', ' ', 'F', 'R', 'O', 'M', ' ', 'W', 'i', 'n', '3', '2', '_', 'P', 'r', 'o', 'c', 'e', 's', 's', 0x0 },
		{ 'l', 'o', 'a', 'd', 'e', 'r', 0x0 },
		{ 'e', 'm', 'p', 't', 'y', ' ', 'n', 'a', 'm', 'e', '\n', 0x0 },
		{ 'a', 'd', 'd', 'r', 'e', 'f', ':', ' ', '%', 'd', '\n', 0x0 },
		{ 'e', 'v', 'e', 'n', 't', ' ', 'o', 'c', 'c', 'u', 'r', 'e', 'd', '\n', 0x0 },
		{ 'C', 'r', 'e', 'a', 't', 'e', '\n', 0x0 },
		{ 'C', 'l', 'o', 's', 'e', '\n', 0x0 },
		{ 'C', 'o', 'n', 'n', 'e', 'c', 't', 'e', 'd', '\n', 0x0 },
		{ 'W', 'Q', 'L', 0x0 }, // UNICODE
		{ 'S', 'E', 'L', 'E', 'C', 'T', ' ', '*', ' ', 'F', 'R', 'O', 'M', ' ', ' ', '_', '_', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'C', 'r', 'e', 'a', 't', 'i', 'o', 'n', 'E', 'v', 'e', 'n', 't', ' ', 'W', 'I', 'T', 'H', 'I', 'N', ' ', '1', ' ', 'W', 'H', 'E', 'R', 'E', ' ', 'T', 'a', 'r', 'g', 'e', 't', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', ' ', 'I', 'S', 'A', ' ', '\'', 'W', 'I', 'n', '3', '2', '_', 'P', 'r', 'o', 'c', 'e', 's', 's', '\'', 0x0 },
		{ 'S', 'E', 'L', 'E', 'C', 'T', ' ', '*', ' ', 'F', 'R', 'O', 'M', ' ', ' ', '_', '_', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'D', 'e', 'l', 'e', 't', 'i', 'o', 'n', 'E', 'v', 'e', 'n', 't', ' ', 'W', 'I', 'T', 'H', 'I', 'N', ' ', '1', ' ', 'W', 'H', 'E', 'R', 'E', ' ', 'T', 'a', 'r', 'g', 'e', 't', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', ' ', 'I', 'S', 'A', ' ', '\'', 'W', 'I', 'n', '3', '2', '_', 'P', 'r', 'o', 'c', 'e', 's', 's', '\'', 0x0 },
		{ 'N', 'a', 'm', 'e', 0x0 },
		{ 'R', 'O', 'O', 'T', '\\', 'C', 'I', 'M', 'V', '2', 0x0 }, // UNICODE
		{ 00, 00, 00, 00, 00, 00, 00, 00, 0xC0, 00, 00, 00, 00, 00, 00, 0x46 }, // IUnknown
		{ 0x01, 0x78, 0x85, 0x7c, 0x81, 0x73, 0xcf, 0x11, 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 }, // IWbemObjectSink
		{ 0x87, 0xa6, 0x12, 0xdc, 0x7f, 0x73, 0xcf, 0x11, 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 }, // IWbemLocator
		{ 0x8c, 0xba, 0xfa, 0x1c, 0x23, 0x15, 0xd1, 0x11, 0xad, 0x79, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff }, // IUnsecuredApartment
		{ 0x81, 0xa6, 0x12, 0xdc, 0x7f, 0x73, 0xcf, 0x11, 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 }, // IWbemClassObject
		{ 0x11, 0xf8, 0x90, 0x45, 0x3a, 0x1d, 0xd0, 0x11, 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 }, // CLSID_WbemLocator
		{ 0x28, 0x20, 0xbd, 0x49, 0x23, 0x15, 0xd1, 0x11, 0xad, 0x79, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff }, // CLSID_UnsecuredApartment
	};
	
	pRuntime->pModuleSpecificData[INDEX_EVENTS]->lpStrings = &eventStrings;


	/* 1] fetch initial process list */
	//get_process_list(pRuntime);

	/* print list */
	//PPROCESS_LIST_ELEMENT tmp_elem, current;
	//HASH_ITER(pRuntime, hh, pVariablesevent->pProcessListUniqueByName, current, tmp_elem)
	//{
		//OUTPUTDEBUGRUNTIME(pRuntime, "process: %s number of instances: %d\n", current->strProcessName, current->dwNumberOfInstances);

		//HASH_DEL(pRuntime, pVariablesevent->pProcessList, current);
		
		//API_FREE(pRuntime, current);
	//}

	/* 2] start process creation/deletion callback */

	//start_process_creation_callback(pRuntime);
	//start_process_deletion_callback(pRuntime);
	
	
	// test process_addwatch, process_delwatch

	//PMONITORED_PROCESS p1;

	//process_addwatch(pRuntime, onbegin, e, MONITOR_FLAG_NONE, EVENT_PROCESS_P(e)->name);
	//p1 = process_addwatch(pRuntime, test_callback, "cal?.exe", 0, "cal?.exe");

	//monitored_process_dump(pRuntime);
	//PMONITORED_PROCESS p2 = process_addwatch(pRuntime, NULL, NULL, NULL, "calc.exe");
	//monitored_process_dump(pRuntime);
	//PMONITORED_PROCESS p3 = process_addwatch(pRuntime, test_callback, "notepa*", 0, "notepa*");
	//monitored_process_dump(pRuntime);

	/*process_delwatch(pRuntime, p1);
	monitored_process_dump(pRuntime);
	process_delwatch(pRuntime, p2);
	monitored_process_dump(pRuntime);
	process_delwatch(pRuntime, p3);
	monitored_process_dump(pRuntime);*/


	monitor_process_start(pRuntime);

	API_SLEEP(100000);


	/* cleanup */
	free(peventSpecificData);
	free(pVariablesevent);
}

int main(int argc, char *argcv[])
{
	go();
}