The MASM Forum

Projects => Rarely Used Projects => RosAsm => Topic started by: guga on June 24, 2014, 10:57:34 AM

Title: How to retrieve the exit code from a dll´s caller ?
Post by: guga on June 24, 2014, 10:57:34 AM
Hi guys, how to safelly close an application from a dll ?

I mean, i´m making some separated libraries for usage  in RosAsm.exe. One of the library is called "RosMem.dll" that is responsable for memory managment of RosAsm memory usage.

Inside RosMem.dll i want to insert a "kernel32.ExitProcess" to close the main RosAsm.exe that called that dll, but how to retrieve the exit code of the executable file ?

I mean, if i place call 'kernel32.ExitProcess' 0 from the dll it will close the caller (RosAsm.exe) too ?

Also...what happens if there are other instances of RosAsm opened at the same time that also uses this dll ?

This is because i can have more then 01 Instance of RosAsm.exe which i´m testing for a specific reason (Ex: One i may debugging a app and the other instance i may use to create a resource or load a lib file etc)...
But...let´s say that on instance 1 (The rosasm i´m using for debug) i find a bug from where i need to terminate only this process using RosMem.dll and not using kernel32.ExitProcess inside the main executable ?

I read on the forum about using KeBugCheck but i think it is not the case here, since i don´t want the system hang, i want only that the main executable safely terminate (Even if i have other instance of the executable running)

For example if i get the handle from the main dll proc (hInstance) can i use GetExitCodeProcess to close only this caller ?

Ex: mine dll starts with



[hCallerInstance: D$ 0]

Proc Main:
    Arguments @Instance, @Reason, @Reserved

        move D$hCallerInstance D@Instance                  ; Not used here...

        If D@Reason = &DLL_PROCESS_ATTACH
            ; ...
            ; I first thought it was possible to call to 'RandomizeTimer' initialisation
            ; from here, but it is *not*. You can only do simple initialisations tasks,
            ; and the GetTickCount api can't be call at load time. So, the user has to
            ; make a call to 'RandomizeTimer' by himself, if he wants the values to be
            ; different at each run.
            ;
            ; There is now a simple x86 instruction that does it as well:

     ;;;    RDTSC

            ; But, as the "Read Time-Stamp Counter" Instruction was introduced into
            ; the Intel Architecture in the Pentium processor, i perfer the
            ; 'RandomizeTimer' Routine available for runing on older Computers.


        Else_If D@Reason = &DLL_PROCESS_DETACH
            ; ...

        Else_If D@Reason = &DLL_THREAD_ATTACH
            ; ...

        Else_If D@Reason = &DLL_THREAD_DETACH
            ; ...

        End_If

        mov eax &TRUE
EndP


Can i use this routine inside a export function on that dll like:

[ExitCode: D$ 0]

Proc MyFunction:: ;<---- double "::" means it is used as an export in RosAsm (On this case, the export is on a dll)
(....)
call 'kernel32.GetExitCodeProcess' D$hCallerInstance, ExitCode
call 'kernel32.ExitProcess' D$ExitCode
EndP



Is it going to close one instance of RosAsm.exe (or any other app that used RosMem.dll) and leave other instance intact (that also uses the dll) ? Or it will terminate both apps, just because they use the same dll ?
Title: Re: How to retrieve the exit code from a dll´s caller ?
Post by: dedndave on June 24, 2014, 11:26:02 AM
i think i would have the DLL set a flag
then examine the flag in the main process   :P
Title: Re: How to retrieve the exit code from a dll´s caller ?
Post by: guga on June 24, 2014, 01:02:57 PM
That would be easier  :biggrin:

But the problem is that if others wants to use the dll in their own apps they will need to check for this flag as many times they use some functions.

I ended up creating a safe function that can terminate the process opened by another instance. (Though it works only on WinXp or above - i´ll fix that later to work on prior windows versions:)

The function to is:

Proc SafeExitProcess::
    Arguments @hwnd
    Local @pId, @hProcess, @ExitCode
    Uses ebx

    call 'Oleacc.GetProcessHandleFromHwnd' D@hwnd
    mov D@hProcess eax

    mov D@ExitCode 0
    lea ebx D@ExitCode
    call GetExitCodeSmart D@hProcess, ebx

    call 'Kernel32.ExitProcess' D@ExitCode

EndP


Proc GetExitCodeSmart:
    Arguments @hProcess, @pExitCode

    mov D@pExitCode 0
    lea ebx D@pExitCode
    call 'kernel32.GetExitCodeProcess' D@hProcess, ebx
    ...If D@pExitCode <> &STILL_ACTIVE
        mov eax &TRUE
    ...Else
        ; Check if process is still alive
        call 'kernel32.WaitForSingleObject' D@hProcess, 0
        If eax = &WAIT_OBJECT_0
            mov eax &TRUE
        Else_If eax = &WAIT_TIMEOUT
            xor eax eax
        Else
            mov eax 0-1 ; Error
        End_If
    ...End_If

EndP



The function is called like:

Proc WndProc:
    Arguments @hWnd, @Message, @wParam, @lParam

        pushad

            .If D@Message = &WM_CLOSE
                call 'USER32.DestroyWindow' D@hWnd

            Else_If D@Message = &WM_DESTROY
                call 'User32.PostQuitMessage' 0

            Else_If D@Message = &WM_COMMAND
(..)
                    call 'DllClose.SafeExitProcess' D@hWnd
            Else
                popad
                call 'User32.DefWindowProcA' D@hWnd, D@Message, D@wParam, D@lParam
                ExitP

            .End_If

    popad | mov eax &FALSE
EndP


It seems to work as expected. I can have multiple instances of the app that it will close only the instance that called SafeExitProcess function


On the example i provided. Just click any of the menus, to it shows the messagebox and it will close the window after that.