I have been trying to run a parent process that acts like a cmd input\output console. the purpose of this is for future use, but for now I am trying to isolate this function in order to get things right.
What I am trying to achieve here is an input from user send it to a simple cmd child process, get the output and keep on sending commands, while keeping the process running.The problem is that the cmd process closes right after the first command is executed. I pasted an output of what happens right after the first command,the issue that rises once I try to keep on going and inputting more commands is that the handle is not valid (since the process is terminated).
Help would be much appreciated!
Main code:
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>
#define bzero(p,size) (void) memset((p), 0 , (size))
// Constant
#define BUFSIZE 4096
// Global variables
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
HANDLE g_hInputFile = NULL;
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
PROCESS_INFORMATION CreateChildProcess()
{
// The following should be the child executable, see the next program example
// Change the path accordingly...
WCHAR szCmdline[] = L"cmd.exe";
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
// Set up members of the PROCESS_INFORMATION structure
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
// Set up members of the STARTUPINFO structure
// This structure specifies the STDIN and STDOUT handles for redirection
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process
bSuccess = CreateProcess(NULL, // Use szCmdLine
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NEW_CONSOLE, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
// If an error occurs, exit the application.
if (!bSuccess)
printf("Error creating process, %d\n", GetLastError());
else
{
wprintf(L"\nChild process ID is : %u\n", GetCurrentProcessId());
wprintf(L"Child thread ID is : %u\n", GetCurrentThreadId());
/*
if (CloseHandle(piProcInfo.hProcess) != 0)
wprintf(L"piProcInfo.hProcess handle was closed!\n");
else
printf("Error closing process , %d\n", GetLastError());
if (CloseHandle(piProcInfo.hThread) != 0)
wprintf(L"piProcInfo.hThread handle was closed!\n");
else
printf("Error closing process thread handle, %d\n", GetLastError());
*/
}
return piProcInfo;
}
void WriteToPipe(char * command)
{
DWORD dwWritten;
DWORD dwRead;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
bSuccess = WriteFile(g_hChildStd_IN_Wr, (LPVOID)command , (DWORD)strlen(command), &dwWritten, NULL);
printf("Command: %s\n", command);
if (!bSuccess)
{
wprintf(L"\nWriteFile() - Failed to write to pipe for child\'s STDIN! Error %u\n", GetLastError());
//break;
}
else
wprintf(L"\nWriteFile() - writing to the pipe for the child\'s STDIN...\n");
// Close the pipe handle so the child process stops reading
if (!CloseHandle(g_hChildStd_IN_Wr))
printf("Error closing STDIN handle, %d\n", GetLastError());
else
wprintf(L"Closing the pipe handle...\n");
//Read from pipe
bSuccess = FALSE;
bzero(chBuf, sizeof(chBuf));
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (!CloseHandle(g_hChildStd_OUT_Wr))
printf("Error closing STDOUT handle, %d\n", GetLastError());
for (;;)
{
bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if (!bSuccess || dwRead == 0)
{
wprintf(L"\nReadFile() from child's standard output failed! Error %u\n", GetLastError());
break;
}
bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);
if (!bSuccess)
{
wprintf(L"\nWriteFile() to parent's standard output failed! Error %u\n", GetLastError());
break;
}
}
}
int main()
{
PROCESS_INFORMATION pi;
char filename[100];
ZeroMemory(&filename, sizeof(filename));
strcpy(filename, "commands.txt");
SECURITY_ATTRIBUTES saAttr;
wprintf(L"Parent process ID %u\n", GetCurrentProcessId());
// Set the bInheritHandle flag so pipe handles are inherited
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
printf("Create pipe for STDOUT failed,%d\n", GetLastError());
else
wprintf(L"CreatePipe() - pipe for child process\'s STDOUT pipe was created!\n");
// Ensure the read handle to the pipe for STDOUT is not inherited
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
printf("Create handle for STDOUT failed,%d\n", GetLastError());
else
wprintf(L"SetHandleInformation() - pipe STDOUT read handle is not inherited!\n");
// Create a pipe for the child process's STDIN
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
printf("Create pipe for STDIN failed,%d\n", GetLastError());
else
wprintf(L"CreatePipe() - pipe for child process\'s STDIN was created!\n");
// Ensure the write handle to the pipe for STDIN is not inherited
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
printf("Error getting handle on STDIN,%d\n", GetLastError());
else
wprintf(L"Stdin SetHandleInformation() - pipe STDIN read handle is not inherited!\n");
// Create the child process
wprintf(L"Creating the child process...\n");
pi = CreateChildProcess();
char chr[1000];
for (;;)
{
bzero(chr, sizeof(chr));
printf("Enter a character: ");
scanf("%s", chr);
strcat(chr, "\n");
if(strncmp(chr,"exit",4) == 0)
break;
WriteToPipe(chr);
}
if (CloseHandle(pi.hProcess) != 0)
wprintf(L"piProcInfo.hProcess handle was closed!\n");
else
printf("Error closing process , %d\n", GetLastError());
if (CloseHandle(pi.hThread) != 0)
wprintf(L"piProcInfo.hThread handle was closed!\n");
else
printf("Error closing process thread handle, %d\n", GetLastError());
printf("End of parent execution.\n");
return 0;
}
Output:
Parent process ID 10580
CreatePipe() - pipe for child process's STDOUT pipe was created!
SetHandleInformation() - pipe STDOUT read handle is not inherited!
CreatePipe() - pipe for child process's STDIN was created!
Stdin SetHandleInformation() - pipe STDIN read handle is not inherited!
Creating the child process...
Child process ID is : 10580
Child thread ID is : 1880
Enter a character: whoami
Command: whoami
WriteFile() - writing to the pipe for the child's STDIN...
Closing the pipe handle...
Microsoft Windows [Version 10.0.18363.836]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\Users\Administrator\Desktop>whoami
Administrator
C:\Users\Administrator\Desktop>Clink v0.4.9 [git:2fd2c2] Copyright (c) 2012-2016 Martin Ridgers
http://mridgers.github.io/clink
ReadFile() from child's standard output failed! Error 109
Enter a character: