C, Create Processes and wait - c

Hi I'm creating more than one process with the CreateProcess
and I need to wait all of them to finish, to analyze the results.
And I cant WaitForSingleObject because I need all of the processes running at the same time.
Since each process has a handle at Process_Information (hProcess)
I tought it was ok to use WaitForMultipleObjects,but the parent process ends without waiting for the child.
Is it ok to use WaitForMultipleObjects or there is a better way?
This is how I'm creating the processes:
#define MAX_PROCESS 3
STARTUPINFO si[MAX_PROCESS];
PROCESS_INFORMATION pi[MAX_PROCESS];
WIN32_FIND_DATA fileData;
HANDLE find;
int j=0, t=0;
ZeroMemory(&si, sizeof(si));
for (t = 0; t < MAX_PROCESS; t++)
si[t].cb = sizeof(si[0]);
ZeroMemory(&pi, sizeof(pi));
while (FindNextFile(find, &fileData) != 0)
{
// Start the child process.
if (!CreateProcess(_T("C:\\Users\\Kumppler\\Documents\\Visual Studio 2010\\Projects\ \teste3\\Debug\\teste3.exe"), // No module name (use command line)
aux2, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si[j], // Pointer to STARTUPINFO structure
&pi[j]) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
j++;
//find next file related
}
FindClose(find);
WaitForMultipleObjects(MAX_PROCESS, &pi[j].hProcess, FALSE, INFINITE);
//wait and analyze results
Btw I'm trying not to use threads.

WaitForMultipleObjects expects array of handles:
HANDLE hanldes[MAX_PROCESS];
for (int i = 0; i < MAX_PROCESS; ++i)
{
handles[i] = pi[i].hProcess;
}
WaitForMultipleObjects(MAX_PROCESS, handles, TRUE, INFINITE);
Also you should know that maximum array size of handles for WaitForMultipleObjects is limited to MAXIMUM_WAIT_OBJECTS (which is 64).

If you want to wait for all the HANDLEs set 'bWaitAll' (the third parameter) to 'TRUE'.

Related

How to write data into global variables from callback function?

According to windows API docs we can use global variable to pass data from creating thread to the new thread and I am assuming the opposite is also possible
Data can also be passed from the creating thread to the new thread using global variables.
Here is a data structure and a callback function, ptr is a pointer to heap allocated memory in main
typedef struct Output
{
char *ptr;
DWORD len;
}Output, *POutput;
Output out; // global variable
DWORD grab_output(LPVOID args)
{
DWORD dread;
BOOL success = FALSE;
while (1)
{
success = ReadFile(g_hChildStd_OUT_Rd,out.ptr, 1024, &dread, NULL);
if (!success || dread == 0 ) break;
out.ptr = realloc(out.ptr, out.len+1024);
out.len += dread;
}
}
int run()
{
BOOL res;
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
DWORD dwThreadIdArray[1];
DWORD n_size;
memset(&si, 0 ,sizeof(si));
memset(&pi, 0, sizeof(pi));
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0))
return GetLastError();
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
return GetLastError();
si.cb = sizeof(STARTUPINFOA);
si.hStdError = g_hChildStd_OUT_Wr;
si.hStdOutput = g_hChildStd_OUT_Wr;
si.dwFlags |= STARTF_USESTDHANDLES;
if(!CreateProcess(NULL,
"C:\\Windows\\System32\\cmd.exe /c dir",
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
))
{
}
else
{
handle = CreateThread(0, 0, grab_output, NULL, 0, NULL);
}
return 0;
}
int main()
{
out.ptr = malloc(1024);
out.len = 0;
run();
printf("%s\n", out.ptr);
}
when running the code out.ptr returns garbage values
gcc example.c && ./a.exe
└e╔┐═☺
for the sake of this question assume that I will be running a single thread at any given time
The reason this prints garbage values is you assumed for no clear reason that the thread finishes before you accessed the global variable.
There's too many unchecked fault points. Right now, check every function that can error for an error return and produce output in that case, and also set a flag in another global variable. Really, you shouldn't have to, but better to much than not enough. Then close the process and thread handles you aren't using.
Now we should be able to discuss synchronization.
It looks like you want to grab all of the output at once. Thus WaitForSingleObject() on your own thread handle. To produce output incrementally, you need to track input highwater and output highwater and output only the characters in between with putc().
Don't forget to null-terminate your string either, or printf() won't be happy.
You need some means to communicate between the thread and main() that the value has been updated. It is very likely that main() will execute the printf before the thread is done with ReadFile. Also you have a race condition where ReadFile might be writing to the buffer while printf is reading it.
Use a mutex, semaphore, event or similar to communcate between threads, then use WaitForSingleObject etc where appropriate. It's also not advisable to have a busy-loop inside the thread or to exit the creator thread main() while there are threads still running.
EDIT:
Note that you must also return 0 from the thread or your program will go haywire, if you somehow managed to get it compiling in the first place despite the missing return.

