#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#pragma warning(disable : 4091)
//https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h - "That's all well and nice for Johnny"
#include <Windows.h>
#include <ShlObj.h>
#include <DbgHelp.h>
#include <stdio.h>
#pragma comment(lib, "dbghelp.lib")

wchar_t* localdata_path(void);

int CALLBACK wWinMain(_In_ HINSTANCE hInst, _In_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
	//MessageBoxW(NULL, L"Attach me.", L"Virtual Idea Area", MB_ICONERROR);
	//get pid, tid and exception data
	DWORD parent_pid = (DWORD) wcstoull(lpCmdLine, &lpCmdLine, 16);
	DWORD parent_tid = (DWORD) wcstoull(lpCmdLine, &lpCmdLine, 16);
	MINIDUMP_EXCEPTION_INFORMATION excp = {0};
	excp.ThreadId = parent_tid;
	excp.ClientPointers = TRUE;
	excp.ExceptionPointers = (PEXCEPTION_POINTERS) wcstoull(lpCmdLine, &lpCmdLine, 16);
	//open process handle
	HANDLE parent_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE | PROCESS_TERMINATE, TRUE, parent_pid);

	if(parent_process) {
		//build paths to dumpfiles
		wchar_t* local = localdata_path();
		wchar_t* dump_large_name = NULL;
		wchar_t* dump_mini_name = NULL;
		if(local) {
			dump_large_name = malloc(2*wcslen(local) + sizeof(L"VIA_latest.dmp"));
			if(dump_large_name) {
				wcscpy(dump_large_name, local);
				wcscat(dump_large_name, L"VIA_latest.dmp");
			}
			size_t mnlen = 2*wcslen(local) + sizeof(L"VIA_yyyymmddhhmmssmmm.dmp");
			dump_mini_name = malloc(mnlen);
			if(dump_mini_name) {
				SYSTEMTIME st = {0};
				GetSystemTime(&st);
				swprintf(dump_mini_name, mnlen, L"%sVIA_%u%u%u%u%u%u%u.dmp",
					local,
					(unsigned) st.wYear%10000,
					(unsigned) st.wMonth%100,
					(unsigned) st.wDay%100,
					(unsigned) st.wHour%100,
					(unsigned) st.wMinute%100,
					(unsigned) st.wSecond%100,
					(unsigned) st.wMilliseconds%1000);
			}
		}
		//minidump large
		if(dump_large_name) {
			HANDLE dump_large = CreateFileW(dump_large_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if(dump_large != INVALID_HANDLE_VALUE) {
				MiniDumpWriteDump(parent_process, parent_pid, dump_large, MiniDumpNormal | MiniDumpWithDataSegs | MiniDumpWithHandleData, &excp, NULL, NULL);
				CloseHandle(dump_large);
			}
		}
		free(dump_large_name);
		//minidump small
		if(dump_mini_name) {
			HANDLE dump_mini = CreateFileW(dump_mini_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if(dump_mini != INVALID_HANDLE_VALUE) {
				MiniDumpWriteDump(parent_process, parent_pid, dump_mini, MiniDumpNormal, &excp, NULL, NULL);
				CloseHandle(dump_mini);
			}
		}
		free(dump_mini_name);
		//kill parent
		TerminateProcess(parent_process, 14);
	}
	//inform the user
	MessageBoxW(NULL, L"Virtual Idea Area encountered an unexpected error and had to be closed.", L"Virtual Idea Area", MB_ICONERROR);
	return 0;
}

wchar_t* localdata_path(void)
{
	wchar_t* w_lappdata = NULL;
	HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &w_lappdata);
	if(FAILED(hr)) return NULL;
	
	const wchar_t subdir[] = L"/Racaedym/VIA/";
	wchar_t* out = malloc(wcslen(w_lappdata) + sizeof(subdir));
	if(!out) {CoTaskMemFree(w_lappdata); return NULL;}
	wcscpy(out, w_lappdata);
	wcscat(out, subdir);

	CoTaskMemFree(w_lappdata);
	return out;
}