; PIPE.ASM--
; Error Message Pipe for Edit
;
; PIPE <command> <args>
;
; Creates a buffer of stdout and stderr from Shell(command)
; If Shell() returns a value (errorlevel) ParseOutput() is called
;
include	clib.inc
include	io.inc
include	dir.inc
include	dos.inc
include	alloc.inc
include	stdio.inc
include	string.inc
include	kernel32.inc

; extern parser for output
ParseOutput proto stdcall Buffer:dword, bSize:dword

	.code

BUFFERSIZE equ 40000h

main	proc c uses ebx edi esi
local 	cmd[WMAXPATH]:byte
local	sa:SECURITY_ATTRIBUTES
local	pi:PROCESS_INFORMATION
local	sinfo:STARTUPINFO
local	hRd:dword
local	hWr:dword
local	hDup:dword
local	buffer:dword
local	dwCount:dword
local	ExitCode:dword
	mov edi,_argc
	mov esi,_argv
	.if _argc > 1
	    lea ebx,cmd
	    lodsd
	    lodsd
	    invoke strcpy,ebx,eax
	    sub edi,2
	    .if edi
	    	.repeat
		    invoke strcat,ebx,cstr(" ")
		    lodsd
		    invoke strcat,ebx,eax
		    dec edi
		.until !edi
	    .endif
	    sub eax,eax
	    mov ExitCode,eax
	    mov dwCount,eax
	    lea edi,sinfo
	    mov ecx,sizeof(STARTUPINFO)/4
	    rep stosd
	    mov sa.bInheritHandle,1
	    mov sa.lpSecurityDescriptor,0
	    mov sa.nLength,sizeof(SECURITY_ATTRIBUTES)
	    .if func(CreatePipe,addr hRd,addr hWr,addr sa,0)
		call GetCurrentProcess
		mov edi,eax
		invoke DuplicateHandle,edi,hRd,edi,addr hDup,0,0,DUPLICATE_SAME_ACCESS
		mov esi,eax
		invoke CloseHandle,hRd
		.if esi
		    mov sinfo.cb,sizeof(STARTUPINFO)
		    invoke GetStartupInfoA,addr sinfo
		    mov eax,hWr
		    mov sinfo.hStdOutput,eax
		    mov sinfo.hStdError,eax
		    mov sinfo.dwFlags,STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES
		    mov sinfo.wShowWindow,SW_HIDE
		    .if func(CreateProcessA,0,addr cmd,0,0,1,0,0,0,addr sinfo,addr pi)
			invoke CloseHandle,hWr
			mov esi,BUFFERSIZE
			.if func(GlobalAlloc,GMEM_FIXED,esi)
			    mov buffer,eax
			    mov edi,eax
			    sub eax,eax
			    mov ecx,BUFFERSIZE/4
			    rep stosd
			    mov edi,buffer
			    .repeat
				invoke ReadFile,hDup,edi,esi,addr dwCount,0
				.break .if !eax
				mov eax,dwCount
				add edi,eax
				sub esi,eax
				.break .if !esi
			    .until !eax
			.endif
		      	.repeat
			    invoke GetExitCodeProcess,pi.hProcess,ADDR ExitCode
			.until ExitCode != STILL_ACTIVE
			invoke CloseHandle,pi.hProcess
			invoke CloseHandle,pi.hThread
			mov eax,BUFFERSIZE
			sub eax,esi
			.if eax
			    invoke ParseOutput,buffer,eax
			.endif
			.if buffer
			    invoke GlobalFree,buffer
			.endif
			sub eax,eax
		    .else
	    		invoke _print,cstr(<"Unable to create process",10>)
			mov eax,1
		    .endif
		.else
	    	    invoke _print,cstr(<"Unable to duplicate handle",10>)
	    	    mov eax,1
		.endif
	    .else
	    	invoke _print,cstr(<"Unable to create pipe",10>)
	    	mov eax,1
	    .endif
	.else
	    invoke _print,cstr(<"Usage: PIPE <command> <args>",10>)
	    sub eax,eax
	.endif
    	ret
main	endp

	end
