mirror of
https://github.com/reactos/reactos.git
synced 2026-06-08 08:52:59 +08:00
Temporary fork of candidate base of potententially very useful development tool for ros.
svn path=/trunk/; revision=3955
This commit is contained in:
682
rosapps/devutils/vmingw/process.cpp
Normal file
682
rosapps/devutils/vmingw/process.cpp
Normal file
@@ -0,0 +1,682 @@
|
||||
/********************************************************************
|
||||
* Module: process.cpp. This is part of Visual-MinGW.
|
||||
*
|
||||
* Purpose: Procedures to invoke MinGW compiler.
|
||||
*
|
||||
* Authors: Manu B.
|
||||
*
|
||||
* License: Visual-MinGW is covered by GNU General Public License,
|
||||
* Copyright (C) 2001 Manu B.
|
||||
* See license.htm for more details.
|
||||
*
|
||||
* Note: The following article from MSDN explanes how to handle Callback
|
||||
* procedures :
|
||||
* Calling All Members: Member Functions as Callbacks.
|
||||
* by Dale Rogerson.
|
||||
* Microsoft Developer Network Technology Group.
|
||||
* April 30, 1992.
|
||||
* http://msdn.microsoft.com/archive/default.asp
|
||||
*
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include "process.h"
|
||||
#include "project.h"
|
||||
#include "main.h"
|
||||
#include "rsrc.h"
|
||||
|
||||
extern CCriticalSection CriticalSection;
|
||||
extern CMessageBox MsgBox;
|
||||
char errmsg[128];
|
||||
|
||||
// For winApp.isWinNT and winApp.Report.Append
|
||||
extern CWinApp winApp;
|
||||
|
||||
/********************************************************************
|
||||
* Class: CCommandDlg.
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
CCommandDlg::CCommandDlg(){
|
||||
*cmdLine = '\0';
|
||||
}
|
||||
|
||||
CCommandDlg::~CCommandDlg(){
|
||||
}
|
||||
|
||||
HWND CCommandDlg::Create(void){
|
||||
return CreateParam(&winApp, IDD_COMMAND, 0);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CCommandDlg::CDlgProc(UINT Message, WPARAM wParam, LPARAM lParam){
|
||||
switch(Message){
|
||||
case WM_INITDIALOG:
|
||||
return OnInitDialog((HWND) wParam, lParam);
|
||||
|
||||
case WM_COMMAND:
|
||||
OnCommand(HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
EndDlg(0);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CCommandDlg::OnInitDialog(HWND, LPARAM){
|
||||
hCmdLine = GetItem(IDC_CMDLINE);
|
||||
|
||||
SetItemText(hCmdLine, cmdLine);
|
||||
// Show the dialog.
|
||||
Show();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CCommandDlg::OnCommand(WORD, WORD wID, HWND){
|
||||
switch (wID){
|
||||
case IDOK:
|
||||
GetItemText(hCmdLine, cmdLine, sizeof(cmdLine));
|
||||
//MsgBox.DisplayString(cmdLine);
|
||||
winApp.Process.CommandLine(cmdLine);
|
||||
return TRUE;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDlg(IDCANCEL);
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Class: CTask.
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
CTask::CTask(){
|
||||
*cmdLine = '\0';
|
||||
*szFileName = '\0';
|
||||
creationFlag = 0;
|
||||
outputFlag = 0;
|
||||
}
|
||||
|
||||
CTask::~CTask(){
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Class: CStack.
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
CStack::CStack(){
|
||||
retBuf = NULL;
|
||||
}
|
||||
|
||||
CStack::~CStack(){
|
||||
DestroyList();
|
||||
if (retBuf)
|
||||
delete retBuf;
|
||||
}
|
||||
|
||||
void CStack::DetachCurrent(void){
|
||||
// Empty list ?
|
||||
if (current != NULL){
|
||||
CNode * node = current;
|
||||
|
||||
// Detach node from the list.
|
||||
if (node->next != NULL)
|
||||
node->next->prev = node->prev;
|
||||
if (node->prev != NULL)
|
||||
node->prev->next = node->next;
|
||||
|
||||
// Set current node.
|
||||
if(node->next != NULL)
|
||||
current = node->next;
|
||||
else
|
||||
current = node->prev;
|
||||
|
||||
if (current == NULL){
|
||||
// Now, the list is empty.
|
||||
first = last = NULL;
|
||||
|
||||
}else if (first == node){
|
||||
// Detached node was first.
|
||||
first = current;
|
||||
|
||||
}else if (last == node){
|
||||
// Detached node was last.
|
||||
last = current;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Push/Pop/Flush.
|
||||
********************************************************************/
|
||||
int CStack::Push(CTask * newTask){
|
||||
InsertLast(newTask);
|
||||
return Length();
|
||||
}
|
||||
|
||||
CTask * CStack::Pop(void){
|
||||
// Delete return buffer.
|
||||
if (retBuf){
|
||||
delete retBuf;
|
||||
retBuf = NULL;
|
||||
}
|
||||
|
||||
// Get first node. (FIFO stack)
|
||||
retBuf = (CTask*) First();
|
||||
|
||||
// The Stack is empty ?
|
||||
if (!retBuf)
|
||||
return NULL;
|
||||
|
||||
// Detach current node from the list. Return a pointer to it.
|
||||
DetachCurrent();
|
||||
return retBuf;
|
||||
}
|
||||
|
||||
void CStack::Flush(void){
|
||||
DestroyList();
|
||||
if (retBuf)
|
||||
delete retBuf;
|
||||
retBuf = NULL;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Class: CPipes.
|
||||
*
|
||||
* Purpose: Creates needed pipes, depending on creationFlag.
|
||||
* Like GNU Make does, we use an Handle array for our pipes.
|
||||
* Parent Process Side is stdXXX[0] and Child Process Side is stdXXX[1].
|
||||
*
|
||||
* Ex: PARENT ->[0]IN_PIPE[1]-> CHILD_IO ->[1]OUT_PIPE[0]-> PARENT
|
||||
* ->[1]ERR_PIPE[0]-> PARENT
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
CPipes::CPipes(){
|
||||
hIn[0] = NULL;
|
||||
hIn[1] = NULL;
|
||||
hOut[0] = NULL;
|
||||
hOut[1] = NULL;
|
||||
hErr[0] = NULL;
|
||||
hErr[1] = NULL;
|
||||
}
|
||||
|
||||
CPipes::~CPipes(){
|
||||
}
|
||||
|
||||
bool CPipes::Create(WORD creationFlag, bool winNT){
|
||||
/* Create needed pipes according to creationFlag */
|
||||
/* Parent side of pipes is [0], child side is [1] */
|
||||
HANDLE hDup;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = TRUE;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
|
||||
if (winNT){
|
||||
/* Create a security descriptor for Windows NT */
|
||||
SECURITY_DESCRIPTOR sd;
|
||||
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)){
|
||||
sprintf(errmsg, "vm error: Process.cpp InitializeSecurityDescriptor(winNT) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)){
|
||||
sprintf(errmsg, "vm error: Process.cpp SetSecurityDescriptorDacl(winNT) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
sa.lpSecurityDescriptor = &sd;
|
||||
}
|
||||
|
||||
/* Input pipe */
|
||||
if (!CreatePipe(&hIn[1], &hIn[0], &sa, 0)){
|
||||
sprintf(errmsg, "vm error: Process.cpp CreatePipe(In) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
hIn[0],
|
||||
GetCurrentProcess(),
|
||||
&hDup,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)){
|
||||
sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(In) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
CloseHandle(hIn[0]);
|
||||
hIn[0] = hDup;
|
||||
|
||||
/* Output pipe */
|
||||
if (!CreatePipe(&hOut[0], &hOut[1], &sa, 0)){
|
||||
sprintf(errmsg, "vm error: Process.cpp CreatePipe(Out) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
hOut[0],
|
||||
GetCurrentProcess(),
|
||||
&hDup,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)){
|
||||
sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(Out) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
CloseHandle(hOut[0]);
|
||||
hOut[0] = hDup;
|
||||
|
||||
/* Error pipe */
|
||||
if (!(creationFlag & OUTERR_PIPE) && (creationFlag & ERR_PIPE)){
|
||||
if (!CreatePipe(&hErr[0], &hErr[1], &sa, 0)){
|
||||
sprintf(errmsg, "vm error: Process.cpp CreatePipe(Err) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
hErr[0],
|
||||
GetCurrentProcess(),
|
||||
&hDup,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS)){
|
||||
sprintf(errmsg, "vm error: Process.cpp DuplicateHandle(Err) failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}
|
||||
CloseHandle(hErr[0]);
|
||||
hErr[0] = hDup;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPipes::CloseChildSide(void){
|
||||
return Close(1);
|
||||
}
|
||||
|
||||
bool CPipes::CloseParentSide(void){
|
||||
return Close(0);
|
||||
}
|
||||
|
||||
bool CPipes::Close(int side){
|
||||
|
||||
if (side < 0 || side > 1)
|
||||
return false;
|
||||
|
||||
if (hIn[side]){
|
||||
CloseHandle(hIn[side]);
|
||||
hIn[side] = NULL;
|
||||
}
|
||||
|
||||
if (hOut[side]){
|
||||
CloseHandle(hOut[side]);
|
||||
hOut[side] = NULL;
|
||||
}
|
||||
|
||||
if (hErr[side]){
|
||||
CloseHandle(hErr[side]);
|
||||
hErr[side] = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* Class: CProcess.
|
||||
*
|
||||
* Purpose:
|
||||
*
|
||||
* Revisions:
|
||||
*
|
||||
********************************************************************/
|
||||
CProcess::CProcess(){
|
||||
Running = false;
|
||||
exitCode = 0;
|
||||
|
||||
pi.hProcess = 0;
|
||||
pi.hThread = 0;
|
||||
pi.dwProcessId = 0;
|
||||
pi.dwThreadId = 0;
|
||||
}
|
||||
|
||||
CProcess::~CProcess(){
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Manage Tasks.
|
||||
********************************************************************/
|
||||
bool CProcess::isRunning(void){
|
||||
if (Running){
|
||||
MsgBox.DisplayWarning("A process is already running !");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CTask * CProcess::AddTask(char * cmdLine, WORD creationFlag, WORD outputFlag){
|
||||
CTask * newTask = new CTask;
|
||||
|
||||
strcpy(newTask->cmdLine, cmdLine);
|
||||
newTask->creationFlag = creationFlag;
|
||||
newTask->outputFlag = outputFlag;
|
||||
Push(newTask);
|
||||
return newTask;
|
||||
}
|
||||
|
||||
bool CProcess::CmdCat(char * cmdLine){
|
||||
CTask * task = (CTask*) GetCurrent();
|
||||
if (!task)
|
||||
return false;
|
||||
|
||||
strcat(task->cmdLine, cmdLine);
|
||||
return true;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* RunNext/Run/RunProcess.
|
||||
********************************************************************/
|
||||
void __cdecl call_thread(void * ptr){
|
||||
/* C++ adapter */
|
||||
((CProcess *) ptr)->Run_Thread_Internal();
|
||||
}
|
||||
|
||||
void CProcess::Run(void){
|
||||
// Check if something is already running before creating a thread.
|
||||
if (!Running){
|
||||
// Call Run_Thread_Internal()
|
||||
_beginthread(call_thread, 1024 * 1024, (void *) this);
|
||||
}
|
||||
}
|
||||
|
||||
void CProcess::Run_Thread_Internal(void){
|
||||
exitCode = 0;
|
||||
/* Execute each task */
|
||||
for ( ; ; ){
|
||||
/* If previous task returns an error code, abort */
|
||||
if (exitCode != 0)
|
||||
break;
|
||||
|
||||
// Get one task to execute.
|
||||
currTask = Pop();
|
||||
|
||||
// Nothing to run.
|
||||
if (!currTask)
|
||||
break;
|
||||
|
||||
/* Show command lines ?*/
|
||||
winApp.Report.Append(currTask->cmdLine, LVOUT_NORMAL);
|
||||
|
||||
if (RunProcess(currTask)){
|
||||
winApp.Report.Append("Abort !", LVOUT_NORMAL);
|
||||
exitCode = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Successful ?
|
||||
if (exitCode == 0)
|
||||
winApp.Report.Append("Performed successfully.", LVOUT_NORMAL);
|
||||
|
||||
Flush();
|
||||
Running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool CProcess::RunProcess(CTask * task){
|
||||
if (!task)
|
||||
return false;
|
||||
|
||||
bool usePipes = task->creationFlag;
|
||||
STARTUPINFO si = {sizeof(STARTUPINFO), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0};
|
||||
|
||||
/* PROCESS_INFORMATION */
|
||||
pi.hProcess = 0;
|
||||
pi.hThread = 0;
|
||||
pi.dwProcessId = 0;
|
||||
pi.dwThreadId = 0;
|
||||
|
||||
/* Process creation with pipes */
|
||||
if (usePipes){
|
||||
/* Create needed pipes according to creationFlag */
|
||||
if(!Pipes.Create(task->creationFlag, winApp.isWinNT)){
|
||||
Pipes.CloseChildSide();
|
||||
Pipes.CloseParentSide();
|
||||
return false;
|
||||
}
|
||||
|
||||
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
//si.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
/* Set pipe handles */
|
||||
if (Pipes.hIn[1] != NULL && Pipes.hOut[1] != NULL){
|
||||
si.hStdInput = Pipes.hIn[1];
|
||||
si.hStdOutput = Pipes.hOut[1];
|
||||
if (Pipes.hErr[1] == NULL)
|
||||
si.hStdError = Pipes.hOut[1];
|
||||
else
|
||||
si.hStdError = Pipes.hErr[1];
|
||||
}else{
|
||||
sprintf(errmsg, "vm error: Process.cpp Invalid pipe handle");
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
Pipes.CloseChildSide();
|
||||
Pipes.CloseParentSide();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the child process */
|
||||
Running = CreateProcess(NULL,
|
||||
task->cmdLine,
|
||||
NULL,
|
||||
NULL,
|
||||
usePipes,
|
||||
0,
|
||||
NULL,
|
||||
/*startDir[0] ? startDir :*/ NULL,
|
||||
&si,
|
||||
&pi);
|
||||
|
||||
if (!Running){
|
||||
/* CreateProcess failed. Close handles and return */
|
||||
Pipes.CloseChildSide();
|
||||
Pipes.CloseParentSide();
|
||||
sprintf(errmsg, "vm error: Process.cpp CreateProcess failed (e=%d)", (int)GetLastError());
|
||||
winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
return false;
|
||||
}else{
|
||||
/* Close child process handles */
|
||||
Pipes.CloseChildSide();
|
||||
|
||||
if (!(usePipes & IN_PIPE)){
|
||||
/* Don't use the Input pipe */
|
||||
::CloseHandle(Pipes.hIn[0]);
|
||||
Pipes.hIn[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//sprintf(errmsg, "vm debug: enter io loop");
|
||||
//winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
if (usePipes){
|
||||
/* Initialize buffers */
|
||||
*outBuf = 0;
|
||||
chr = outBuf;
|
||||
bool bResult;
|
||||
for ( ; ; ){
|
||||
Sleep(100L);
|
||||
|
||||
bResult = ReadStdOut(task, Pipes.hOut[0]);
|
||||
if (bResult != NO_ERROR)
|
||||
break;
|
||||
|
||||
::GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||
if (exitCode != STILL_ACTIVE){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//sprintf(errmsg, "vm debug: exit io loop");
|
||||
//winApp.Report.Append(errmsg, LVOUT_ERROR);
|
||||
|
||||
/* The child process is running. Perform I/O until terminated */
|
||||
::WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
/* Process terminated. Get exit code. */
|
||||
::GetExitCodeProcess(pi.hProcess, &exitCode);
|
||||
if (exitCode == NO_ERROR){
|
||||
return NO_ERROR;
|
||||
}
|
||||
/* Close handles */
|
||||
Pipes.CloseParentSide();
|
||||
::CloseHandle(pi.hProcess);
|
||||
if (pi.hThread){
|
||||
::CloseHandle(pi.hThread);
|
||||
pi.hThread = NULL;
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Pipes input/output.
|
||||
********************************************************************/
|
||||
void CProcess::WriteStdIn(HANDLE hPipe, WORD){
|
||||
if (!hPipe)
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void CProcess::ReadStdErr(HANDLE hPipe, WORD){
|
||||
if (!hPipe)
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
long CProcess::ReadStdOut(CTask * task, HANDLE hPipe){
|
||||
if (!task || !hPipe)
|
||||
return ERROR_INVALID_FUNCTION;
|
||||
|
||||
/* Copy each char and output lines while there is something to read */
|
||||
for ( ; ; ){
|
||||
// Copy one char, return if nothing available.
|
||||
if (!ReadOneChar(hPipe, chr))
|
||||
break;
|
||||
|
||||
// Ignore CR.
|
||||
if (*chr == '\r')
|
||||
continue;
|
||||
|
||||
if (*chr != '\n'){
|
||||
chr++;
|
||||
/* @@TODO Overflow
|
||||
if ((chr - outBuf) >= max_len)
|
||||
realloc(buffer);*/
|
||||
// End of line
|
||||
}else if (*chr =='\n'){
|
||||
*chr = '\0';
|
||||
// Output error lines to List View.
|
||||
if (task->outputFlag == STDOUT_FILE_APPEND){
|
||||
WriteFileAppend(task->szFileName, outBuf, (chr - outBuf));
|
||||
}else{
|
||||
OutputLine(task->outputFlag, outBuf, (chr - outBuf));
|
||||
}
|
||||
*outBuf = '\0';
|
||||
chr = outBuf;
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int CProcess::ReadOneChar(HANDLE hPipe, char * chrin){
|
||||
DWORD bytesRead = 0;
|
||||
DWORD bytesAvail = 0;
|
||||
|
||||
if (!PeekNamedPipe(hPipe, chrin, (DWORD)1, &bytesRead, &bytesAvail, NULL))
|
||||
return 0;
|
||||
|
||||
if (bytesAvail == 0)
|
||||
return 0;
|
||||
|
||||
if (!ReadFile(hPipe, chrin, (DWORD)1, &bytesRead, NULL))
|
||||
return 0;
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
bool CProcess::CommandLine(char * cmdLine){
|
||||
if (!Pipes.hIn[0])
|
||||
return false;
|
||||
if (!Running || !currTask || !currTask->creationFlag)
|
||||
return false;
|
||||
int len = strlen(cmdLine);
|
||||
if (len){
|
||||
strcpy(inBuf, cmdLine);
|
||||
char * s = inBuf;
|
||||
s+=len;
|
||||
*s = '\r';
|
||||
s++;
|
||||
*s = '\n';
|
||||
s++;
|
||||
*s = '\0';
|
||||
}
|
||||
DWORD written;
|
||||
|
||||
if (!WriteFile(Pipes.hIn[0], inBuf, strlen(inBuf), &written, 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CProcess::WriteFileAppend(char * fileName, char * line, int /*len*/){
|
||||
if (!*fileName)
|
||||
return false;
|
||||
|
||||
/* Append one line of text to a file */
|
||||
FILE * file = fopen(fileName, "a");
|
||||
if (file){
|
||||
fprintf(file, line);
|
||||
fprintf(file, "\n");
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CProcess::OutputLine(WORD outputFlag, char * line, int /*len*/){
|
||||
/* Output error lines to List View */
|
||||
|
||||
CriticalSection.Enter();
|
||||
winApp.Report.Append(line, outputFlag);
|
||||
CriticalSection.Leave();
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user