News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Calling API WriteConsoleOutput

Started by frktons, August 02, 2010, 10:31:27 PM

Previous topic - Next topic

frktons

Hi!

I've recentely realized a function in C for displaying a win32 console screen:


//--------------------------------------------------------------------------------------------------
// Display a console screen in a 80 cols  x 25 rows fixed size console
//--------------------------------------------------------------------------------------------------
// Structure for preparing output data
//--------------------------------------------------------------------------------------------------
// typedef struct _CHAR_INFO { // chi 
//    union {                /* Unicode or ANSI character  */
//        WCHAR UnicodeChar;
//        CHAR AsciiChar;
//    } Char;
//    WORD Attributes;       // text and background colors
// } CHAR_INFO, *PCHAR_INFO;
//--------------------------------------------------------------------------------------------------
void  DisplayCon(const CHAR_INFO * starget){


    COORD bufferSize = {80, 25};
    COORD TopLeft = {0,0};

    SMALL_RECT Out_buf;

    Out_buf.Left = 0;
    Out_buf.Top = 0;
    Out_buf.Right = 79;
    Out_buf.Bottom = 24;


    WriteConsoleOutput(wHnd,starget, bufferSize, TopLeft, &Out_buf);

    return;

}


How do I define all these structures for calling the WriteConsoleOutput API,
and what is the MASM format for calling/invoking it?
In few words, how this function is going to look as a MASM procedure?

Thanks



Mind is like a parachute. You know what to do in order to use it :-)

dedndave

they should already be defined for you in windows.inc   :U
give me some time to scratch out some code...

BOOL WINAPI WriteConsoleOutput(
  __in     HANDLE hConsoleOutput,
  __in     const CHAR_INFO *lpBuffer,
  __in     COORD dwBufferSize,
  __in     COORD dwBufferCoord,
  __inout  PSMALL_RECT lpWriteRegion
);

helps if i use the right function - lol

dedndave

BufHght EQU 25                                          ;buffer height (rows)
BufWdth EQU 80                                          ;buffer width (columns)
BufLen  EQU BufHght*BufWdth                             ;string length (tchars)

        .DATA?

hStdOut dw ?

CharBuf CHAR_INFO BufLen dup(<>)

;CHAR_INFO STRUCT
;  Char          CHARTYPE <>
;  Attributes    WORD      ?
;CHAR_INFO ENDS

;CHARTYPE UNION
; UnicodeChar    WORD ?
; AsciiChar      db ?
;CHARTYPE ENDS

SizCord COORD <>
LocCord COORD <>

;COORD STRUCT
;  x  WORD      ?
;  y  WORD      ?
;COORD ENDS

WrRgn  SMALL_RECT <>

;SMALL_RECT STRUCT
;  Left      WORD      ?
;  Top       WORD      ?
;  Right     WORD      ?
;  Bottom    WORD      ?
;SMALL_RECT ENDS

        .CODE

        INVOKE  GetStdHandle,STD_OUTPUT_HANDLE
        mov     hStdOut,eax
        INVOKE  WriteConsoleOutput,
                eax,
                offset CharBuf,
                offset SizCord,
                offset LocCord,
                offset WrRgn


sorry i don't have a little more time, Frank
i wanted to make a complete working example
but, you'll have to fill in the structures
i have shown their definitions (from windows.inc) in the comments

frktons

Thanks Dave. It is a good start. I have to prepare a small application
to read a file into a memory area, to process a little, and afterwards to fill
the fields before calling WriteConsoleOutput.

So let's start, it'll take a while  :P at my slow pace  :lol
Mind is like a parachute. You know what to do in order to use it :-)

frktons

Back to my pc for a while.

