News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

WriteConsoleInput

Started by jj2007, January 03, 2013, 09:04:53 AM

Previous topic - Next topic

jj2007

Quote from: qWord on January 03, 2013, 09:02:13 PM
Well, I can't compile your source (SendStringsOnDemand) with MASM. Also, when using jWasm, I get an executable that behaviors differently than the EXE you supplied - I get directly an error "invalid handle".

That is odd. The library \Masm32\MasmBasic\MasmBasic.lib should have time stamp 2 Jan 13, 18:33, 68126 bytes. It doesn't work with ML.exe 6.14 (no SSE2), but 6.15 upwards works fine for me.

Sorry to impose MB on you, but re-writing the whole thing in plain Masm32 would be tedious. I am not proficient in C to write a corresponding example, and I haven't found any full example on the web...

It might even help to find an executable written in another language that does prefilling of an Input$() type prompt.

QuoteAlso, I've seen some "strange" comments in your code:
LOCAL PipeBytes, buffer[8000]:BYTE ; 8102 works, 8104 crashes, slow for small buffers (e.g. 100 bytes) How should one interpret that?

A few lines further down:
invoke ReadFile, hPipe, edi, sizeof buffer, addr PipeBytes, NULL

I have played with several values, of course if you take 2 bytes, you need many ReadFile calls, and that slows it down. Somewhere around 8102 for XP it starts crashing, the usual problem with stack & guard pages, so I chose 8000 as a compromise. This is for XP - Win7 seems to allow higher values.

In any case, thanks a lot for your willingness to help, much appreciated :icon14:

@sinsi: yes, that works perfectly in "direct", i.e. non-piped mode.
pushw KEY_EVENT
...
imul edx, edi, 18

does not crash, but the prefill stops working even in direct mode.

qWord

I'v download the library this morning. I get this error for all version of MASM
SendStringsOnDemand.asm(134) : error A2046:missing single or double quotation mark in string
cStyle$(2): Macro Called From
  Input$(3): Macro Called From
   Let(1): Macro Called From

the problem is the angle brackets in the literal "Enter x, Date or Time: !>"
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

Sorry, I use JWasm by default and didn't stumble over that one. Here is a workaround for ML 6.15:

                Let esi=Input$(Chr$("Enter x, Date or Time: ", 62),  esi)                ; let's simulate a prompt...

japheth


I do not really understand what you are trying to do, but if it's some inter-process communication with "key-strokes" being sent from a parent process to a child process, you should probably forget using pipes and look at DuplicateHandle() instead.

jj2007

Quote from: japheth on January 03, 2013, 10:55:02 PMI do not really understand what you are trying to do, but if it's some inter-process communication with "key-strokes" being sent from a parent process to a child process, you should probably forget using pipes and look at DuplicateHandle() instead.

The CmdGUI app (CmdGUI_full.exe) launches cmd.exe, displays its output in a standard edit control, and sends lines of text to cmd.exe via a pipe. Cursor up/down works like doskey /history. In short, a standard window instead of a console for cmd.exe. Right-click in CmdGUI to see one advantage of having that.

Then there is a console prog (SendStringsOnDemand.exe) that prompts for input, providing a prefilled string:
Enter x, Date or Time: >date
Everything works fine except prefilling via the pipe.

DuplicateHandle assumes that you have source code control over the child process - not a universal solution.

japheth

Quote from: jj2007 on January 03, 2013, 11:15:59 PM
DuplicateHandle assumes that you have source code control over the child process - not a universal solution.

Yes, I see. Additionally, according to MS, DuplicateHandle() will only copy console handles if target process and source process are identical.

jj2007

Are you aware of any plain C or C++ solution for the prompt with prefill? I have searched a lot, but all I found is examples in Python, Linux C++ and Ruby using the readline library plus a hook (code by Casper):

require 'rubygems'
require 'rb-readline'

module RbReadline
  def self.prefill_prompt(str)
    @rl_prefill = str
    @rl_startup_hook = :rl_prefill_hook
  end

  def self.rl_prefill_hook
    rl_insert_text @rl_prefill if @rl_prefill
    @rl_startup_hook = nil
  end
end

RbReadline.prefill_prompt("Previous query")
str = Readline.readline("Enter query: ", true)

puts "You entered: #{str}"


See The GNU Readline Library, 2.2MB to download, but it seems there is no Windows version.

The functionality is not that exotic; most travel agents still have a terminal-like screen where they can edit client data via prefill. Very old technology, it's amazing that they don't switch to Windows.

japheth

> Are you aware of any plain C or C++ solution for the prompt with prefill?

Hm, I guess the best solution is some kind of KI ( deutsch: Koud Intschäggtschen ).

A small routine that reads a pipe and writes to console via WriteConsoleInput(). It has to be copied to the "other" address space and run - may be using CreateRemoteThread().

jj2007

#23
'Son cannot speak for himself, so daddy puts the words in his mouth' - interesting idea, thanks Japheth.
Edit: There is one problem, though: In the CmdGUI case, it's the 'son' who knows what to say, i.e. the child process only knows what the prefilled string should contain...

Still, if anybody knows a console proggie that asks for input and offers a prefilled string, let me know. I had hoped to find something among the DOS command, but those which prompt the user do so without offering a string in the readline, it seems...

jj2007

I've put an update into the QikPad thread in the campus. Until now, I have not found a solution for the piped WriteConsoleInput problem.

What I did find, though, is that inkey (Masm32, using crt_getch) and Inkey (MasmBasic, using ReadFile) both behave badly when piped through cmd.exe: the proggies hang and must be killed via Task Manager. Workaround is to launch them with start myproggie. In contrast, Input$() does not hang the child process. However, the underlying ReadFile cannot be used as a substitute for inkey; SetConsoleMode 0 works in standalone mode, i.e. one keypress is enough, but in pipes it requires a Return. Confusing ::)

                invoke SetLastError, 0
                mov ebx, rv(GetStdHandle, STD_INPUT_HANDLE)
                invoke SetConsoleMode, ebx, 0        ; enable return after single key press (works standalone but not piped)
                push ecx        ; create a slot for chars read
                mov edx, esp
                invoke ReadFile, ebx, addr buffer, 1000, edx, 0        ; works fine, doesn't block, but needs Return in pipes
                deb 4, "ret", eax, $Err$()
                pop ecx        ; chars read

jj2007

I've put an update into the QikPad thread in the campus. Until now, I have not found a solution for the piped WriteConsoleInput problem.

What I did find, though, is that inkey (Masm32, using crt_getch) and Inkey (MasmBasic, using ReadFile) both behave badly when piped through cmd.exe: the proggies hang and must be killed via Task Manager. Workaround is to launch them with start myproggie. In contrast, Input$() does not hang the child process. However, the underlying ReadFile cannot be used as a substitute for inkey; SetConsoleMode 0 works in standalone mode, i.e. one keypress is enough, but in pipes it requires a Return. Confusing ::)

                invoke SetLastError, 0
                mov ebx, rv(GetStdHandle, STD_INPUT_HANDLE)
                invoke SetConsoleMode, ebx, 0        ; enable return after single key press (works standalone but not piped)
                push ecx        ; create a slot for chars read
                mov edx, esp
                invoke ReadFile, ebx, addr buffer, 1000, edx, 0        ; works fine, doesn't block, but needs Return in pipes
                deb 4, "ret", eax, $Err$()
                pop ecx        ; chars read