; $Id$
;
; Micro stub for <app> -> <app>.exe forwarding, nasm version.
;
; Build Instructions:
;   Stantard version:
;       nasm -f obj -o ldstub-nasm.o ldstub-nasm.asm
;       ilink /pmtype:vio /ALIGN:1 /OUT:ldstub.bin ldstub-nasm.obj ldstub.def os2386.lib
;
; OVERLAY may be defined for execv()/spawnv(OVERLAY,..) is to be emulated.
;
; InnoTek Systemberatung GmbH Confidential
;
; Copyright (c) 2003 InnoTek Systemberatung GmbH
; Author: knut st. osmundsen <bird@anduin.net>
;
; All Rights Reserved
;
;


;*******************************************************************************
;* Global Variables                                                            *
;*******************************************************************************
extern DosExecPgm
extern DosQueryModuleName


;*******************************************************************************
;* Segment definitions                                                         *
;*******************************************************************************
segment TEXT32 public align=1 use32 FLAT class=CODE FLAT
segment STACK32 stack align=16 use32 class=STACK FLAT


;*******************************************************************************
;* Structures and Typedefs                                                     *
;*******************************************************************************
segment TEXT32  ; works around warning and dummy 'text' segment.
struc RESC
    .codeTerminate	resd 1
    .codeResult     resd 1
endstruc


; Program startup registers are defined as follows. 
;    EIP = Starting program entry address. 
;    ESP = Top of stack address. 
;    CS = Code selector for base of linear address space. 
;    DS = ES = SS = Data selector for base of linear address space. 
;    FS = Data selector of base of Thread Information Block (TIB). 
;    GS = 0. 
;    EAX = EBX = 0. 
;    ECX = EDX = 0. 
;    ESI = EDI = 0. 
;    EBP = 0.   
;    [ESP+0] = Return address to routine which calls DosExit(1,EAX). 
;    [ESP+4] = Module handle for program module. 
;    [ESP+8] = Reserved. 
;    [ESP+12] = Environment data object address. 
;    [ESP+16] = Command line linear address in environment data object. 
;
; @remark   I don't care about cleaning up arguments as the leave does so.
;
segment TEXT32
start:
..start:
    BITS 32
    enter 260 + 4 + RESC_size, 0
%define achNewExeName   ebp - 260 - RESC_size - 4  ; == esp right now
%define res             ebp - RESC_size    
    
    ;
    ; Get the executable name.
    ;
    ; ULONG DosQueryModuleName(HMODULE hmod, ULONG ulNameLength, PCHAR pNameBuf);
    ;   
    mov     ebx, esp                    ; esp=achNewExeName
    push    ebx                         ; pNameBuf
    push    260                         ; ulNameLength
    push    dword [ebp+8]               ; hmod
    call    DosQueryModuleName
    or      eax, eax
    jnz     .exec_failed                ; this ain't supposed to happen

    ;
    ; Append .EXE to the module name.
    ;
    xor     ecx, ecx
    dec     ecx
    mov     edi, ebx                    ; achNewExeName
    repne scasb
    mov     dword [edi-1], 'EXE.'
    mov     dword [edi+3], esi          ; esi = 0 at this point.

    ;
    ; Try execute the .EXE appended module name.
    ;
    ; APIRET APIENTRY DosExecPgm(PCHAR pObjname,
    ;                            LONG cbObjname,
    ;                            ULONG execFlag,
    ;                            PCSZ  pArg,
    ;                            PCSZ  pEnv,
    ;                            PRESULTCODES pRes,
    ;                            PCSZ  pName);
    ;
    push    ebx                         ; pName (achNewExeName)
    lea     edi, [res]
    push    edi                         ; pRes
    push    dword [ebp + 10h]           ; pEnv
    push    dword [ebp + 14h]           ; pArg
%ifdef OVERLAY
    push    1                           ; execFlag = EXEC_ASYNC
%else
    push    esi                         ; execFlag = EXEC_SYNC = 0
%endif    
    push    esi                         ; cbObjname
    push    esi                         ; pObjname
    call    DosExecPgm
    or      eax, eax
    jz      .exec_success
    
.exec_failed:
    mov     eax, 07fh
    jmp     .done
    
.exec_success:        
%ifndef OVERLAY
    ;
    ; Retrieve the result code.
    ;
    mov     eax, [res + RESC.codeResult]
    cmp     [res + RESC.codeTerminate], esi
    jz      .done
    
    ;
    ; Something bad happend and the result code is 0.
    ; We shouldn't return 0 when we trap, crash or is killed.
    ; 
    mov     eax, 0ffh
%endif            


.done:
    leave   
    ret    


; for emxomfld
ABSOLUTE 0
global WEAK$ZERO
WEAK$ZERO:
     
