News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Way besides ExitProcess to exit a program?

Started by henry.chris, March 01, 2013, 05:36:20 PM

Previous topic - Next topic

henry.chris

This is a college programming assignment in masm32 using kernel32.lib

I'm trying to learn how to use windows API functions in my code, and have been successful with several.
Currently I want to learn how to exit a program without using invoke ExitProcess, 0
I have tried several things and feel I am getting closer, but am hitting a road block.  My goal is to
display "Goodbye" to the user for a small amount of time and then exit.
I am currently trying to use
invoke SetConsoleTitleA, near32 ptr currentTitle ; sets current title to Haha
invoke FindWindowA, 0h, near32 ptr currenTitle            ; Returns window handle


and then call

invoke SendMessageA,hwnd_window,WM_SYSCOMMAND,SC_CLOSE, 0h

I am trying to use FindWindow to return the handle for SendMessageA; however, I can't even
figure out how to use the return from the function in assembly. I can't find where it's returned to,
or how to set something to the return of the function if that is the case. 

I figure i can use SendMessageA to close the console at least.

Any ways I can exit with a displayed string and not just, "Press any key to Continue..."
like I usually get would be of great help.


MichaelW

Assuming that ESP has the same value that it had at entry (IOW, anything that was pushed onto the stack has been removed from the stack), you can set the return value in EAX and use RET.

    printf("Bye")
    invoke Sleep, 2000
    xor eax, eax
    ret

Well Microsoft, here's another nice mess you've gotten us into.

henry.chris

I defined the Sleep function and used it correctly. That works beautifully, thank you.
I'm not sure I completely understand the esp, but I think everything is pulled off the stack.
Using 'ret' seems to do the exact same thing as invoke ExitProcess, 0        though. The
"Goodbye" message is displayed, then the 'ret' exits the program and it displays "Press any key to continue..."

Is it a setting I have turned on somewhere? Should ExitProcess even ask to 'press a key to continue..."
or should it just close the console automatically?

MichaelW

#3
"Press any key to continue ..." is what the inkey macro displays. Perhaps I should have added that you cannot do this within a procedure. Here is my full test source:

;==============================================================================
    include \masm32\include\masm32rt.inc
;==============================================================================
    .data
    .code
;==============================================================================
start:
;==============================================================================
    printf("Bye")
    invoke Sleep, 2000
    xor eax, eax
    ret
;==============================================================================
end start


And perhaps I should also have added that you probably should not be using the inkey macro in a GUI app.

Also, if you are running the app from a batch file with a PAUSE command then you should see "Press any key to continue . . ." after the app terminates.
Well Microsoft, here's another nice mess you've gotten us into.

jj2007

The main difference between a simple ret and ExitProcess is that the latter uses a different way out.

