Author Topic: Control in console input?  (Read 1084 times)

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Control in console input?
« on: June 10, 2017, 11:02:16 AM »
Is there a way to limit input in the console to a maximum of keys?

Code: [Select]
.386
.model  flat,stdcall
option  casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data?
hconsoleinput   dd  ?
hconsoleoutput  dd  ?
charswritten    dd  ?
charsread       dd  ?
charsattset     dd  ?

.data
programname db  "THE CONSOLE WAY!",0
welcome     db  "Hi, welcome to this program!",0ah,0dh
text        db  " "

.code

main    proc
        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     hconsoleinput,eax
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hconsoleoutput,eax
        invoke  SetConsoleTitle,offset programname   
        call    paintb
        invoke  SetConsoleTextAttribute,hconsoleoutput,\                            ; Set the text and background
                FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\     ;  colors.
                BACKGROUND_GREEN     
        invoke  WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\
                offset charswritten,NULL   
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\
                offset charsread,NULL
        invoke  ExitProcess,0
main    endp

paintb  proc                                                                        ; Fill into green.
        local   cc:COORD
        mov     cc.x,0
        mov     cc.y,0
        mov     eax,cc       
        invoke  FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN,\
                30000,eax,offset charsattset
        ret
paintb  endp
                 
        end     main
   

Here you can enter until 255 chars from the keyboard (including the enter key) But that's crap, how to limit this?
Felipe.

jj2007

  • Member
  • *****
  • Posts: 7764
  • Assembler is fun ;-)
    • MasmBasic
Re: Control in console input?
« Reply #1 on: June 10, 2017, 05:02:55 PM »
Is there a way to limit input in the console to a maximum of keys?
...
Here you can enter until 255 chars from the keyboard (including the enter key) But that's crap, how to limit this?

This has been answered already:

Does MASM32 include a Console string input function which can do the following:

1. Allows me to specify a maximum input length of the string

2. Handles input editing keys, such as arrow keys, backspace, and delete?

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #2 on: June 11, 2017, 01:16:48 AM »
Thanks jj. I'm starting to think that if i want to play with a console program,  it would better to "emulate" a console by creating a window and writing text there... :P
Felipe.

jj2007

  • Member
  • *****
  • Posts: 7764
  • Assembler is fun ;-)
    • MasmBasic
Re: Control in console input?
« Reply #3 on: June 11, 2017, 10:34:14 AM »
It is perhaps not totally impossible (GetNumberOfConsoleInputEvents+timer), but I am pessimistic. There are many thousands of absolutely useless functions in the Windows API, but the one function that could prevent buffer overflows doesn't exist. Strange, isn't it? :P

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #4 on: June 11, 2017, 12:09:27 PM »
 :biggrin:
Felipe.

Vortex

  • Member
  • *****
  • Posts: 1734
Re: Control in console input?
« Reply #5 on: June 11, 2017, 08:02:58 PM »
Hi felipe,

The code below does not replace the traditional input functions and you will have to implement the functionality of the DEL key :

Code: [Select]
.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\msvcrt.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib

.data

msg1        db 'You can type 10 characters. Hit RETURN to terminate the keyboard input',13,10,0
msg2        db '%c',0
msg3        db 13,10,'You typed : %s',13,10,0

.data?

buffer      db 10 dup(?)

.code

start:

    call    main
    invoke  ExitProcess,0

main PROC uses esi ebx

    invoke  crt_printf,ADDR msg1
    mov     esi,OFFSET buffer
    xor     ebx,ebx
@@:
    invoke  crt__getch
    cmp     eax,13
    je      finish
   
    push    eax
    invoke  crt_printf,ADDR msg2,eax
    pop     eax
   
    mov     BYTE PTR [esi+ebx],al
    inc     ebx
    cmp     ebx,10
    jne     @b

finish:

    invoke  crt_printf,ADDR msg3,esi
    ret

main ENDP

END start

Reference :

https://msdn.microsoft.com/en-us/library/078sfkak%28v=vs.100%29.aspx

Don't forget to check the StdIn function from masm32.lib

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #6 on: June 12, 2017, 06:34:57 AM »
Thanks Vortex, i will check this.  :t
Felipe.

