#include "StdAfx.h"
#include "SubProcess.h"

//!	バッファサイズ
#define	BUFFER_SIZE	65536

CSubProcess::CSubProcess(void)
{
	//	プロセス構造体初期化
	memset(&m_processInfo, 0 ,sizeof(m_processInfo));

	//	フラグクリア
	m_processCreated = 0;

	//	環境領域初期化
	ClearSubProcessEnvironment();
}

CSubProcess::~CSubProcess(void)
{
	TerminateSubProcess();

	SAFE_CLOSE_HANDLE(m_processInfo.hProcess);
	SAFE_CLOSE_HANDLE(m_processInfo.hThread);
}

///////////////////////////////////////////////////////////////////////
//	サブプロセス起動、制御
///////////////////////////////////////////////////////////////////////
/*!
	サブプロセスの起動
*/
int CSubProcess::RunSubProcess(CString command, CString workPath, CString idString)
{
	//	終了する
	TerminateSubProcess();

	//	パイプ初期化
	if(SetupPipe(idString))
		return(-1);

	//	環境変数初期化
	m_subProcessEnvironment.AppendWord('\0\0');

	//	プロセス情報構造体
	STARTUPINFO StartupInfo;
	::ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
	StartupInfo.cb = sizeof(STARTUPINFO);

	// ハンドルの継承を指定
	StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

	// DOS窓を表示しない
	StartupInfo.wShowWindow = SW_HIDE;

	// 標準出力ハンドルとエラー出力ハンドルを設定
	StartupInfo.hStdInput	= m_stdIn.GetReadPipe();
	StartupInfo.hStdOutput	= m_stdOut.GetWritePipe();
	StartupInfo.hStdError	= m_stdErr.GetWritePipe();

	//	セキュリティ属性
	SECURITY_ATTRIBUTES	sa;
	memset(&sa, 0, sizeof(sa));
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;	//	ハンドル継承可

	// コンソールアプリ起動
	if (!::CreateProcess(
		NULL,
		command.GetBuffer(0),
		&sa,
		NULL,
		TRUE,				// ハンドルの継承
		0,	// DOS窓を表示しないための指定
		m_subProcessEnvironment.GetPtr(),
		workPath,
		&StartupInfo,
		&m_processInfo))
	{
		return(-1);
	}

	m_processCreated = 1;
	return(0);
}


/*!
	プロセスは実行中か？
*/
int CSubProcess::SubProcessIsRunning()
{
	if(!m_processCreated)
		return(FALSE);

	if(::WaitForSingleObject(m_processInfo.hProcess, 0) == WAIT_OBJECT_0)
		return(TRUE);
	return(FALSE);
}

/*!
	強制終了
*/
void CSubProcess::TerminateSubProcess()
{
	if(SubProcessIsRunning())
	{
		::TerminateProcess(m_processInfo.hProcess, -1);
	}
	m_processCreated = 0;
}

///////////////////////////////////////////////////////////////////////
//	補助関数
///////////////////////////////////////////////////////////////////////
/*!
	パイプ準備
*/
int CSubProcess::SetupPipe(CString idString)
{
	//	STDIN
	if(m_stdIn.CreateOvrlappedPipe(idString + "_STDIN", BUFFER_SIZE))
		return(-1);

	//	STDOUT
	if(m_stdOut.CreateOvrlappedPipe(idString + "_STDOUT", BUFFER_SIZE))
		return(-1);

	//	STDERR
	if(m_stdErr.CreateOvrlappedPipe(idString + "_STDERR", BUFFER_SIZE))
		return(-1);

	return(0);
}

///////////////////////////////////////////////////////////////////////
//	環境変数
///////////////////////////////////////////////////////////////////////
/*!
	環境変数の追加
*/
void CSubProcess::AddSubProcessEnvironment(CString env)
{
	m_subProcessEnvironment.AppendString(env);
	m_subProcessEnvironment.AppendByte('\0');
}

/*!
	環境変数の追加
*/
void CSubProcess::AddSubProcessEnvironmentWorkspace(CWorkspaceAccess workspace)
{
	CStringArray	list;
	workspace.GetAllKey(list);

	//	追加
	for(int i=0;i<list.GetSize();i++)
		AddSubProcessEnvironment(list[i] + "=" + workspace.GetKeyStr(list[i],""));
}

/*!
	クリア
*/
void CSubProcess::ClearSubProcessEnvironment()
{
	m_subProcessEnvironment.Empty();
}


