Skip to content

Instantly share code, notes, and snippets.

@ryangraham
Created March 2, 2012 00:38
Show Gist options
  • Save ryangraham/1954307 to your computer and use it in GitHub Desktop.
Save ryangraham/1954307 to your computer and use it in GitHub Desktop.
named pipe inheritance
class child
{
public:
child(char *cmd)
{
// Sec attr for the named pipe
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa,sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
// Name the pipe. Lets randomize this later. No rush.
std::string pipe_name = "\\\\.\\pipe\\";
char pid[100]; // What size should this really be?
sprintf_s(pid,"%u",GetCurrentProcessId());
// Thats right. sprintf AND append. Zero fucks given.
pipe_name.append(pid);
printf("%s",pipe_name.c_str());
// Read handle for the parent process
_read = CreateNamedPipeA(pipe_name.c_str(),PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED,0,1,8192,8192,0,&sa);
if(_read == INVALID_HANDLE_VALUE) {
throw std::runtime_error("failed to create named pipe");
}
// Write handle for the child process
// Zero out and re-use security attributes with inherit flag enabled
ZeroMemory(&sa,sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
_write = CreateFileA(pipe_name.c_str(),GENERIC_WRITE,0,&sa,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if(_write == INVALID_HANDLE_VALUE) {
throw std::runtime_error("failed to create write handle");
}
// Event handle for ConnectNamedPipe
ZeroMemory(&_overlapped,sizeof(_overlapped));
_overlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(!_overlapped.hEvent) {
throw std::runtime_error("failed to create event handle");
}
// Connect to the pipe
BOOL success = ConnectNamedPipe(_read,&_overlapped);
if(!success) {
if(GetLastError() == ERROR_IO_PENDING) {
if(WaitForSingleObject(_overlapped.hEvent,INFINITE) == WAIT_FAILED) {
CloseHandle(_overlapped.hEvent);
throw std::runtime_error("failed WSFO for ConnectNamedPipe");
}
}
else if(GetLastError() != ERROR_PIPE_CONNECTED) {
CloseHandle(_overlapped.hEvent);
throw std::runtime_error("failed to connect to named pipe");
}
}
CloseHandle(_overlapped.hEvent);
ZeroMemory(_buf,8192);
// Spawn the new process
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
// Not passing stdin handle. Feel free to add it if you need it.
si.hStdError = _write;
si.hStdOutput = _write;
si.dwFlags = STARTF_USESTDHANDLES;
success = CreateProcess(NULL,cmd,NULL,NULL,TRUE,0,0,NULL,&si,&pi);
if(!success) {
throw std::runtime_error("failed to create child process");
}
_handle = pi.hProcess;
}
HANDLE &read()
{
return _read;
}
OVERLAPPED &overlapped()
{
return _overlapped;
}
private:
char _buf[8192]; // this buffer is only used by test functions. make your own outside the object.
HANDLE _read;
HANDLE _write;
OVERLAPPED _overlapped;
HANDLE _handle;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment