private void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
{
Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributesParent = new Interop.Kernel32.SECURITY_ATTRIBUTES();
securityAttributesParent.bInheritHandle = Interop.BOOL.TRUE;
SafeFileHandle hTmp = null;
try
{
if (parentInputs)
{
CreatePipeWithSecurityAttributes(out childHandle, out hTmp, ref securityAttributesParent, 0);
}
else
{
CreatePipeWithSecurityAttributes(out hTmp,
out childHandle,
ref securityAttributesParent,
0);
}
// Duplicate the parent handle to be non-inheritable so that the child process
// doesn't have access. This is done for correctness sake, exact reason is unclear.
// One potential theory is that child process can do something brain dead like
// closing the parent end of the pipe and there by getting into a blocking situation
// as parent will not be draining the pipe at the other end anymore.
SafeProcessHandle currentProcHandle = Interop.Kernel32.GetCurrentProcess();
if (!Interop.Kernel32.DuplicateHandle(currentProcHandle,
hTmp,
currentProcHandle,
out parentHandle,
0,
false,
Interop.Kernel32.HandleOptions.DUPLICATE_SAME_ACCESS))
{
throw new Win32Exception();
}
}
finally
{
if (hTmp != null && !hTmp.IsInvalid)
{
hTmp.Dispose();
}
}
}