Win32 changing to binary mode child's Stdout (pipe)
Hello to this great community,
I have problems with the automatic conversion of ('\n') 0x0A to ('\n\r')
0x0D 0x0A when using a pipe to redirect child's stdout to a file, the
child's output are bytes and not text.
First, I have used these examples MSDN-Creating a Child Process with
Redirected Input and Output and http://support.microsoft.com/kb/190351),
and now I have this basic application, it creates a pipe and redirect the
child's STDOUT to a binary file. All this in a Win32 Console Application
in Visual C++ 6.0 (yes it is old but is a requirement).
#define BUFSIZE 256
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
int _tmain(int argc, TCHAR *argv[])
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
ErrorExit(TEXT("StdoutRd CreatePipe"));
if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
ErrorExit(TEXT("Stdout SetHandleInformation"));
CreateChildProcess();
if (!CloseHandle(g_hChildStd_OUT_Wr))
ErrorExit("CloseHandle");
ReadFromPipe();
if (!CloseHandle(g_hChildStd_OUT_Rd))
ErrorExit("CloseHandle");
return 0;
}
void CreateChildProcess()
{
TCHAR szCmdline[]=TEXT("child.exe");
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bSuccess = FALSE;
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
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 ( ! bSuccess )
ErrorExit(TEXT("CreateProcess"));
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
}
}
void ReadFromPipe(void)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD nTotalBytesRead = 0;
fstream filePk;
filePk.open("result.out", ios::out | ios::trunc | ios::binary);
for (;;)
{
bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead,
NULL);
if( ! bSuccess || dwRead == 0 ) {
if (GetLastError() == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
else
ErrorExit("ReadFile"); // Something bad happened.
}
filePk.write(chBuf, dwRead);
nTotalBytesRead += dwRead;
}
filePk.close();
char ibuff[24];
sprintf(ibuff,"%d bytes." , (int)nTotalBytesRead);
::MessageBox(NULL, ibuff, "", 0);
}
And in this dummy child.cpp you'll notice that if I set the STDOUT to
binary mode everything works just fine (I get just 0x0A 0x0A!), but my
real child is an EXE and I don't have access to that code.
int main(int argc, char* argv[])
{
_setmode( _fileno( stdout ), _O_BINARY );
printf("\n");
unsigned char buffer[] = {'\n'};
fwrite(buffer, sizeof(unsigned char), sizeof(buffer), stdout);
return 0;
}
So, after searching for about 2 days and considering that I have a basic
C++ knowledge I ask: Is there a Way that I could do _setmode to the childs
stdout from the parent, considering that I don't have access to the
child's code.
As a solution, I am seriously considering finding every '0x0D' '0x0A' and
replacing it with '0x0A'. I am really going crazy with this problem... So
if someone could help me I will be very grateful.
Related Question: Win32 Stream Handles - Changing To Binary Mode but he
has access to the child's code!
No comments:
Post a Comment