Created
          March 2, 2012 00:38 
        
      - 
      
- 
        Save ryangraham/1954307 to your computer and use it in GitHub Desktop. 
    named pipe inheritance
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | 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