flat assembler
Message board for the users of flat assembler.
Index
> Tutorials and Examples > A Win32 console keypress example (Updated) Goto page 1, 2 Next |
Author |
|
revolution 30 Mar 2024, 08:40
MatQuasar wrote: I don't know, there is also PeekConsoleInputA (without clearing the input buffer). Code: proc WIN32_is_key_waiting ;return 0 if no keys waiting locals read_count dd ? endl invoke PeekNamedPipe,[handle_std_input],NULL,0,NULL,addr read_count,NULL mov eax,[read_count] test eax,eax jnz .done invoke GetFileType,[handle_std_input] cmp eax,FILE_TYPE_CHAR .done: setnz al movzx eax,al ret endp |
|||
30 Mar 2024, 08:40 |
|
AsmGuru62 30 Mar 2024, 12:02
Windows Console by default is set up in a way, where user can type characters and they are echoed to screen right away and the input ends with [ENTER] key. You need to use the SetConsoleMode function to cancel that behavior, so the ReadConsoleInput can actually wait for a key to be pressed and then decide to echo it or not -- all this will depend on your code.
|
|||
30 Mar 2024, 12:02 |
|
MatQuasar 30 Mar 2024, 12:33
Thanks revolution for your supplementary code and AsmGuru62 for your tip & trick.
I just tested my code at Post #1 in Windows Terminal and PowerShell, it didn't work properly by waiting for keypress. It only worked in Command Prompt window. Any idea why? |
|||
30 Mar 2024, 12:33 |
|
bitRAKE 30 Mar 2024, 17:45
Display the console mode for each interface. I'd wager they are different. Best to use SetConsoleMode as AsmGuru62 suggests.
_________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
30 Mar 2024, 17:45 |
|
MatQuasar 30 Mar 2024, 20:28
bitRAKE wrote: Display the console mode for each interface. I'd wager they are different. Best to use SetConsoleMode as AsmGuru62 suggests. Thanks, I think it is because ENABLE_WINDOW_INPUT is not enabled on Windows Terminal and PowerShell. SetConsoleMode wrote: If the hConsoleHandle parameter is an input handle, the mode can be one or more of the following values. When a console is created, all input modes except ENABLE_WINDOW_INPUT and ENABLE_VIRTUAL_TERMINAL_INPUT are enabled by default. But I am having extra work to do to debug the GetConsoleMode and SetConsoleMode. Strange, the mode values returned is 0x40202E no matter what values I set or clear, and is the same across all interfaces. Maybe something wrong with my hex conversion routine. I will try again tomorrow. |
|||
30 Mar 2024, 20:28 |
|
revolution 30 Mar 2024, 21:23
MatQuasar wrote: ... the mode values returned is 0x40202E ... |
|||
30 Mar 2024, 21:23 |
|
MatQuasar 30 Mar 2024, 21:33
revolution wrote:
OMG, I passed wrong value to wsprintfA, should have passed in bracket, i.e. [_mode] instead of _mode. Thank you very much, revolution! |
|||
30 Mar 2024, 21:33 |
|
revolution 30 Mar 2024, 23:02
If you are not yet using a debugger then you should definitely look into using one.
Those kinds of silly mistakes can be identified and fixed effortlessly. |
|||
30 Mar 2024, 23:02 |
|
MatQuasar 31 Mar 2024, 09:05
I took note, revolution.
bitRAKE wrote: Display the console mode for each interface. I'd wager they are different. Best to use SetConsoleMode as AsmGuru62 suggests. I run a test and there is no difference in console mode value returned across CMD, PS, and Windows Terminal's CMD. (see screenshot) 0x1F7 is the initial value, 0x1FF after setting ENABLE_WINDOW_INPUT. But the behavior still the same, PS and Windows Terminal's CMD don't wait for keypress. Or even I click Run in FASMW.EXE, the CMD popped up also doesn't wait for keypress. Only work when I run the program by typing the filename in CMD. So ENABLE_WINDOW_INPUT is not the answer.
Last edited by MatQuasar on 06 Apr 2024, 12:45; edited 1 time in total |
||||||||||
31 Mar 2024, 09:05 |
|
AsmGuru62 31 Mar 2024, 12:12
Please try to set Mode to 0.
|
|||
31 Mar 2024, 12:12 |
|
MatQuasar 31 Mar 2024, 14:17
AsmGuru62 wrote: Please try to set Mode to 0. Thanks for your reply. I set to mode 0 for screen input buffer handle, but the same behavior is reported. |
|||
31 Mar 2024, 14:17 |
|
AsmGuru62 31 Mar 2024, 21:58
I looked closely at the code you provided in post #1.
I am sure you are using GetConsoleInput function in a wrong way. Let me paste some of your code here: Code: push _dummy push 2 push _buffer push eax call [ReadConsoleInputA] I think you do not need the 'A' in the name of this function. And now, lets check your variables: Code:
_dummy dd ?
_buffer rb 2
ReadConsoleInput function is reading structures, so that "_buffer" should be a structure, at least one structure of type INPUT_RECORD. Lets assume that we will read just one structure at a time, so then we do not care about the size of this structure. You can find it all in the description of the function. The size of INPUT_RECORD is definitely not 2 bytes. Lets get safe here and make it a good 32 bytes piece of memory. When the function returns -- the first 16-bit value of the structure will indicate the type of the Console Input Event that was returned. It can be a key, menu command, mouse event or event if you resize the Console window -- that is also reported using this function. In your case -- you want the key, and that is a value of 1 in that 16-bit WORD at the beginning of the structure. So, basically, you have to LOOP this function until it returns a key event. So, these lines of code I pasted will look like this: Code: _dummy dd 0 _buffer dw 0 _event rb 30 ; <-- this is where Windows will put details about the key ... ; --> call SetConsoleMode with '0' mode waiting: push -10 call [GetStdHandle] push _dummy push 1 push _buffer push eax call [ReadConsoleInputA] cmp [_buffer], 1 jne waiting ... ; key was pressed at this point |
|||
31 Mar 2024, 21:58 |
|
bitRAKE 31 Mar 2024, 22:21
This is what I am currently using:
Code: invoke GetConsoleMode, [.hIn], addr .oldInMode mov edx, not (ENABLE_LINE_INPUT or ENABLE_ECHO_INPUT) and edx, [.oldInMode] invoke SetConsoleMode, [.hIn], rdx
_________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||||||||||
31 Mar 2024, 22:21 |
|
MatQuasar 01 Apr 2024, 06:18
Thank you so much, bitRAKE for the detailed analysis. I forgot it is a key event. It is eye opening for me to know need to allocate 32-bytes for buffer (dw 0 + rb 30).
Your code modificiation now is better, work in FASMW.EXE's Run command as well besides CMD, but still not working in PowerShell and Windows Terminal. But your press_key.exe is amazing! It works perfectly on all command processors! You are truly an advanced programmer. |
|||
01 Apr 2024, 06:18 |
|
MatQuasar 01 Apr 2024, 16:18
Whoops....! It was AsmGuru62 who replied with code modification! I thought both posts were made by bitRAKE.
Thank you AsmGuru62. Yes, I did set mode to 0 or with 0x0008. |
|||
01 Apr 2024, 16:18 |
|
bitRAKE 01 Apr 2024, 19:18
MatQuasar wrote: It works perfectly on all command processors! You are truly an advanced programmer. _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
01 Apr 2024, 19:18 |
|
MatQuasar 01 Apr 2024, 21:44
You're welcome, bitRAKE. I think I still need to figure ReadConsoleInput....
AsmGuru62 wrote: I looked closely at the code you provided in post #1. I know why your code still doesn't work in PowerShell and Windows Terminal. Thank you for pointing out the improvement. This time I read the Win32 API documentation and example properly. As screenshot shows, the first event registered is "key released" when running PowerShell and Windows Terminal, while command prompt wait for key press than echo "key pressed". I look at the MS example C code, need to check KEY_EVENT_RECORD for key down, just the key event is not enough. But I don't know the exact length of INPUT_RECORD, I am going to disassemble the example C code I compiled, using IDA Freeware. Will post here tomorrow or later.
|
||||||||||
01 Apr 2024, 21:44 |
|
MatQuasar 02 Apr 2024, 07:30
I fixed it!!! Thanks AsmGuru62 for initially pointing to INPUT_RECORD.
I found the length of INPUT_RECORD struct as dissassembled by IDA Freeware: Code: 00000000 _INPUT_RECORD struc ; (sizeof=0x14, align=0x4, copyof_152) 00000000 ; XREF: _main/r 00000000 EventType dw ? 00000002 db ? ; undefined 00000003 db ? ; undefined 00000004 Event _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4 ? 00000014 _INPUT_RECORD ends 00000014 00000000 _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4 union ; (sizeof=0x10, align=0x4, copyof_153) 00000000 ; XREF: _INPUT_RECORD/r 00000000 KeyEvent KEY_EVENT_RECORD ? 10+2 00000000 MouseEvent MOUSE_EVENT_RECORD ? 10 00000000 WindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD ? 4 00000000 MenuEvent MENU_EVENT_RECORD ? 4 00000000 FocusEvent FOCUS_EVENT_RECORD ? 4 00000000 _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4 ends 00000000 00000000 KEY_EVENT_RECORD struc ; (sizeof=0x10, align=0x4, copyof_154) 00000000 ; XREF: _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4/r 00000000 bKeyDown dd ? 00000004 wRepeatCount dw ? 00000006 wVirtualKeyCode dw ? 00000008 wVirtualScanCode dw ? 0000000A uChar _KEY_EVENT_RECORD::$0E79EC4DAC98A4AB202537FA8C3F69FC ? 0000000C dwControlKeyState dd ? 00000010 KEY_EVENT_RECORD ends 00000010 00000000 _KEY_EVENT_RECORD::$0E79EC4DAC98A4AB202537FA8C3F69FC union ; (sizeof=0x2, align=0x2, copyof_156) 00000000 ; XREF: KEY_EVENT_RECORD/r 00000000 UnicodeChar dw ? 00000000 AsciiChar db ? 00000000 _KEY_EVENT_RECORD::$0E79EC4DAC98A4AB202537FA8C3F69FC ends 00000000 00000000 MOUSE_EVENT_RECORD struc ; (sizeof=0x10, align=0x4, copyof_158) 00000000 ; XREF: _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4/r 00000000 dwMousePosition COORD ? 00000004 dwButtonState dd ? 00000008 dwControlKeyState dd ? 0000000C dwEventFlags dd ? 00000010 MOUSE_EVENT_RECORD ends 00000010 00000000 MENU_EVENT_RECORD struc ; (sizeof=0x4, align=0x4, copyof_165) 00000000 ; XREF: _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4/r 00000000 dwCommandId dd ? 00000004 MENU_EVENT_RECORD ends 00000004 00000000 WINDOW_BUFFER_SIZE_RECORD struc ; (sizeof=0x4, align=0x2, copyof_163) 00000000 ; XREF: _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4/r 00000000 dwSize COORD ? 00000004 WINDOW_BUFFER_SIZE_RECORD ends 00000004 00000000 FOCUS_EVENT_RECORD struc ; (sizeof=0x4, align=0x4, copyof_168) 00000000 ; XREF: _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4/r 00000000 bSetFocus dd ? 00000004 FOCUS_EVENT_RECORD ends 00000004 I updated the code at post #1 accordingly, now it works on all interfaces. I just need to run additional check for keydown after initial check for keyevent.
Last edited by MatQuasar on 02 Apr 2024, 11:01; edited 1 time in total |
||||||||||
02 Apr 2024, 07:30 |
|
MatQuasar 02 Apr 2024, 10:37
But I don't understand, there is padded bytes automatically added by compiler.
For example: Code: typedef struct _INPUT_RECORD { WORD EventType; union { KEY_EVENT_RECORD KeyEvent; MOUSE_EVENT_RECORD MouseEvent; WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; MENU_EVENT_RECORD MenuEvent; FOCUS_EVENT_RECORD FocusEvent; } Event; } INPUT_RECORD; ....is become: Code: 00000000 _INPUT_RECORD struc ; (sizeof=0x14, align=0x4, copyof_152) 00000000 ; XREF: _main/r 00000000 EventType dw ? 00000002 db ? ; undefined 00000003 db ? ; undefined 00000004 Event _INPUT_RECORD::$56C9F45CD5AB058B1B4FD5A9AB9216C4 ? 00000014 _INPUT_RECORD ends Two undefined "db ? " added. Is it because needed by alignment , which is 32-bit? And what about this: Code: 00000000 _KEY_EVENT_RECORD::$0E79EC4DAC98A4AB202537FA8C3F69FC union ; (sizeof=0x2, align=0x2, copyof_156) 00000000 ; XREF: KEY_EVENT_RECORD/r 00000000 UnicodeChar dw ? 00000000 AsciiChar db ? 00000000 _KEY_EVENT_RECORD::$0E79EC4DAC98A4AB202537FA8C3F69FC ends Is the size of struct 3 bytes or 4 bytes?
Last edited by MatQuasar on 03 Apr 2024, 14:45; edited 1 time in total |
||||||||||
02 Apr 2024, 10:37 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.