I am trying to learn how to use the windows api (instead of just using C calls, irvine32 or masm32) And are running into issues with ReadConsoleInputA (WriteConsoleA works fine)
You asked what the A
and W
suffix on the end of the WinAPI functions are for. Functions ending with A
denote A
nsi, and functions ending with W
are W
ide. Microsoft documents them this way:
Unicode and ANSI Functions When Microsoft introduced Unicode support to Windows, it eased the transition by providing two parallel sets of APIs, one for ANSI strings and the other for Unicode strings. For example, there are two functions to set the text of a window's title bar:
SetWindowTextA
takes an ANSI string.SetWindowTextW
takes a Unicode string.
In the first version of the code
You don't allocate space necessary for buffer
. You had:
buffer db ?
That allocated a single byte to the buffer. It should have been:
buffer db 128 DUP(?)
You used STD_OUTPUT_HANDLE
instead of STD_INPUT_HANDLE
The last parameter to ReadConsoleInputA
is a pointer to a DWORD that will return the number of events read. Changing the variable name bufferSize
might make the code more readable. From the ReadConsoleInputA documentation:
BOOL WINAPI ReadConsoleInput( _In_ HANDLE hConsoleInput, _Out_ PINPUT_RECORD lpBuffer, _In_ DWORD nLength, _Out_ LPDWORD lpNumberOfEventsRead );
If you are reading just the keyboard you should be using ReadConsoleA as ReadConsoleInputA
will process keyboard and mouse events and may prematurely return before your string is read. ReadConsoleA
takes one extra parameter and you can set it to NULL:
BOOL WINAPI ReadConsole( _In_ HANDLE hConsoleInput, _Out_ LPVOID lpBuffer, _In_ DWORD nNumberOfCharsToRead, _Out_ LPDWORD lpNumberOfCharsRead, _In_opt_ LPVOID pInputControl );
To exit the program you need to invoke ExitProcess
.
In the second version of the code
Your code does:
invoke WriteConsoleA, consoleOutHandle, offset message, eax, bytesWritten, 0
bytesWritten
needs to be a pointer because that is an output parameter. From WriteConsoleA documentation:
BOOL WINAPI WriteConsole( _In_ HANDLE hConsoleOutput, _In_ const VOID *lpBuffer, _In_ DWORD nNumberOfCharsToWrite, _Out_ LPDWORD lpNumberOfCharsWritten, _Reserved_ LPVOID lpReserved );
A version of the code that uses ReadConsoleA
instead of ReadConsoleInputA
based on your second code example could look like:
.data
consoleOutHandle dd ?
consoleInHandle dd ?
bytesWritten dd ?
bufferlen dd ?
buffer db 128 DUP(?)
numEvents dd ?
message db "Enter a number:", 0
lmessage equ $-message
.code
main PROC
invoke GetStdHandle, STD_INPUT_HANDLE
mov consoleInHandle, eax
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
mov eax, lmessage
invoke WriteConsoleA, consoleOutHandle, offset message, eax, offset bytesWritten, 0
invoke ReadConsoleA, consoleInHandle, offset buffer, 128, offset numEvents, 0
invoke ExitProcess, 0
main endp
end main
This code can be cleaned up a bit by using MASM's sizeof
operator. The code could be written as:
.data
consoleOutHandle dd ?
consoleInHandle dd ?
buffer db 128 DUP(?)
bytesWritten dd ?
numEvents dd ?
message db "Enter a number:", 0
.code
main PROC
invoke GetStdHandle, STD_INPUT_HANDLE
mov consoleInHandle, eax
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov consoleOutHandle, eax
invoke WriteConsoleA, consoleOutHandle, offset message, sizeof message, offset bytesWritten, 0
invoke ReadConsoleA, consoleInHandle, offset buffer, sizeof buffer, offset numEvents, 0
invoke ExitProcess, 0
main endp
end main