jj2007

  • Member
  • *****
  • Posts: 7764
  • Assembler is fun ;-)
    • MasmBasic
Re: Control in console input?
« Reply #7 on: June 12, 2017, 09:27:28 AM »
Attached a test, let me know if that is what you wanted.

Seems to run OK on Win XP, 7-64 and the latest 10-64.
It's still a beta, and required some acrobatic workarounds ::)

qWord

  • Member
  • *****
  • Posts: 1471
  • The base type of a type is the type itself
    • SmplMath macros
Re: Control in console input?
« Reply #8 on: June 12, 2017, 10:10:08 AM »
This kind of question did come up several times in the past IIRC, e.g. here:
Win32 Console Addition
MREAL macros - when you need floating point arithmetic while assembling!

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #9 on: June 12, 2017, 12:54:53 PM »
Attached a test, let me know if that is what you wanted.

Seems to run OK on Win XP, 7-64 and the latest 10-64.
It's still a beta, and required some acrobatic workarounds ::)

Actually yes.
But what kind of file is the no exe file? :shock:
Felipe.

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #10 on: June 12, 2017, 12:59:52 PM »
This kind of question did come up several times in the past IIRC, e.g. here:
Win32 Console Addition
Thanks qword i will see it tomorrow. (Now i have to go to the bed..   :redface:).

 :lol:
Felipe.

jj2007

  • Member
  • *****
  • Posts: 7764
  • Assembler is fun ;-)
    • MasmBasic
Re: Control in console input?
« Reply #11 on: June 12, 2017, 05:22:01 PM »
But what kind of file is the no exe file? :shock:

In case you mean the *.asc file: the source. If you don't yet have RichMasm, you can open it in WordPad. Here is the main loop:

  .Repeat
      Print At(5, Locate(y)) " "
      Let esi=Input$("Go ahead, edit that string: ", "123456789012345678", max20)
      PrintLine "                       you typed [", esi, "]"
  .Until Len(esi)<5

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #12 on: June 13, 2017, 02:55:58 AM »
Well, seems like: "ReadConsole always wants a 256 buffer", (yes, dedndave is right  :bgrin:), but maybe is not the end of the world (certainly  :biggrin:). So in this program the way to control the input will be allocating a buffer size of 256 bytes for each input (if this size is less and the user writes more chars the program terminates  ::)).  Doing a clear screen and locating the cursor position will help it the control of the output. Now i have to control the input for just the CR key (probably using SetConsoleMode).

Code: [Select]
.386
.model  flat,stdcall
option  casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data?
hconsoleinput   dd  ?
hconsoleoutput  dd  ?
charswritten    dd  ?
charsread       dd  ?
charsattset     dd  ?

.data
programname db  "THE CONSOLE WAY!",0
welcome     db  "Hi, welcome to this program!",0ah,0dh
text        db  256 dup(" "),0
promptname  db  "Enter your name: "
saveit      db  0ah,0ah,"Exit program?(Y/N): "
usernbuff   db  256 dup(" "),0
username    db  256 dup(" "),0
inerror     db  "Error! names allowed of 20 chars max. only...",0

cursorp proto   :word,:word
paintb  proto   :word,:word

.code

main    proc
        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     hconsoleinput,eax
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hconsoleoutput,eax
        invoke  SetConsoleTitle,offset programname   

again:
        invoke  cursorp,0,0                                                         ; Locates the cursor.
        invoke  paintb,0,0                                                          ; Clears the screen.
        invoke  SetConsoleTextAttribute,hconsoleoutput,\                            ; Set the text and background
                FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\     ;  colors for the console.
                BACKGROUND_GREEN     
        invoke  WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\         ; Welcome message in screen.
                offset charswritten,NULL         
        invoke  WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\   ; Prompt for the user's name.
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
                offset charsread,NULL
        cmp     charsread,23                                                        ; More chars than allowed?:                           
        jb      all_ok                                                              ;  -no, so continue in all_ok.
        invoke  cursorp,0,0                                                         ;  -yes, so:
        invoke  paintb,0,0                                                          ;    *locate cursor and clears the screen.
        invoke  WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\         ;    *show error message.
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\                 ;*****(*Waits for the CR key.)*****
                offset charsread,NULL                                             
        jmp     again                                                                         
           
