The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Neil on November 27, 2008, 11:40:10 AM

Title: Console Output Handle
Post by: Neil on November 27, 2008, 11:40:10 AM
I have a number of procs which all begin :-

     LOCAL hOutPut:DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut,eax

Is there any advantage in making this Handle Global i.e. doing it only once at the beginning of the program & thus doing away with all the GetStdHandle handle calls.
Title: Re: Console Output Handle
Post by: Vortex on November 27, 2008, 11:50:06 AM
Yes, you can make it global to avoid multiple calls to GetStdHandle
Title: Re: Console Output Handle
Post by: Neil on November 27, 2008, 11:54:44 AM
Thanks Vortex, why I had my doubts was because I was taught that it was good practice to release a handle as soon as it was finished with.
Title: Re: Console Output Handle
Post by: Vortex on November 27, 2008, 12:03:10 PM
Hi Neil,

You are welcome.

You can have a look at the source code of StdOut.asm, it does not release the handle at the end :

StdOut proc lpszText:DWORD

    LOCAL hOutPut  :DWORD
    LOCAL bWritten :DWORD
    LOCAL sl       :DWORD

    invoke GetStdHandle,STD_OUTPUT_HANDLE
    mov hOutPut, eax

    invoke StrLen,lpszText
    mov sl, eax

    invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL

    mov eax, bWritten
    ret

StdOut endp
Title: Re: Console Output Handle
Post by: Tedd on November 27, 2008, 12:04:37 PM
Quote from: Neil on November 27, 2008, 11:54:44 AM
I was taught that it was good practice to release a handle as soon as it was finished with.

That's right, but you're not finished with it until you've finished printing text to the console :wink

The handle actually exists whether you use it or not - it's created when the program is loaded (which is why you have to link as a console program; or you must AllocConsole yourself to create it.) You didn't actually create it, so you're not the one destroying it either. Apply that rule to handles you specifically create, e.g. file handles, graphic objects, etc.
Title: Re: Console Output Handle
Post by: Neil on November 27, 2008, 01:35:44 PM
Thanks Vortex & Tedd for clearing that one up :thumbu
Title: Re: Console Output Handle
Post by: redskull on November 27, 2008, 01:45:42 PM
In keeping with the way "they" teach, the preferred method might be to get the handle once, in the beggining, and then pass it to each function that needs to print as an argument, in lieu of accessing the global varaible directly from each WriteFile() line.

-alan
Title: Re: Console Output Handle
Post by: Mark Jones on November 27, 2008, 05:30:33 PM
I think the MASM32 "print" macro gets this handle every time it is used. When I would run a MASM32 console program through MemProof (a memory leak tool, search here) it would report many such "unfreed handles." However Tedd is correct, when we "GetStdHandle" it is not actually creating a handle, just giving us the handle which is already there. Thus, perhaps a few clock cycles could be saved if we get this handle once and referr to it globally.

Here is a basic routine in GoASM syntax, which outputs unicode text. If "threaded" is defined (#define threaded), it becomes thread-safe, meaning two or more threads from the same process cannot write text to the output at the same time.


.data
CSect CRITICAL_SECTION<> ; threading info

.code

coutt frame hConsole,lpTextW ; console-out (threaded)
local n ; returns nChars as eax

#ifdef threaded
invoke EnterCriticalSection,addr CSect ; only allow one at a time
#endif
xor eax,eax ; get length of text arg
mov ecx,[lpTextW]
: cmp w[ecx+eax],0
jz >
add eax,2
jmp <
: shr eax,1 ; eax = n unicode chars
invoke WriteConsole,[hConsole],[lpTextW],eax,addr n,0
#ifdef threaded
invoke LeaveCriticalSection,addr CSect
#endif
mov eax,[n]
ret
endf


Use as:


.data
align 4
hCin dd ? ; console handles
hCout dd ?
hCerr dd ?
wMyString dw "Hello World from UNICODE land!",13,10,0

.code
start:
invoke GetStdHandle,STD_INPUT_HANDLE ; get console handles (once)
mov [hCin],eax
invoke GetStdHandle,STD_ERROR_HANDLE
mov [hCerr],eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [hCout],eax
invoke SetConsoleMode,[hCin],ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT

invoke coutt,[hCout],addr wMyString ; print desired text to hCout
; number of characters written returned in EAX