Capture stdout of child process with overlapped I/O

I want to spawn a child process and capture its stdout (and stderr) using overlapped I/O without using threads. Here's my current knowledge of all the stars that must align in order to achieve that, i.e. here's the recipe:
Set an inheritable handle as the stdout (and stderr) of the process when creating the process (set hStdOutput and hStdError fields of STARTUPINFO).
Tell the process to inherit any inheritable handles from its parent so that it will inherit said stdout handle (arg bInheritHandles of CreateProcess()).
The handle itself must be the writing end of an anonymous pipe. I will then capture the process' stdout by reading from the reading end of that pipe.
The pipe must be overlapped-I/O-enabled.
Since anonymous pipes don't support overlapped I/O, I must emulate them using a named pipe (which I create with FILE_FLAG_OVERLAPPED). This pipe will serve as the writing end of the anonymous pipe. I then open this pipe using CreateFile to get a handle to the reading end (this is more/less how anonymous pipes are implemented in Windows also).
The reading end of the pipe must not be inherited by the child process, so I am careful to not make it inheritable. (does anyone have a good explanation for why that is?)
After the process is created and the writing handle is thus inherited, I close said handle in the parent process. This is so that (thanks #o11c in the comments) the writing end of the pipe is left with only one handle open to it (the handle that the child holds), so that when the child exists, the pipe is closed and reading from it fails with a broken pipe error (otherwise we would never know when to stop reading).
Now that everything is set up I can start reading from the pipe: I create a completion port, perform an overlapped ReadFile() and then check the completion status.
And here's the problem: GetQueuedCompletionStatus() hangs until timeout and then returns WAIT_TIMEOUT instead of returning immediately with either some data or with ERROR_IO_PENDING so I can check again.
Below is the minimum amount of C code that reproduces the problem. Any help appreciated. Thanks!
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
PROCESS_INFORMATION pi;
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
OVERLAPPED o;
#define sz 1024
unsigned char buf[sz];
char* pipe_name = "\\\\.\\pipe\\t1";
int main(int argc, char **argv) {
sa.nLength = sizeof(sa);
sa.bInheritHandle = 1;
HANDLE stdout_r = CreateNamedPipe(pipe_name,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
0,
1,
8192, 8192,
120 * 1000,
0
);
assert(stdout_r != INVALID_HANDLE_VALUE);
HANDLE stdout_w = CreateFile(pipe_name,
GENERIC_WRITE,
0,
&sa,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0
);
assert(stdout_w != INVALID_HANDLE_VALUE);
si.hStdOutput = stdout_w;
si.hStdError = stdout_w;
si.dwFlags = STARTF_USESTDHANDLES;
assert(CreateProcess(0, "dir", 0, 0, 1, 0, 0, 0, &si, &pi) != 0);
assert(CloseHandle(stdout_w) != 0);
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
assert(iocp != INVALID_HANDLE_VALUE);
if (ReadFile(stdout_r, buf, sz, 0, &o) == 0) {
if (GetLastError() == ERROR_IO_PENDING) {
DWORD n;
ULONG_PTR compkey;
LPOVERLAPPED po;
int ret = GetQueuedCompletionStatus(iocp, &n, &compkey, &po, 1000);
if (!ret) {
assert(GetLastError() != WAIT_TIMEOUT);
}
}
}
return 0;
}
NOTE: I built/tested this with mingw but VC should work too (in ANSI mode).

How do I process the output of "dir"?

I have written a program that implements a tiny shell to process commands from the user.
If the entered command is recognised as internal command, my program executes this command.
These commands are implemented as internal functions and their output is being processed by another internal function that is able to send the text to the console and / or to file for logging purposes.
If the entered command is not recognised, I try to execute the entered command as part of the windows command shell, e.g. : cmd dir would execute the dir command and the output gets printed on the console. This is done via CreateProcess. Until now I did not specify the members hStdError, hStdOutput and hStdInput of the STARTUPINFO parameter.
I tried to implement and adapt the example of Creating a Child Process with Redirected Input and Output.
I did not use their implementation of the child process, but tried to get the output of the dir command into my application:
#include "pch.h"
#include <windows.h>
#define BUFSIZE 512
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{
TCHAR szCmdline[] = TEXT("cmd /c dir q:\\Sicherung\\Bilder /s");
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,
szCmdline, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // 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)
return; // ErrorExit(("CreateProcess"));
else
{
// Close handles to the child process and its primary thread.
// Some applications might keep these handles to monitor the status
// of the child process, for example.
//CloseHandle(piProcInfo.hProcess);
//CloseHandle(piProcInfo.hThread);
}
}
void ReadFromPipe(void)
// Read output from the child process's pipe for STDOUT
// and write to the parent process's pipe for STDOUT.
// Stop when there is no more data.
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
for (;;)
{
DWORD objectstat = WAIT_TIMEOUT;
//do
//{
// objectstat = WaitForSingleObject(piProcInfo.hProcess, 0);
//} while (objectstat != WAIT_OBJECT_0);
memset(&chBuf[0], 0x00, BUFSIZE);
bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if (!bSuccess)
break;
bSuccess = WriteFile(hParentStdOut, chBuf,
dwRead, &dwWritten, NULL);
if (!bSuccess)
break;
if (dwRead == 0)
break;
}
}
int main()
{
SECURITY_ATTRIBUTES saAttr;
printf("\n->Start of parent execution.\n");
// 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))
return -1;// ErrorExit("StdoutRd CreatePipe");
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
return -2;// ErrorExit(("Stdout SetHandleInformation"));
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
return -3 ;// ErrorExit(("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
return -4;// ErrorExit(("Stdin SetHandleInformation"));
// Create the child process.
CreateChildProcess();
ReadFromPipe();
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return 0;
}
I know, that the problem has to be with ReadFile. I can not determine when all output of the dir command has been processed. Checking dwRead for 0 or for BUFSIZE does not work. dwReadnever becomes 0, and it can happen that it is less than BUFSIZE, because the dir command is not fast enough.
So, how am i supposed to end processing of the pipe data?
Ok, after i searched some different terms in google, I came up with this link to stackoverflow ;) :
How to read output from cmd.exe using CreateProcess() and CreatePipe()
Ian Boyd wrote there :
Once you've launched your child process: be sure to close those ends of the pipe you no longer need.
result = CreateProcess(...);
//CreateProcess demands that we close these two populated handles when we're done with them. We're done with them.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
/*
We've given the console app the writable end of the pipe during CreateProcess; we don't need it anymore.
We do keep the handle for the *readable* end of the pipe; as we still need to read from it.
The other reason to close the writable-end handle now is so that there's only one out-standing reference to the writeable end: held by the console app.
When the app closes, it will close the pipe, and ReadFile will return code 109 (The pipe has been ended).
That's how we'll know the console app is done. (no need to wait on process handles with buggy infinite waits)
*/
CloseHandle(g_hChildStd_OUT_Wr);
g_hChildStd_OUT_Wr = 0;
CloseHandle(g_hChildStd_IN_Rd);
g_hChildStd_OUT_Wr = 0;
The common problem with most solutions is that people try to wait on a process handle. There are many problems with this; the main one being that if you wait for the child the terminate, the child will never be able to terminate.
After closing the unneeded handles ReadFile works as expected.