all_ok:       
        invoke  WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\
                offset charsread,NULL
        invoke  ExitProcess,0
main    endp

paintb  proc    colx:word,rowy:word                                                 ; Fill into green all the screen,
        local   cc:COORD                                                            ;   (background and foreground).
        mov     ax,colx
        mov     cc.x,ax
        mov     ax,rowy
        mov     cc.y,ax
        mov     eax,cc       
        invoke  FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
                FOREGROUND_GREEN,30000,eax,offset charsread
        ret
paintb  endp

cursorp proc    col:word,row:word                                                   ; Sets the cursor location.
        local   cc:COORD
        mov     ax,col
        mov     cc.x,ax
        mov     ax,row
        mov     cc.y,ax
        mov     eax,cc
        invoke  SetConsoleCursorPosition,hconsoleoutput,eax
        ret
cursorp endp         
       
        end     main


Felipe.

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #13 on: June 13, 2017, 05:13:00 AM »
Yeah, i added the SetConsoleMode function, first to allow just the CR key, and then for all the others (256 chars in the input buffer  ::)  :lol:). I guess this would be the most basic 'algo' for some text mode programs. Thanks for all your help!  :t

Code: [Select]
.386
.model  flat,stdcall
option  casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data?
hconsoleinput   dd  ?
hconsoleoutput  dd  ?
charswritten    dd  ?
charsread       dd  ?
charsattset     dd  ?

.data
programname db  "THE CONSOLE WAY!",0
welcome     db  "Hi, welcome to this program!",0ah,0dh
text        db  256 dup(" "),0
promptname  db  "Enter your name: "
saveit      db  0ah,0ah,"Exit program?(Y/N): "
usernbuff   db  256 dup(" "),0
username    db  256 dup(" "),0
inerror     db  "Error! names allowed of 20 chars max. only...",0

cursorp proto   :word,:word
paintb  proto   :word,:word

.code

main    proc
        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     hconsoleinput,eax
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hconsoleoutput,eax
        invoke  SetConsoleTitle,offset programname   

again:
        invoke  cursorp,0,0                                                         ; Locates the cursor.
        invoke  paintb,0,0                                                          ; Clears the screen.
        invoke  SetConsoleTextAttribute,hconsoleoutput,\                            ; Set the text and background
                FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\     ;  colors for the console.
                BACKGROUND_GREEN     
        invoke  WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\         ; Welcome message in screen.
                offset charswritten,NULL         
        invoke  WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\   ; Prompt for the user's name.
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
                offset charsread,NULL
        cmp     charsread,23                                                        ; More chars than allowed?:                           
        jb      all_ok                                                              ;  -no, so continue in all_ok.
        invoke  cursorp,0,0                                                         ;  -yes, so:
        invoke  paintb,0,0                                                          ;    *sets the cursor location and clears the screen.
        invoke  WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\         ;    *show error message.
                offset charswritten,NULL
        invoke  SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\                 ;    *Waits for the CR key.
                offset charsread,NULL     
        invoke  SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\                  ; Allow inputs again (256 chars).
                ENABLE_LINE_INPUT                                         
        jmp     again                                                                         
           
all_ok:       
        invoke  WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\
                offset charsread,NULL
        invoke  ExitProcess,0
main    endp

paintb  proc    colx:word,rowy:word                                                 ; Fill into green all the screen,
        local   cc:COORD                                                            ;   (background and foreground).
        mov     ax,colx
        mov     cc.x,ax
        mov     ax,rowy
        mov     cc.y,ax
        mov     eax,cc       
        invoke  FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
                FOREGROUND_GREEN,30000,eax,offset charsread
        ret
paintb  endp

cursorp proc    col:word,row:word                                                   ; Sets the cursor location.
        local   cc:COORD
        mov     ax,col
        mov     cc.x,ax
        mov     ax,row
        mov     cc.y,ax
        mov     eax,cc
        invoke  SetConsoleCursorPosition,hconsoleoutput,eax
        ret
cursorp endp         
       
        end     main

Felipe.

