I've met with a console redirecting problem in Win9x. (does not happen on NT)
see code below



ConsolePipe proc uses esi edi lpCmdLine:DWORD,lpCurDir:DWORD,lpOutBuf:DWORD,BufSize:DWORD
LOCAL startupinfo:STARTUPINFO
LOCAL pinfo:PROCESS_INFORMATION
LOCAL buffer[pipebufsize+1]:byte
LOCAL bytesGo:DWORD
LOCAL bytesTotal:DWORD
LOCAL sat:SECURITY_ATTRIBUTES

mov bytesTotal,0
mov sat.nLength,sizeof SECURITY_ATTRIBUTES
mov sat.lpSecurityDescriptor,NULL
mov sat.bInheritHandle,TRUE
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL
.if eax==NULL
invoke MessageBox,hInstance,addr CreatePipeError,lpCmdLine,MB_ICONERROR+MB_OK
.else
mov startupinfo.cb,sizeof STARTUPINFO
invoke GetStartupInfo,addr startupinfo
mov eax,hWrite
mov startupinfo.hStdOutput,eax
mov startupinfo.hStdError,eax
mov startupinfo.dwFlags,STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES
mov startupinfo.wShowWindow,SW_HIDE
invoke CreateProcess,NULL,lpCmdLine,NULL,NULL,TRUE,NULL,NULL,lpCurDir,addr startupinfo,addr pinfo
.if eax==NULL
invoke MessageBox,NULL,addr CreateProcessError,lpCmdLine,MB_ICONERROR+MB_OK
.else
invoke CloseHandle,hWrite
.while TRUE
invoke RtlZeroMemory,addr buffer,pipebufsize+1
invoke ReadFile,hRead,addr buffer,pipebufsize,addr bytesGo,NULL
.if eax==NULL
mov eax,1
.break
.else
mov eax,bytesTotal
add eax,bytesGo
.if eax>BufSize
.break
.else
mov bytesTotal,eax
.endif
invoke lstrcat,lpOutBuf,addr buffer
.endif
.endw
.endif
invoke CloseHandle,hRead
.endif
mov eax,bytesTotal
ret
ConsolePipe endp


The problem is ReadFile blocks after the program has finished. How to solve it?
Posted on 2003-10-13 11:59:40 by optimus
Hi, optimus.

Perhaps you could use asynchronous I/O calls, and also check for program termination. That way your program won't get locked by a pipe that never gets written to.
Posted on 2003-10-14 18:10:46 by QvasiModo
can u give me some details on that?
Posted on 2003-10-15 01:49:32 by optimus
Mhm... my mistake, only CreateFile uses overlapped calls. I couldn't find a way to do the same with pipes. :(
Perhaps you could instead create a temp file, redirect console I/O of the target process into that file, and wait for process termination. Then just read the temp file.
Also I think there was some info in the FAQ...

EDIT: Indeed,
http://www.asmcommunity.net/board/index.php?topic=23
Posted on 2003-10-17 13:15:56 by QvasiModo
Now I use 2 threads to solve the problem.



ConsolePipe proc uses esi edi lpCmdLine:DWORD,lpCurDir:DWORD,lpOutBuf:DWORD,BufSize:DWORD
LOCAL startupinfo:STARTUPINFO
LOCAL pinfo:PROCESS_INFORMATION
LOCAL sat:SECURITY_ATTRIBUTES
LOCAL hThread:DWORD
LOCAL pHnd:DWORD

mov sat.nLength,sizeof SECURITY_ATTRIBUTES
mov sat.lpSecurityDescriptor,NULL
mov sat.bInheritHandle,TRUE
invoke CreatePipe,addr hRead,addr hWrite,addr sat,NULL
.if eax==NULL
invoke MessageBox,hInstance,addr CreatePipeError,lpCmdLine,MB_ICONERROR+MB_OK
.else
mov startupinfo.cb,sizeof STARTUPINFO
invoke GetStartupInfo,addr startupinfo
mov eax,hWrite
mov startupinfo.hStdOutput,eax
mov startupinfo.hStdError,eax
mov startupinfo.dwFlags,STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES
mov startupinfo.wShowWindow,SW_HIDE
invoke CreateProcess,NULL,lpCmdLine,NULL,NULL,TRUE,NULL,NULL,lpCurDir,addr startupinfo,addr pinfo
.if eax==NULL
invoke MessageBox,NULL,addr CreateProcessError,lpCmdLine,MB_ICONERROR+MB_OK
.else
invoke CloseHandle,hWrite
invoke RtlZeroMemory,lpOutBuf,BufSize
invoke OpenProcess,SYNCHRONIZE,0,pinfo.dwProcessId
.if eax==0
invoke MessageBox,NULL,addr CreateProcessError,lpCmdLine,MB_ICONERROR+MB_OK
.else
mov pHnd,eax
mov eax,BufSize
mov BufferSize,eax
invoke CreateThread,0,0,addr ReadPipeThread,lpOutBuf,0,addr hThread
mov hThread,eax
invoke WaitForSingleObject,pHnd,10000
invoke CloseHandle,pHnd
invoke TerminateThread,hThread,0
.endif
.endif
invoke CloseHandle,hRead
.endif
mov eax,bytesTotal
ret
ConsolePipe endp




ReadPipeThread proc lpOutBuf:DWORD
LOCAL buffer[pipebufsize+1]:byte
LOCAL bytesGo:DWORD

mov bytesTotal,0

.while TRUE
invoke RtlZeroMemory,addr buffer,pipebufsize+1
invoke ReadFile,hRead,addr buffer,pipebufsize,addr bytesGo,NULL
.if eax==NULL
mov eax,1
ret
.else
mov eax,bytesTotal
add eax,bytesGo
.if eax>BufferSize
.break
.else
mov bytesTotal,eax
.endif
invoke lstrcat,lpOutBuf,addr buffer
.endif
.endw
ret
ReadPipeThread endp
Posted on 2003-10-17 21:46:55 by optimus
The API docs say that TerminateThread is not a very good choice. Perhaps you could set a global variable instead to signal thread termination, and write zero bytes to the pipe (if that doesn't work, try writing a CR/LF pair) to make your thread return from ReadFile. :)
Posted on 2003-10-18 15:23:31 by QvasiModo
It's probably because you don't close the process handle.
Posted on 2003-10-18 15:38:20 by Sephiroth3