#include "stdafx.h"
#include "Hook.h"
#include "ProcessRunner.h"
ProcessRunner::ProcessRunner()
{
LOG(Logger::cDebug, "ProcessRunner::ProcessRunner(){");
m_bRunning = false;
m_pOrigCreateProcess = NULL;
m_pOrigDeleteFile = NULL;
m_bFirst = true;
LOG(Logger::cDebug, "ProcessRunner::ProcessRunner()}");
}
ProcessRunner& ProcessRunner::GetInstance()
{
static ProcessRunner runner;
return runner;
}
ProcessRunner::~ProcessRunner()
{
}
BOOL WINAPI ProcessRunner::CreateProcess(
LPCTSTR lpApplicationName, // name of executable module
LPTSTR lpCommandLine, // command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
BOOL bInheritHandles, // handle inheritance option
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // new environment block
LPCTSTR lpCurrentDirectory, // current directory name
LPSTARTUPINFO lpStartupInfo, // startup information
LPPROCESS_INFORMATION lpProcessInformation // process information
)
{
LOG(Logger::cDebug, "ProcessRunner::CreateProcess(%s, %s, %p, %p, %d, %d, %p, %s, %p, %p){",
lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory,
lpStartupInfo, lpProcessInformation);
MK_TRY;
GetInstance().Hook(cDeleteFileA, false);
long lEvent = 0;
char *p = strstr(lpCommandLine, "-e ");
if(NULL != p)
{
p += 3;
char *q = strstr(p, " ");
if(NULL != q)
{
char buf[100];
memset(buf, 0, sizeof buf);
memcpy(buf, p, q-p);
lEvent = atoi(buf);
}
}
_bstr_t sNewCommadLine = GetInstance().CreateCommandLine(lEvent);
BOOL bRet = GetInstance().m_pOrigCreateProcess(lpApplicationName,
static_cast<LPTSTR>(sNewCommadLine),
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
GetInstance().m_bFirst = false;
MK_CATCH;
::SetLastError(MK_VAR.GetErrorCode());
return FAILED(MK_VAR.GetErrorCode()) ? FALSE : TRUE;
}
BOOL WINAPI ProcessRunner::DeleteFile(
LPCTSTR lpFileName // file name
)
{
LOG(Logger::cDebug, "ProcessRunner::DeleteFile(%s){", lpFileName);
lpFileName;
LOG(Logger::cDebug, "ProcessRunner::DeleteFile()}");
return TRUE;
}
void ProcessRunner::Hook(ProcessRunner::API HookFunc, bool bHook)
{
LOG(Logger::cDebug, "ProcessRunner::Hook(%d, %d){", HookFunc, bHook);
_bstr_t sFunc;
HMODULE hModule = NULL;
PROC HookProc = NULL;
PROC *pOrigProc = NULL;
switch(HookFunc)
{
case cCreateProcessA:
sFunc = "CreateProcessA";
hModule = ::GetModuleHandle("DevShl.dll");
HookProc = (PROC)ProcessRunner::CreateProcess;
pOrigProc = (PROC*)&m_pOrigCreateProcess;
break;
case cDeleteFileA:
sFunc = "DeleteFileA";
hModule = ::GetModuleHandle("DevBld.pkg");
HookProc = (PROC)ProcessRunner::DeleteFile;
pOrigProc = (PROC*)&m_pOrigDeleteFile;
break;
default:
MK_THROW(SppMkError::eInvalidParam, "ProcessRunner::Hook(): unknownd hook proc %d", HookProc);
break;
}
HOOKFUNCDESC stToHook ;
stToHook.szFunc = static_cast<char*>(sFunc);
DWORD uiCount = 0;
if(bHook && NULL == *pOrigProc)
{
LOG(Logger::cDebug, "ProcessRunner::Hook(): hooking %s", stToHook.szFunc);
stToHook.pProc = HookProc;
TEST_BOOL(FALSE != HookImportedFunctionsByName(hModule, "KERNEL32.DLL",
1, &stToHook, pOrigProc, &uiCount));
}
else if(!bHook && NULL != *pOrigProc)
{
LOG(Logger::cDebug, "ProcessRunner::Hook(): unhooking %s", stToHook.szFunc);
PROC temp = NULL;
stToHook.pProc = *pOrigProc;
TEST_BOOL(FALSE != HookImportedFunctionsByName(hModule, "KERNEL32.DLL",
1, &stToHook, &temp, &uiCount));
*pOrigProc = NULL;
}
LOG(Logger::cDebug, "ProcessRunner::Hook()}");
}
void ProcessRunner::TearDown()
{
LOG(Logger::cDebug, "ProcessRunner::TearDown(){");
if(m_SetupParams.bDeleteAfterRun)
{
LOG(Logger::cDebug, "ProcessRunner::TearDown(): deleting file '%S'",
static_cast<WCHAR*>(m_SetupParams.sCommandLine));
::DeleteFileW(m_SetupParams.sCommandLine);
}
m_SetupParams = SetupParams();
SetRunning(false);
Hook(cCreateProcessA, false);
LOG(Logger::cDebug, "ProcessRunner::TearDown()}");
}
_bstr_t ProcessRunner::CreateCommandLine(long lEvent)
{
LOG(Logger::cDebug, "ProcessRunner::CreateCommandLine(%d){", lEvent);
_bstr_t s("vcspawn.exe -e ");
char buf[100];
s += itoa(lEvent, buf, 10);
s += " -m";
if(!m_bFirst)
{
s += _bstr_t("\n") + "echo skipping unnecessary build steps...";
}
else
{
s += _bstr_t("\n~vcecho!Executing '") + m_SetupParams.sCommandLine + _bstr_t("'");
s += _bstr_t("\n") + m_SetupParams.sCommandLine;
}
LOG(Logger::cDebug, "ProcessRunner::CreateCommandLine()}, ret = '%S'", s);
return s;
}
void ProcessRunner::Run(const SetupParams &Params, IApplication *pApp)
{
LOG(Logger::cDebug, "ProcessRunner::Run(%p){", pApp);
TEST_BOOL(!GetRunning());
m_pOrigCreateProcess = NULL;
m_pOrigDeleteFile = NULL;
m_bFirst = true;
Hook(cCreateProcessA, true);
Hook(cDeleteFileA, true); // (???) unhook CreateProcess if failed
m_SetupParams = Params;
TEST_HR(pApp->ExecuteCommand(L"BuildRebuildAll"));
LOG(Logger::cDebug, "ProcessRunner::Run()}");
}
void ProcessRunner::Stop(IApplication *pApp)
{
LOG(Logger::cDebug, "ProcessRunner::Stop(%p){", pApp);
TEST_HR(pApp->ExecuteCommand(L"BuildStop"));
LOG(Logger::cDebug, "ProcessRunner::Stop()}");
}