felipe

  • Member
  • ***
  • Posts: 378
  • assemble the unassembled.
Re: Control in console input?
« Reply #14 on: June 13, 2017, 06:32:20 AM »
Here one little more addition to this and a fix of some usless buffer: Now checks if you didn't enter any char (only CR key), only accept 2 chars as minimum for the name and a maximum of 20. The username buffer was useless (i think i forget it there... :lol:) so i deleted.

Code: [Select]
.386
.model  flat,stdcall
option  casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data?
hconsoleinput   dd  ?
hconsoleoutput  dd  ?
charswritten    dd  ?
charsread       dd  ?
charsattset     dd  ?

.data
programname db  "THE CONSOLE WAY!",0
welcome     db  "Hi, welcome to this program!",0ah,0dh
text        db  256 dup(" "),0
promptname  db  "Enter your name: "
saveit      db  0ah,0ah,"Exit program?(Y/N): "
usernbuff   db  256 dup(" "),0
inerror     db  "Error! names allowed of 20 chars as maximun only...",0
inerror2    db  "Error! you must put a name here of 2 chars as minimum...",0

cursorp proto   :word,:word
paintb  proto   :word,:word

.code

main    proc
        invoke  GetStdHandle,STD_INPUT_HANDLE
        mov     hconsoleinput,eax
        invoke  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hconsoleoutput,eax
        invoke  SetConsoleTitle,offset programname   

again:
        invoke  cursorp,0,0                                                         ; Locates the cursor.
        invoke  paintb,0,0                                                          ; Clears the screen.
        invoke  SetConsoleTextAttribute,hconsoleoutput,\                            ; Set the text and background
                FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\     ;  colors for the console.
                BACKGROUND_GREEN     
        invoke  WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\         ; Welcome message in screen.
                offset charswritten,NULL         
        invoke  WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\   ; Prompt for the user's name.
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
                offset charsread,NULL
        cmp     charsread,23                                                        ; More chars than allowed?:                           
        jb      all_ok                                                              ;  -no, so continue in all_ok.
        invoke  cursorp,0,0                                                         ;  -yes, so:
        invoke  paintb,0,0                                                          ;    *clears the screen.
        invoke  WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\         ;    *show error message.
                offset charswritten,NULL
        invoke  SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\                 ;    *Waits for the CR key.
                offset charsread,NULL     
        invoke  SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\                  ; Allows inputs again (256 chars).
                ENABLE_LINE_INPUT                                         
        jmp     again                                                                         
           
all_ok:   
        cmp     charsread,2   
        ja      all_ok2                                                             ; No input at all (just CR)?       
        invoke  cursorp,0,0                                                         ;  if so, set cursor location (0,0)
        invoke  paintb,0,0                                                          ;   clears the screen
        invoke  WriteConsole,hconsoleoutput,offset inerror2,sizeof inerror2,\       ;     show error message.
                offset charswritten,NULL
        invoke  SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT                      ; Just CR accepted.
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\
                offset charsread,NULL
        invoke  SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\                  ; All keys accepted from now
                ENABLE_LINE_INPUT                                                   ;   again.
        jmp     again

all_ok2:                                                                            ; Correct name format until here.
        invoke  WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
                offset charswritten,NULL
        invoke  ReadConsole,hconsoleinput,offset text,sizeof text,\
                offset charsread,NULL
        invoke  ExitProcess,0
main    endp

paintb  proc    colx:word,rowy:word                                                 ; Fill into green all the screen,
        local   cc:COORD                                                            ;   (background and foreground).
        mov     ax,colx
        mov     cc.x,ax
        mov     ax,rowy
        mov     cc.y,ax
        mov     eax,cc       
        invoke  FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
                FOREGROUND_GREEN,30000,eax,offset charsread
        ret
paintb  endp

cursorp proc    col:word,row:word                                                   ; Sets the cursor location.
        local   cc:COORD
        mov     ax,col
        mov     cc.x,ax
        mov     ax,row
        mov     cc.y,ax
        mov     eax,cc
        invoke  SetConsoleCursorPosition,hconsoleoutput,eax
        ret
cursorp endp         
       
        end     main
   

Felipe.