Passing an anonymous PIPE HANDLE to Child Process

I am wanting to pass an anonymous Pipe HANDLE to a Child Process. This answer seems to explain it well for C++, however I am wanting to do this in C.
Do I convert the handle into an integer? Or do I pass the memory address of the HANDLE to the child process, and then make another HANDLE pointing to that?
For example:
Parent:
BOOL bCreatePipe, bReadFile;
HANDLE hRead = NULL;
HANDLE hWrite = NULL;
SECURITY_ATTRIBUTES lpPipeAttributes;
lpPipeAttributes.nLength = sizeof(lpPipeAttributes);
lpPipeAttributes.lpSecurityDescriptor = NULL;
lpPipeAttributes.bInheritHandle = TRUE;
// Create pipe file descriptors for parent and child
bCreatePipe = CreatePipe(&hRead, &hWrite, &lpPipeAttributes, (DWORD)BUFFER_SIZE);
if (bCreatePipe == FALSE) {
printf("[-]Error creating IPC pipe : %d", GetLastError());
exit(-1);
}
// Create command line arguments for child process
snprintf(child_cmd, CMD_LINE_SIZE, "%d", &hWrite);
// Create child process to handle request
if ( !CreateProcess(
"C:\\Users\\Child.exe", // No module name (use command line)
child_cmd, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to TRUE (for pipe)
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("[-]CreateProcess failed : %d\n", GetLastError());
exit(-1);
}
Child:
// Set variables to arguments passed by parent
HANDLE hWrite = atoi(argv[0]);
yes, this is ok pass HANDLE by value. in practice currently your code will be work ok. however need remember that HANDLE is 64-bit size on 64-bit system - so not fit in int which is 32-bit size (now user mode handle values in practice fit to 32bit). so need use say %I64x format to encode handle value and _atoi64 or _wcstoi64 to decode.
for example in parent:
WCHAR child_cmd[32];
swprintf(child_cmd, L"<%I64x>", (ULONG64)(ULONG_PTR)hWrite);
and in child:
HANDLE hWrite = 0;
if (PWSTR sz = wcschr(GetCommandLineW(), '<'))
{
hWrite = (HANDLE)(ULONG_PTR)_wcstoi64(sz + 1, &sz, 16);
if (*sz != '>')
{
hWrite = 0;
}
}
as separate note - use CreatePipe not the best choice - this api very bad design, say one handle only for write, another only for read, can not select asynchronous I/O, can not make one handle inherit and another not (as need in this case) - better use CreateNamedPipeW + CreateFileW for create pipe pair. or this way if you want no name on pipe (work from win7)

Problem in CreateProcess function!

I have my main application ,from my main application I will be calling another
module(third party) to perform a small operation in my main application,when I call that module..it processes for a particular time say 5 sec.while its proccessing it shows the process in the commmand window with some information..now my main application waits until the called module finishes its process.Now my Question is..how to do I hide this command window without disturbing its process..I tried to use the createprocess but it seems to not work...
for example: my main application is the Parent process and the called application is child process..Parent process should be independent of the child process..check my example below
int main()
{
execl("c:\\users\\rakesh\\Desktop\\calledapplication.exe","c:\\users\\rakesh\\Desktop \\calledapplication.exe",0);
}
code in calledapplication
int main
{
printf("Rakesh");
}
now considering the above if you run the first program...output would appear in the same
command window(It shouldnt be like that)...I want the main application to create the process but it should not be affected by child process.
Pass CREATE_NO_WINDOW in the dwCreationFlags parameter of CreateProcess.
You talked about a "command window", so I presume that the child is a console application.
In that case you can create the process in a separate conole and optionally force the new console to be iconified or hidden.
The following code launch a child process that interprets a batch file (mytest.bat).
I hope it can help. Regards.
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL rv = FALSE;
WCHAR cmdline[] = TEXT("cmd.exe /c mytest.bat");
memset(&si,0,sizeof(si));
si.cb = sizeof(si);
// Add this if you want to hide or minimize the console
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; //or SW_MINIMIZE
///////////////////////////////////////////////////////
memset(&pi,0,sizeof(pi));
rv = CreateProcess(NULL, cmdline, NULL, NULL,
FALSE, CREATE_NEW_CONSOLE,
NULL, NULL, &si, &pi);
if (rv) {
WaitForSingleObject(pi.hProcess, INFINITE);
printf("Done! :)\n");
}
else {
printf("Failed :(\n");
}
return rv ? 0 : 1;
}
It sounds like you want the child process's output to show up in a separate window. If so, you want to call CreateProcess and pass it the CREATE_NEW_CONSOLE flag, rather than using exec*.

Resources