News:

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

Main Menu

Control in console input?

Started by felipe, June 10, 2017, 11:02:16 AM

Previous topic - Next topic

felipe

Is there a way to limit input in the console to a maximum of keys?


.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?

jj2007

Quote from: felipe on June 10, 2017, 11:02:16 AM
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:

Quote from: Brannagan on September 04, 2014, 06:43:08 PM
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

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

jj2007

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


Vortex

Hi felipe,

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

.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

Thanks Vortex, i will check this.  :t

jj2007

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

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

Quote from: jj2007 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 ::)

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

felipe

Quote from: qWord 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
Thanks qword i will see it tomorrow. (Now i have to go to the bed..   :redface:).

:lol:

jj2007

Quote from: felipe on June 12, 2017, 12:54:53 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

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).


.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

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


.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

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.


.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