
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#include "libdetect.h"

#define REASON_VIRTUAL_MACHINE 0
#define REASON_WINE 		   1
#define REASON_DEBUGGER		   2

#define SHOW_MESSAGE_NEVER  0
#define SHOW_MESSAGE_ALWAYS 1

DWORD WINAPI start_main_checks( LPVOID lpParam );
void create_main_threads(void);
void exit_proc(int reason, int show_msg);

HANDLE ghCheckThread;
DWORD  gdwCheckThreadId;

HANDLE ghDebugThread;
DWORD  gdwDebugThreadId;

void exit_proc(int reason, int show_msg)
{
	if (show_msg == SHOW_MESSAGE_ALWAYS)
	{
		switch(reason) {
			case REASON_VIRTUAL_MACHINE:
				MessageBox(0, "This program cannot be run in a Virtual Machine.", "Malware Inc.", 0);
				break;
			case REASON_WINE:
				MessageBox(0, "This program cannot be run under Wine.", "Malware Inc.", 0);
				break;
			case REASON_DEBUGGER:
				MessageBox(0, "This program cannot be run in a debugger.", "Malware Inc.", 0);
				break;
		}
	}

	ExitProcess(-1);
}

DWORD WINAPI start_main_checks( LPVOID lpParam )
{
	for (;;)
	{
		if (check_vmrpill())
			exit_proc(REASON_VIRTUAL_MACHINE, SHOW_MESSAGE_NEVER);
	
		if (check_wine() == 1)
			exit_proc(REASON_WINE, SHOW_MESSAGE_NEVER);
		
		Sleep(1);
	}
	return(0);
}

DWORD WINAPI start_debugger_checks( LPVOID lpParam)
{
	for (;;)
	{
		if (check_debug())
			exit_proc(REASON_DEBUGGER, SHOW_MESSAGE_NEVER);
		
		Sleep(1);
	}
}

void create_main_threads(void)
{
	ghCheckThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size  
            start_main_checks,       // thread function name
            0,         				// argument to thread function 
            0,                      // use default creation flags 
            &gdwCheckThreadId);   		// returns the thread identifier 

	if (ghCheckThread == NULL)
	{
		MessageBox(0, "Cannot create a thread!", "Threads", 0);
		return;
	}

	ghDebugThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size  
            start_debugger_checks,       // thread function name
            0,         				// argument to thread function 
            0,                      // use default creation flags 
            &gdwDebugThreadId);   		// returns the thread identifier 

	if (ghDebugThread == NULL)
	{
		MessageBox(0, "Cannot create a thread!", "Threads", 0);
		return;
	}
}

int main(void)
{
	MessageBox(0, "Here we go!", "Malware Inc.", 0);
	create_main_threads();
	MessageBox(0, "Enter to finish.", "Malware Inc.", 0);
	MessageBox(0, "All good?", "Malware Inc.", 0);
}

