ReadConsoleInputA引发访问冲突 [英] ReadConsoleInputA throws an Access Violation

查看:75
本文介绍了ReadConsoleInputA引发访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用Windows api(而不是仅使用C调用,irvine32或masm32),并且遇到了ReadConsoleInputA的问题(WriteConsoleA可以正常工作).

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

此外,我不明白为什么在该函数的PROC原型中,大多数示例在ReadConsoleInput/WriteConsole的末尾附加A或W,您能解释为什么吗?

Also, I don't get why in the PROC prototype for the function, most examples append either an A or a W at the end of ReadConsoleInput/WriteConsole, can you explain why?

.data
consoleOutHandle dd ?
consoleInHandle dd ?
bufferlen dd ?
buffer db ?
bufferSize DWORD ?
message db "Enter a number:", 0
lmessage equ $-message


.code
main PROC

    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov consoleOutHandle, eax

    invoke ReadConsoleInputA, consoleOutHandle, offset buffer, 128, bufferSize
main endp
end main

它抛出:访问冲突写入位置0x00000004.

It throws: Access violation writing location 0x00000004.

根据Michael Petch的建议,我现在有以下代码:

Following the advice from Michael Petch, I have this code now:

.data
consoleOutHandle dd ?
consoleInHandle dd ?
byteswritten dd ?
bufferlen dd ?
buffer db 128 DUP(?)
bufferSize 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, bytesWritten, 0

    invoke ReadConsoleInputA, consoleInHandle, offset buffer, 128, offset bufferSize
main endp
end main

现在它会引发触发断点".

And now it throws "triggered a breakpoint".

反汇编:

invoke ReadConsoleInputA, consoleInHandle, offset buffer, 128, offset bufferSize
00E71066  push        offset bufferSize (0E74090h)  
00E7106B  push        80h  
00E71070  push        offset buffer (0E74010h)  
00E71075  push        dword ptr [consoleInHandle (0E74004h)]  
00E7107B  call        _ReadConsoleInputA@16 (0E7100Ah)  
--- No source file -------------------------------------------------------------
00E71080  int         3    **---> Breakpoint here**
00E71081  int         3  

推荐答案

您问WinAPI函数末尾的AW后缀是什么.以A结尾的函数表示A nsi,以W结尾的函数为W ide. Microsoft通过以下方式记录它们:

You asked what the A and W suffix on the end of the WinAPI functions are for. Functions ending with A denote Ansi, and functions ending with W are Wide. Microsoft documents them this way:

Unicode和ANSI函数 当Microsoft向Windows引入Unicode支持时,它通过提供两组并行的API(一组用于ANSI字符串,另一组用于Unicode字符串)简化了过渡.例如,有两个函数可以设置窗口标题栏的文本:

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采用ANSI字符串.
  • SetWindowTextW采用Unicode字符串.
  • SetWindowTextA takes an ANSI string.
  • SetWindowTextW takes a Unicode string.


第一版代码


In the first version of the code

  • 您没有分配buffer所需的空间.你有:

buffer db ?

那为缓冲区分配了一个字节.应该是:

That allocated a single byte to the buffer. It should have been:

buffer db 128 DUP(?)

  • 您使用的是STD_OUTPUT_HANDLE而不是STD_INPUT_HANDLE

  • You used STD_OUTPUT_HANDLE instead of STD_INPUT_HANDLE

    ReadConsoleInputA的最后一个参数是指向DWORD的指针,该DWORD将返回读取的事件数.更改变量名称bufferSize可能会使代码更具可读性.从 ReadConsoleInputA 文档:

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

  • 如果您只在阅读键盘,则应该使用 ReadConsoleA 作为ReadConsoleInputA,将处理键盘和鼠标事件,并且可能在读取字符串之前过早返回. ReadConsoleA需要一个额外的参数,您可以将其设置为NULL:

  • 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
    );
    

  • 要退出程序,您需要调用ExitProcess.

    在第二版代码中

    • 您的代码可以:

    • Your code does:

    invoke WriteConsoleA, consoleOutHandle, offset message, eax, bytesWritten, 0
    

    bytesWritten必须是一个指针,因为这是一个输出参数.从 WriteConsoleA 文档:

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

  • 根据您的第二个代码示例,使用ReadConsoleA而不是ReadConsoleInputA的代码版本可能如下:

    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
    

    可以使用MASM的sizeof运算符来清除此代码.该代码可以写为:

    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
    

    这篇关于ReadConsoleInputA引发访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