I put something together, but I probably still miss some SMALL_RECT
or COORD:
Microsoft (R) Macro Assembler Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: C:\masm32\examples\viewfmt\viewfmt.asm
C:\masm32\examples\viewfmt\viewfmt.asm(88) : error A2098:invalid operand for OFF
SET
C:\masm32\examples\viewfmt\viewfmt.asm(88) : error A2114:INVOKE argument type mi
smatch : argument : 5
C:\masm32\examples\viewfmt\viewfmt.asm(88) : error A2114:INVOKE argument type mi
smatch : argument : 4
C:\masm32\examples\viewfmt\viewfmt.asm(88) : error A2114:INVOKE argument type mi
smatch : argument : 3
_
Assembly Error


the prog I put together is:

;----------------------------------------------------------------------
; Reads a file containing a console screen format into an array
; of structure CHAR_INFO totalling 8000 bytes, and invoke the API
; to display it all at once: WriteConsoleOutput(). Wait a key and
; terminates the program.
;----------------------------------------------------------------------
; Input file: myfiles.txt
;----------------------------------------------------------------------
; Author: frktons @ MASM32 forum
; Date: 17/aug/2010.
;----------------------------------------------------------------------


include \masm32\include\masm32rt.inc

Console80x25 PROTO


.data

        bytecount dd 8000 ; Bytes to read from input file
        ConTitle  db "Win32 Console 80 x 25 Fixed Size - Extended ASCII chart", 0       

.data?

        hFile     HANDLE ?

        charArray CHAR_INFO 2000 dup (<>)

        wHnd      HANDLE ?
        rHnd      HANDLE ?
        inpbyte   DWORD  ?

.code
start: 

        mov hFile, fopen("myfiles.txt")

        mov ebx, fread(hFile, offset charArray, bytecount)

        fclose hFile


        invoke AllocConsole

        invoke Console80x25

        invoke GetStdHandle, STD_INPUT_HANDLE
        mov rHnd,eax

        invoke ReadConsole, rHnd, ADDR inpbyte, 1, NULL, NULL

finish: invoke ExitProcess,0

        ret
   

Console80x25 PROC

    LOCAL windowSize:SMALL_RECT
    LOCAL bufferSize:COORD
    LOCAL startPoint:COORD

    mov windowSize.Left, 0
    mov windowSize.Right, 0
    mov windowSize.Top, 79
    mov windowSize.Bottom, 24
   

    mov bufferSize.x, 80
    mov bufferSize.y, 25

    mov startPoint.x, 0
    mov startPoint.y, 0
   
    invoke GetStdHandle, STD_OUTPUT_HANDLE
    mov wHnd,eax
   

   
    invoke SetConsoleTitle, ADDR ConTitle
   
    invoke SetConsoleWindowInfo, wHnd, TRUE, ADDR windowSize

    invoke SetConsoleScreenBufferSize, wHnd, DWORD PTR bufferSize

    invoke WriteConsoleOutput, wHnd, offset charArray, offset bufferSize, offset startPoint, offset windowSize

    ret

Console80x25 ENDP


end start



and guess where the errors are? Just in WriteConsoleOutput invoke.

What did I miss?
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

lemme seeeeee
you were trying to scroll, right ?
let me have a look.....

frktons

Quote from: dedndave on August 16, 2010, 11:38:06 PM
lemme seeeeee
you were trying to scroll, right ?
let me have a look.....


Hi Dave, I'm trying to display a complete console screen for the time being.
No scrolling at all.  ::)
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

oh - now i remember - lol
i don't think i would put the structures local inside the proc
same is true of SetConsoleTitle, unless you want to change it each time
(generally, it is set at program init and left as is)

i would probably declare the structures as data, then pass the pointers to the proc
from there, you should be able to use PTR to point to the structure and access the different elements

AllocConsole is kind of a useless gizmo when called from a console app - lol
it creates a new console window, but the old one is rendered useless
or, at least, overly complicated to get back to   :P
it is useful if you are running a GUI app and want a console window to run along side

