0

_open_osfhandle creates a C file descriptor from a windows file handle, and _dup can change an existing fd's underlying file object. When used to redirect stdout to a CreatePipe pipe ReadFile does not capture output written to stdout.

The following code snippet demonstrates the core of what I am attempting. I want to create an anonymous pipe, replacing stdout so that I can read it from the read handle.

The documentation i've been able to find indicates that _open_osfhandle and _dup2 can perform this trickery and Microsofts documentation page for dup2 specifically calls out replacing the fd in stdout as being possible.

Given all that, I am expecting the following code to return immediately from ReadFile with the bytes written by printf as prior calls to _write and fprintf worked as expected.

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
FILE *fp = _fdopen(fd, "w");
setvbuf(fp, NULL, _IONBF, 0);
_dup2(_fileno(fp), _fileno(stdout));
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
//_write(fd, "_write", 6); // works
//fprintf(fp, "fprintf"); // works
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);
Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • in what question ? possible `fprintf` cache data in internal buffer and not call `WriteFile`. until you not flush buffer will be no data in pipe. call `fflush` after fprintf – RbMm Oct 10 '18 at 21:45
  • That was the problem I was having. until I figured out `setvbuf`. The ultimate goal was using _dup2 to replace the fd in stdout. but that still does not work. – Chris Becke Oct 10 '18 at 21:50

1 Answers1

1

Investigation has finally yielded fruit. The file stream opened by _fdopen is buffered by default preventing anything actually being written to the underlying OS pipe handle. setvbuf can be used to turn that off so writes happen immediately.

Performing a dup2 to reset the underlying file bound to stdout's file descriptor resets the buffering, so the following code works. The call to _fdopen is dropped as not needed and the `setvbuf' is performed on stdout.

HANDLE hread;
HANDLE hwrite;
SECURITY_ATTRIBUTES sa = { sizeof(sa),NULL,TRUE };
CreatePipe(&hread, &hwrite, &sa, 0);
int fd = _open_osfhandle(intptr_t(hwrite), _O_TEXT);
_dup2(fd, _fileno(stdout));
setvbuf(stdout, NULL, _IONBF, 0);
TCHAR buffer[64] = { 0 };
DWORD bytesRead;
printf("printf");
ReadFile(hread, buffer, sizeof(buffer), &bytesRead, NULL);
Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • https://stackoverflow.com/questions/45339874/how-to-make-fprintf-writes-immediately – RbMm Oct 10 '18 at 21:57