urbackup_backend/piped_process/piped_process_win.cpp
2011-02-06 18:53:57 +01:00

161 lines
4.4 KiB
C++

/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "../vld.h"
#include "piped_process.h"
#include "../Interface/Server.h"
#include "../stringtools.h"
#define BUFSIZE 1000
CPipedProcess::CPipedProcess(std::string cmd)
{
is_open=true;
stop_thread=false;
thread_stopped=false;
output=Server->createMemoryPipe();
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
Server->Log("Error creating PIPE g_hChildStd_OUT_Rd", LL_ERROR);
if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
Server->Log("Error creating SetHandleInformation g_hChildStd_OUT_Rd", LL_ERROR);
if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
Server->Log("Error creating PIPE g_hChildStd_IN_Rd", LL_ERROR);
if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
Server->Log("Error creating SetHandleInformation g_hChildStd_IN_Wr", LL_ERROR);
TCHAR szCmdline[]=TEXT("child");
STARTUPINFOA siStartInfo;
BOOL bSuccess = FALSE;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFOA) );
siStartInfo.cb = sizeof(STARTUPINFOA);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
Server->Log("Creating process", LL_DEBUG);
bSuccess = CreateProcessA(NULL, (char*)cmd.c_str(), &saAttr, NULL,TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
if( !bSuccess )
{
Server->Log("Error Creating Process", LL_ERROR);
is_open=false;
return;
}
Server->Log("Created process", LL_DEBUG);
}
CPipedProcess::~CPipedProcess()
{
Server->Log("Closing..", LL_DEBUG);
stop_thread=true;
CloseHandle(g_hChildStd_OUT_Rd);
CloseHandle(g_hChildStd_IN_Rd);
CloseHandle(g_hChildStd_OUT_Wr);
CloseHandle(g_hChildStd_IN_Wr);
BOOL rc=TerminateProcess(piProcInfo.hProcess, 0);
if(!rc )
{
Server->Log("Error Terminating Process "+nconvert((int)GetLastError()), LL_ERROR);
}
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
std::string tmp;
while(thread_stopped==false)
output->isReadable(-1);
Server->destroy(output);
Server->Log("Closing... CPipedProcess", LL_DEBUG);
}
bool CPipedProcess::Write(const std::string &str)
{
BOOL bSuccess = FALSE;
DWORD dwWritten;
bSuccess = WriteFile(g_hChildStd_IN_Wr, str.c_str(), (DWORD)str.size(), &dwWritten, NULL);
if( dwWritten!=str.size() )
{
is_open=false;
stop_thread=true;
Server->Log("Not enough buffer space", LL_ERROR);
return false;
}
if ( ! bSuccess ) return false;
else
{
unsigned long ExitCode=0;
if(!GetExitCodeProcess(piProcInfo.hProcess , &ExitCode) || ExitCode!= STILL_ACTIVE)
{
is_open=false;
stop_thread=true;
return false;
}
return true;
}
}
std::string CPipedProcess::Read(void)
{
if(g_hChildStd_OUT_Wr!=NULL)
{
CloseHandle(g_hChildStd_OUT_Wr);
g_hChildStd_OUT_Wr=NULL;
}
DWORD dwRead;
BOOL bSuccess = FALSE;
CHAR chBuf[BUFSIZE];
bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if( !bSuccess )
{
is_open=false;
Server->Log("Error reading STD_OUT", LL_ERROR );
return "";
}
std::string ret;
ret.resize(dwRead);
memcpy((void*)ret.c_str(), chBuf, dwRead);
if(ret.size()==0)
return Read();
return ret;
}