the errors you are getting are because you can't use OFFSET with local variables
locals are on the stack, and are thus addressed with something like [ebp-4]
you may be able to use ADDR instead of OFFSET
although, you can run out of registers, too
in which case, you may have to use LEA and push the parms individually (you shouldn't have to do this)
but - if the structures are defined in the .data segment, you can use OFFSET

are you assembling this as a console app or GUI ?

dedndave

oh - could you post your screen data file so i don't have to make one ?
thanks

KeepingRealBusy

frktons,

Most APIs are not sensitive to the direction flag (sometimes they clear it when they return), but I believe Console Write is sensitive. I have a wrapper that saves flags, clears direction, then calls Console Write, then restores flags. I did this for both Console Write and Console Read.

Dave.

dedndave

generally, the DF is left cleared
if you set it, you should clear it when done
but, i don't see where Frank has set it
clearing and setting the DF, as well as PUSHF'ing and POPF'ing flags are surprisingly slow instructions

frktons

Now the pgm compiles but doesn't show anything worth seeing  ::)
I attach the new version and the screen file for your tests.

The new code looks like this:

;----------------------------------------------------------------------
; Reads a file containing a console screen format into an array
; of structure CHAR_INFO totalling 8000 bytes, and invoke the API
; to display it all at once: WriteConsoleOutput(). Wait a key and
; terminates the program.
;----------------------------------------------------------------------
; Input file: myfile.txt
;----------------------------------------------------------------------
; Author: frktons @ MASM32 forum
; Date: 17/aug/2010.
;----------------------------------------------------------------------


include \masm32\include\masm32rt.inc

Console80x25 PROTO


.data

        bytecount dd 8000 ; Bytes to read from input file
        ConTitle  db "Win32 Console 80 x 25 Fixed Size - Extended ASCII chart", 0     
         
        charArray CHAR_INFO 2000 dup (<>)
        lp_charArray  dd charArray[0]   

        hFile     HANDLE 0


        wHnd      HANDLE 11
        rHnd      HANDLE 10
        inpbyte   DWORD  1 

        windowSize SMALL_RECT <>
        bufferSize COORD      <>
        startPoint COORD      <>

.data?



.code
start: 

        mov hFile, fopen("myfiles.txt")

        mov ebx, fread(hFile, offset charArray, bytecount)

        fclose hFile

        invoke GetStdHandle, STD_OUTPUT_HANDLE
        mov    wHnd,eax

        mov windowSize.Left, 0
        mov windowSize.Right, 0
        mov windowSize.Top, 79
        mov windowSize.Bottom, 24
   

        mov bufferSize.x, 80
        mov bufferSize.y, 25

        mov startPoint.x, 0
        mov startPoint.y, 0

        invoke SetConsoleTitle, ADDR ConTitle
       

        invoke Console80x25

        invoke GetStdHandle, STD_INPUT_HANDLE
        mov rHnd,eax

        invoke ReadConsole, rHnd, ADDR inpbyte, 1, NULL, NULL

finish: invoke ExitProcess,0

        ret
   

Console80x25 PROC


    invoke SetConsoleWindowInfo, wHnd, TRUE, ADDR windowSize

    invoke SetConsoleScreenBufferSize, wHnd, DWORD PTR bufferSize

    invoke WriteConsoleOutput, wHnd, offset charArray, offset bufferSize, offset startPoint, offset windowSize

    ret

Console80x25 ENDP


end start


and is attached in the zip file with the screen to display. Both need to stay on the same
folder.  :P

Mind is like a parachute. You know what to do in order to use it :-)

dedndave

well - it assembles
so, you got that going for you   :bg

frktons

Quote from: dedndave on August 17, 2010, 12:28:33 AM
well - it assembles
so, you got that going for you   :bg


And now let's try to make it work as well  :lol
Mind is like a parachute. You know what to do in order to use it :-)

dedndave

you are using ANSI chars, so each cell should look like this...
character  db 'A',0         ;the 0 is a filler - if it were unicode, it would contain data
attributes dw Attrib        ;refer to the link below


http://msdn.microsoft.com/en-us/library/ms682013%28VS.85%29.aspx

i am trying to write some code   :P
if you make a new DAT file.....