ExitProce   8BC0            mov eax, eax                             ; kernel32.ExitProcess(ExitCode)
75CCBBE4    55              push ebp
75CCBBE5    8BEC            mov ebp, esp
75CCBBE7    6A FF           push -1
75CCBBE9    68 B0F3E877     push 77E8F3B0
75CCBBEE    FF75 08         push dword ptr [ebp+8]
75CCBBF1    FF15 1017C775   call dword ptr [<&ntdll.RtlExitUserProcess
... code never gets here ...
75CCBBF7    E9 ACE40000     jmp 75CDA0A8

BaseThreadInitThunk    8BFF            mov edi, edi
75CBED5C               55              push ebp
75CBED5D               8BEC            mov ebp, esp
75CBED5F               85C9            test ecx, ecx
75CBED61               0F85 4D010000   jne 75CBEEB4
75CBED67               FF75 08         push dword ptr [ebp+8]
75CBED6A               FFD2            call edx   << edx=00401000h, ret returns here
75CBED6C               50              push eax
75CBED6D               FF15 0C17C775   call dword ptr [<&ntdll.RtlExitUserThread
[/color]

dedndave

RtlExitUserProcess calls NtTerminateProcess
but, i am wondering what is wrong with ExitProcess ???   :P

    INVOKE  Sleep,-1
it may not terminate, but it will stop doing stuff   :biggrin:

Magnum


CPU Disasm
Address   Hex dump          Command                                  Comments
00401000  /$  68 00304000   PUSH OFFSET 00403000                     ; /format = "Bye"
00401005  |.  FF15 24204000 CALL DWORD PTR DS:[<&msvcrt.printf>]     ; \MSVCRT.printf
0040100B  |.  83C4 04       ADD ESP,4
0040100E  |.  68 D0070000   PUSH 7D0                                 ; /Time = 2000. ms
00401013  |.  E8 28000000   CALL <JMP.&kernel32.Sleep>               ; \KERNEL32.Sleep
00401018  |.  33C0          XOR EAX,EAX
0040101A  \.  C3            RETN



I wonder why this differs ?
Take care,
                   Andy

Ubuntu-mate-18.04-desktop-amd64

http://www.goodnewsnetwork.org

henry.chris

Ok, so at my school we have to use the visual studio environment for masm.  It just seems like it's how studio exits a program in assembly. It doesn't do this for .cpp or other languages i've used, so I just expected it to be a part of the ExitProcess somehow.  I used a different compiler etc... and got it to close successfully.  The invoke Sleep, -1 is actually cool if you have to display a long message.

Thank you for your time, I'm still learning so I was having a hard time parsing what you gave me.

If I may, I have another question now. Tell me if I need a new thread or anything else.  I'm trying to poll the keyboard for a keypress. Basically..instead of needing to "press enter to continue" I just want to poll most any one keypress.  I searched and saw dedndave's procedure but cannot get it to work for some reason.   I then tried using invoke WaitForSingleObject, STD_INPUT, 0FFFFFFFFh ....which works great, but leaves the keypress in the buffer. So, after my call to this function, I clear the screen and output a menu...the keypress is recorded in the place I ask the user to choose a menu item.  I then searched for functions to clear that from the buffer. I thought invoke FlushConsoleInputBuffer would work with the correct handle...but it doesn't seem to.   Does anyone have an idea of how I could keep that keypress from being recorded?

qWord

Quote from: henry.chris on March 02, 2013, 05:57:30 AMDoes anyone have an idea of how I could keep that keypress from being recorded?
As usual there are several ways, but the simplest is probably to use the CRT function _getch():
invoke GetStdHandle,STD_INPUT_HANDLE
invoke FlushConsoleInputBuffer,eax
invoke crt__getch ; reads one char. from input, but does not echo it
MREAL macros - when you need floating point arithmetic while assembling!

Zen

My all-time favorite means of Process Termination is: Bug Check,...this is especially satisfying if you are drunk.
Here is the MSDN documentation: KeBugCheck routine
Zen

dedndave


henry.chris

Ok, _getch it is, I tried it before when trying to implement your proc Dedndave...could not get it to work for some reason.
I'll try the bug check routine also just to see what it does.  Thank you all for your time. 

dedndave

it may have something to do with the fact it is being called from another thread
i am no C expert, but i think there is a "thread-safe" version of MSVCRT that you can use
one of the C guys may be able to help you more

an alternate approach is to use the keyboard polling routine in a "round-robin" style loop
that way, you don't have to start another thread

MichaelW

Per MSDN "These functions lock the calling thread and are therefore thread-safe."

http://msdn.microsoft.com/en-US/library/078sfkak(v=vs.80).aspx

But the source from the PSDK uses #ifdef _MT to determine whether to lock or not, so the only way to know for sure is to trace it in a debugger (this under Windows XP):

77C2EAA1   8BFF             MOV EDI,EDI   ; ntdll.7C910228
77C2EAA3   56               PUSH ESI
77C2EAA4   6A 03            PUSH 3
77C2EAA6   E8 10BB0000      CALL msvcrt._lock
77C2EAAB   E8 95FDFFFF      CALL msvcrt.77C2E845
77C2EAB0   6A 03            PUSH 3
77C2EAB2   8BF0             MOV ESI,EAX
77C2EAB4   E8 60BA0000      CALL msvcrt._unlock
77C2EAB9   59               POP ECX
77C2EABA   59               POP ECX
77C2EABB   8BC6             MOV EAX,ESI
77C2EABD   5E               POP ESI
77C2EABE   C3               RETN



Well Microsoft, here's another nice mess you've gotten us into.