home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
caway349.zip
/
SOURCE
/
ALL
/
API.ASM
< prev
next >
Wrap
Assembly Source File
|
1999-11-01
|
171KB
|
8,870 lines
.386
_apiCode segment para 'API CODE' use32
assume cs:_apiCode, ds:_apiCode
_apiCodeStart label byte
;*******************************************************************************
;Put carry into return carry.
;*******************************************************************************
cwAPI_C2C macro
push eax
pushfd
pushfd
pop eax
and al,1
cwAPI_AL2C
popfd
pop eax
endm
;*******************************************************************************
;Put carry into return carry.
;*******************************************************************************
cwAPI_AL2C macro
local __0, __1
pushfd
assume ds:nothing
test cs:apiSystemFlags,1
jz __0
or b[ebp+Int_Flags16],al
jmp __1
__0: or b[ebp+Int_Flags32],al
__1: assume ds:_apiCode
popfd
endm
;*******************************************************************************
;Call old int 31h handler.
;*******************************************************************************
cwAPI_CallOld macro
local __0, __1
assume ds:nothing
test cs:apiSystemFlags,1
jz __0
pushf
db 66h
call cs:f[OldIntSys] ;pass it onto previous handler.
jmp __1
__0: pushfd
call cs:f[OldIntSys] ;pass it onto previous handler.
__1: assume ds:_apiCode
endm
;*******************************************************************************
;Convert character in AL to upper case.
;*******************************************************************************
UpperChar macro
local __0
cmp al,61h ; 'a'
jb __0
cmp al,7Ah ; 'z'
ja __0
and al,5Fh ;convert to upper case.
__0: ;
endm
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;This must be just before cwAPIpatch
;
cwIdentity db "CAUSEWAY"
cwMajorVersion db 0
cwMinorVersion db 0
;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;CW API int 31h patch.
;
cwAPIpatch proc near
pushm ds,es,fs,gs ;Preserve all registers.
pushad ;/
mov ebp,esp ;Make registers addressable.
;
;Check if we're allowed to interfere.
;
push ds
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp Int21hExecCount,0
assume ds:_apiCode
pop ds
jnz @@Nope
;
;Check if this is a CauseWay function.
;
cmp ah,255
jz @@Ours
;
;Scan the table of other relavent functions.
;
mov edi,offset apiExtraCallTable+2
@@extra: cmp cs:w[edi-2],0
jz @@Nope
cmp ax,cs:w[edi-2]
jz @@GotCall
add edi,4+2
jmp @@extra
;
;An internal funtion? so point to table entry.
;
@@Ours: movzx edi,al
shl edi,2
add edi,offset apiCallTable
;
;Check if final call is still going to pass control to the old handler.
;
@@GotCall: cmp cs:d[edi],0
jz @@Nope
;
;See about turning interrupts back on.
;
mov esi,Int_Flags32
assume ds:nothing
test cs:apiSystemFlags,1 ;/
assume ds:_apiCode
jz @@32bit0 ;/
movzx ebp,bp ;/
mov esi,Int_Flags16
@@32Bit0: and ss:b[ebp+esi],not 1 ;clear carry.
cld ;Default direction.
test ss:w[ebp+esi],1 shl 9 ;Were interrupts enabled?
jz @@NoInts
sti ;Turn interrupts back on.
;
;Call the function handler.
;
@@NoInts: assume ds:nothing
call cs:d[edi] ;Pass control to handler.
assume ds:_apiCode
popad ;\
popm ds,es,fs,gs ;Restore all registers.
assume ds:nothing
test cs:apiSystemFlags,1
assume ds:_apiCode
jz @@32Bit1
iret
@@32Bit1: iretd ;Return to caller.
;
;Not an internal function or anything we want to interfere with so pass control
;to origional handler.
;
@@Nope: popad ;Restore registers.
popm ds,es,fs,gs
assume ds:nothing
test cs:apiSystemFlags,1
jz @@n32
db 66h
@@n32: jmp cs:f[OldIntSys] ;pass it onto previous handler.
assume ds:_apiCode
;
OldIntSys df 0
;
APICallTable dd cwAPI_Info ;00
dd cwAPI_IntXX ;01
dd cwAPI_FarCallReal ;02
dd cwAPI_GetSel ;03
dd cwAPI_RelSel ;04
dd cwAPI_CodeSel ;05
dd cwAPI_AliasSel ;06
dd cwAPI_GetSelDet ;07
;
dd cwAPI_GetSelDet32 ;08
dd cwAPI_SetSelDet ;09
dd cwAPI_SetSelDet32 ;0A
dd cwAPI_GetMem ;0B
dd cwAPI_GetMem32 ;0C
dd cwAPI_ResMem ;0D
dd cwAPI_ResMem32 ;0E
dd cwAPI_RelMem ;0F
;
dd cwAPI_GetMemLinear ;10
dd cwAPI_GetMemLinear32 ;11
dd cwAPI_ResMemLinear ;12
dd cwAPI_ResMemLinear32 ;13
dd cwAPI_RelMemLinear ;14
dd cwAPI_RelMemLinear32 ;15
dd cwAPI_GetMemNear ;16
dd cwAPI_ResMemNear ;17
;
dd cwAPI_RelMemNear ;18
dd cwAPI_Linear2Near ;19
dd cwAPI_Near2Linear ;1A
dd cwAPI_LockMem ;1B
dd cwAPI_LockMem32 ;1C
dd cwAPI_UnLockMem ;1D
dd cwAPI_UnLockMem32 ;1E
dd cwAPI_LockMemNear ;1F
;
dd cwAPI_UnLockMemNear ;20
dd cwAPI_GetMemDOS ;21
dd cwAPI_ResMemDOS ;22
dd cwAPI_RelMemDOS ;23
dd cwAPI_Exec ;24
dd cwAPI_GetDOSTrans ;25
dd cwAPI_SetDOSTrans ;26
dd cwAPI_GetMCBSize ;27
;
dd cwAPI_SetMCBSize ;28
dd cwAPI_GetSels ;29
dd cwAPI_cwLoad ;2A
dd cwAPI_cwcInfo ;2B
dd cwAPI_GetMemSO ;2C
dd cwAPI_ResMemSO ;2D
dd cwAPI_RelMemSO ;2E
dd cwAPI_UserDump ;2F
; dd 16 dup (0) ;30-3F
dd cwAPI_SetDump ; 30
dd cwAPI_UserErrTerm ; 31
dd cwAPI_CWErrName ; 32
dd 13 dup (0) ;33-3F
dd 16 dup (0) ;40-4F
dd 16 dup (0) ;50-5F
dd 16 dup (0) ;60-6F
dd 16 dup (0) ;70-7F
;
dd 16*7 dup (0) ;80-EF
;
dd 8 dup (0) ;F0-F7
;
dd 0 ;F8
dd cwAPI_ID ;F9
dd cwAPI_GetPatch ;FA
dd cwAPI_cwcLoad ;FB
dd cwAPI_LinearCheck ;FC
dd cwAPI_ExecDebug ;FD
dd cwAPI_Cleanup ;FE
dd 0 ;FF
;
apiExtraCallTable label byte
dw 0600h
dd dpmiAPI_Lock
dw 0601h
dd dpmiAPI_UnLock
dw 0303h
dd dpmiAPI_GetCallBack
dw 0304h
dd dpmiAPI_RelCallBack
dw 0
cwAPIpatch endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;AX = 0600h
;BX:CX = Starting linear address of memory to lock
;SI:DI = Size of region to lock in bytes
;
dpmiAPI_Lock proc near
mov ax,[ebp+Int_AX]
mov bx,[ebp+Int_BX]
mov cx,[ebp+Int_CX]
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
pushad
shl ebx,16
mov bx,cx
shl esi,16
mov si,di
mov edx,ebx
mov ecx,esi
mov ax,Res_LOCK
call RegisterResource
popad
cwAPI_CallOld
cwAPI_C2C
jnc @@0
mov [ebp+Int_AX],ax
@@0: ret
dpmiAPI_Lock endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;AX = 0601h
;BX:CX = Starting linear address of memory to unlock
;SI:DI = Size of region to unlock in bytes
;
dpmiAPI_UnLock proc near
mov ax,[ebp+Int_AX]
mov bx,[ebp+Int_BX]
mov cx,[ebp+Int_CX]
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
pushad
shl ebx,16
mov bx,cx
shl esi,16
mov si,di
mov edx,ebx
mov ecx,esi
mov ax,Res_LOCK
call ReleaseResource
popad
cwAPI_CallOld
cwAPI_C2C
jnc @@0
mov [ebp+Int_AX],ax
@@0: ret
dpmiAPI_UnLock endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;AX = 0303h
;DS:(E)SI = Selector:Offset of procedure to call
;ES:(E)DI = Selector:Offset of real mode call structure
;
;Returns
;
;If function was successful:
;Carry flag is clear.
;CX:DX = Segment:Offset of real mode call address
;
dpmiAPI_GetCallBack proc near
mov ax,[ebp+Int_AX]
mov ds,[ebp+Int_DS]
mov esi,[ebp+Int_ESI]
mov es,[ebp+Int_ES]
mov edi,[ebp+Int_EDI]
cwAPI_CallOld
cwAPI_C2C
jc @@9
;
mov [ebp+Int_CX],cx
mov [ebp+Int_DX],dx
;
shl ecx,16
mov cx,dx
mov edx,ecx
mov ecx,esi
xor ebx,ebx
mov bx,ds
mov ax,Res_CALLBACK
call RegisterResource
;
@@9: ret
dpmiAPI_GetCallBack endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;AX = 0304h
;CX:DX = Real mode call-back address to free
;
dpmiAPI_RelCallBack proc near
mov ax,[ebp+Int_AX]
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
cwAPI_CallOld
cwAPI_C2C
jc @@9
;
shl ecx,16
mov cx,dx
mov edx,ecx
mov ax,Res_CALLBACK
call ReleaseResource
;
@@9: ret
dpmiAPI_RelCallBack endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Call user termination routine on exception
;
;On Entry:
;
; AX = 0ff31h
; CL = 0 if 16-bit termination routine
; CL = nonzero if 32-bit termination routine
; DS:[E]SI = user termination routine address, if ES is zero or an invalid
; selector value, then the user termination routine call is removed
; ES:[E]DI = user information dump area
;
;Returns:
;
; None
;
cwAPI_UserErrTerm PROC NEAR
mov ds,cs:apiDSeg
assume ds:_cwMain
mov UserTermFlag,0 ; initialize flag
mov dx,[ebp+Int_DS]
lsl ax,dx
jnz uetret ; invalid selector
mov al,[ebp+Int_CL] ; get bitness flag
test al,al
setne al ; 0 if 0, 1 if nonzero
inc ax ; 1 if 16-bit, 2 if 32-bit
mov UserTermFlag,al
cmp al,1 ; see if 16-bit
jne uet32 ; no
mov ax,[ebp+Int_SI]
mov WORD PTR UserTermRoutine,ax
mov WORD PTR UserTermRoutine+2,dx
mov ax,[ebp+Int_DI]
mov WORD PTR UserTermDump,ax
mov ax,[ebp+Int_ES]
mov WORD PTR UserTermDump+2,ax
jmp uetret
uet32:
mov eax,[ebp+Int_ESI]
mov DWORD PTR UserTermRoutine,eax
mov WORD PTR UserTermRoutine+4,dx
mov eax,[ebp+Int_EDI]
mov DWORD PTR UserTermDump,eax
mov ax,[ebp+Int_ES]
mov WORD PTR UserTermDump+4,ax
uetret:
ret
cwAPI_UserErrTerm ENDP
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Disable/enable error display and CW.ERR creation
;
;On Entry:
;
; AX = 0ff30h
; CL = 0, disable error display and CW.ERR file creation
; CL = nonzero, enable error display and CW.ERR file creation
;
;Returns:
;
; None
;
cwAPI_SetDump PROC NEAR
mov ds,cs:apiDSeg
assume ds:_cwMain
mov al,[ebp+Int_CL]
mov EnableDebugDump,al
ret
cwAPI_SetDump ENDP
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
; change CW.ERR file name, with optional path/drivespec
;
;On Entry:
;
; AX = 0ff32h
; CX:[E]DX = new CW.ERR ASCIIZ file name
;
;Returns:
;
; None
;
cwAPI_CWErrName PROC NEAR
mov ds,cs:apiDSeg
assume ds:_cwMain
mov edx,[ebp+Int_EDX]
test cs:apiSystemFlags,1
jz cen2
movzx edx,dx ; 16-bit, zero high word of edx
cen2:
mov ax,[ebp+Int_CX]
mov es,ax
mov ebx,OFFSET NewCWErrName ; ds:ebx -> destination, es:edx -> source
mov cx,80 ; don't allow more than 80 chars in file name
cenloop:
mov al,es:[edx]
test al,al
je centerm ; at null terminator
mov ds:[ebx],al
inc edx
inc ebx
dec cx
jne cenloop
centerm:
mov BYTE PTR ds:[ebx],0
ret
cwAPI_CWErrName ENDP
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Setup user buffer display in CW.ERR file
;
;On Entry:
;
; AX = 0ff2fh
; ES:[E]DI -> user buffer to display in CW.ERR
; CX = count of bytes to display from buffer in CW.ERR
; BL = 'A' if ASCII dump (non-binary display of bytes, control characters
; display as periods)
; BH = nonzero if preset ASCII buffer to word value, ignored for non-ASCII
; DX = word value to fill ASCII dump buffer if BH is nonzero, ignored
; for non-ASCII
;
;Returns:
;
; Carry set on ASCII dump invalid buffer address
;
cwAPI_UserDump PROC NEAR
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ax,[ebp+Int_ES]
verr ax
jnz udfail ; can't read to user selector
mov DebugUserSel,ax
mov es,ax
mov edi,[ebp+Int_EDI]
xor eax,eax
mov ax,es
lsl eax,eax
cmp eax,10000h
jnc @@0
movzx edi,di
@@0:
mov DebugUserOff,edi
mov cx,[ebp+Int_CX]
mov DebugUserCount,cx
; check for out of bounds
movzx edx,cx
add edx,edi
jc udfail
dec edx ; make relative 0
xor eax,eax
mov ax,es
lsl eax,eax
cmp eax,edx
jb udfail
mov al,[ebp+Int_BL]
cmp al,'A'
je aflag
xor al,al
aflag:
mov DebugAsciiFlag,al
test al,al
je udret ; if not ASCII then no fill
mov al,[ebp+Int_BH] ; check fill flag
test al,al ; no fill, carry flag reset by default
je udret
; fill the allocation with value in dx to count specified in cx
mov ax,es
verw ax
jnz udfail ; can't write to user selector
mov ax,[ebp+Int_DX]
push ax
push ax
pop eax
push ecx
shr ecx,1
rep stosd
pop ecx
and cx,3
je udsuccess
mov es:[edi],al ; finish off remainder bytes
dec cx
je udsuccess
inc edi
mov es:[edi],ah
dec cx
je udsuccess
inc edi
mov es:[edi],al
udsuccess:
clc ; flag success
jmp udret
udfail:
mov DebugUserCount,0
stc ; flag failure
udret:
cwAPI_C2C
ret
cwAPI_UserDump ENDP
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get CauseWay identifier, return PageDIRLinear and Page1stLinear info
;
;Returns:
;
;EDX - Linear address of patch table.
;
cwAPI_ID proc near
push ds
assume ds:nothing
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
mov esi,PageDIRLinear
mov edi,Page1stLinear
pop ds
mov ecx,"CAUS"
mov edx,"EWAY"
mov [ebp+Int_ESI],esi
mov [ebp+Int_EDI],edi
mov [ebp+Int_EDX],edx
mov [ebp+Int_ECX],ecx
xor al,al
cwAPI_AL2C
ret
cwAPI_ID endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get patch table address.
;
;Returns:
;
;EDX - Linear address of patch table.
;
cwAPI_GetPatch proc near
assume ds:nothing
mov bx,cs:apiDDSeg
sys GetSelDet32
add edx,offset PatchTable
assume ds:_apiCode
mov [ebp+Int_EDX],edx
xor al,al
cwAPI_AL2C
ret
cwAPI_GetPatch endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get address of transfer buffer.
;
;Returns:
;
;BX - Real mode segment
;DX - Protected mode selector.
;ECX - Buffer size.
;
cwAPI_GetDOSTrans proc near
assume ds:nothing
mov es,cs:apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
assume ds:_apiCode
mov ax,es:w[EPSP_TransReal]
mov [ebp+Int_BX],ax
mov ax,es:w[EPSP_TransProt]
mov [ebp+Int_DX],ax
mov eax,es:d[EPSP_TransSize]
mov [ebp+Int_ECX],eax
ret
cwAPI_GetDOSTrans endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Set real mode transfer buffer address.
;
;On Entry:
;
;BX - Real mode segment.
;DX - Protected mode selector.
;ECX - Buffer size.
;
cwAPI_SetDOSTrans proc near
mov bx,[ebp+Int_BX]
mov dx,[ebp+Int_DX]
mov ecx,[ebp+Int_ECX]
assume ds:nothing
mov es,cs:apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
assume ds:_apiCode
mov es:w[EPSP_TransReal],bx
mov es:w[EPSP_TransProt],dx
cmp ecx,10000h
jc @@0
mov ecx,65535
@@0: mov es:d[EPSP_TransSize],ecx
ret
cwAPI_SetDOSTrans endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get various useful variable contents.
;
;Returns:
;
;AX - 0-4G selector.
;BX - Current PSP selector.
;ECX - Transfer buffer size.
;DX - Transfer buffer real mode segment.
;ESI - Transfer buffer offset.
;DI - System flags.
;ES - Transfer buffer protected mode selector.
;
cwAPI_Info proc near
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov di,w[SystemFlags]
mov ax,RealSegment
mov bx,PspSegment
mov es,bx
mov dx,es:w[EPSP_TransReal]
mov ecx,es:d[EPSP_TransSize]
mov es,es:w[EPSP_TransProt]
xor esi,esi
assume ds:_apiCode
mov [ebp+Int_AX],ax
mov [ebp+Int_BX],bx
mov [ebp+Int_ECX],ecx
mov [ebp+Int_DX],dx
mov [ebp+Int_ESI],esi
mov [ebp+Int_DI],di
mov [ebp+Int_ES],es
ret
cwAPI_Info endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Pass control to a real mode interrupt handler.
;
;On Entry:
;
;BL - INT number.
;ES:[E]DI - Real mode register structure.
;
cwAPI_IntXX proc near
mov edi,[ebp+Int_EDI]
mov es,[ebp+Int_ES]
; mov bl,[ebp+Int_BL]
xor eax,eax
mov ax,es
lsl eax,eax
cmp eax,10000h
jnc @@0
movzx edi,di
@@0: assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp ProtectedType,2
assume ds:_apiCode
jnz @@NoStack0
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
sub DPMIStackOff,RawStackDif
mov ax,DPMIStackOff
add ax,RawStackDif
mov es:Real_SP[edi],ax
mov ax,DPMIStackSeg
mov es:Real_SS[edi],ax
; MED 05/23/96
test cs:apiSystemFlags,1
jz medUse32Bit8
mov ebx,Int_Flags16
jmp medUse16Bit8
medUse32Bit8:
mov ebx,Int_Flags32
medUse16Bit8:
mov ax,ss:[ebp+ebx]
and ax,1111110011111111b ;clear Trap and INT flag.
mov es:Real_Flags[edi],ax ; explicitly set flags on DPMI 300h call
assume ds:_apiCode
jmp @@DoneStack0
@@NoStack0:
mov es:Real_SP[edi],0 ;use DPMI provided stack.
mov es:Real_SS[edi],0
@@DoneStack0:
xor cx,cx ;No stack parameters.
mov bh,ch ;no flags.
mov bl,ss:[ebp+Int_BL] ; MED 05/23/96
mov ax,0300h
cwAPI_CallOld
cwAPI_C2C
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp ProtectedType,2
assume ds:_apiCode
jnz @@DoneStack1
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
add DPMIStackOff,RawStackDif
assume ds:_apiCode
@@DoneStack1: assume ds:nothing
test cs:apiSystemFlags,1
assume ds:_apiCode
jz @@Use32Bit8
mov ebx,Int_Flags16
jmp @@Use16Bit8
@@Use32Bit8: mov ebx,Int_Flags32
@@Use16Bit8: mov ax,ss:[ebp+ebx]
and ax,0000011000000000b ;retain IF.
and es:Real_Flags[edi],1111100111111111b ;lose IF.
or es:Real_Flags[edi],ax
ret
cwAPI_IntXX endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Pass control to a real mode far routine.
;
;On Entry:
;
;ES:[E]DI - Real mode register structure.
;
cwAPI_FarCallReal proc near
mov edi,[ebp+Int_EDI]
mov es,[ebp+Int_ES]
xor eax,eax
mov ax,es
lsl eax,eax
cmp eax,10000h
jnc @@0
movzx edi,di
@@0: pushf
pop es:Real_Flags[edi]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp ProtectedType,2
assume ds:_apiCode
jnz @@NoStack1
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
sub DPMIStackOff,RawStackDif
mov ax,DPMIStackOff
add ax,RawStackDif
mov es:Real_SP[edi],ax
mov ax,DPMIStackSeg
mov es:Real_SS[edi],ax
assume ds:_apiCode
jmp @@DoneStack2
@@NoStack1: mov es:Real_SP[edi],0 ;use DPMI provided stack.
mov es:Real_SS[edi],0
@@DoneStack2: xor cx,cx ;No stack parameters.
xor bx,bx ;no flags.
mov ax,0301h
cwAPI_CallOld
cwAPI_C2C
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp ProtectedType,2
assume ds:_apiCode
jnz @@DoneStack3
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
add DPMIStackOff,RawStackDif
assume ds:_apiCode
@@DoneStack3: ;
assume ds:nothing
test cs:apiSystemFlags,1
assume ds:_apiCode
jz @@Use32Bit8
mov ebx,Int_Flags16
jmp @@Use16Bit8
@@Use32Bit8: mov ebx,Int_Flags32
@@Use16Bit8: mov ax,ss:[ebp+ebx]
and ax,0000011000000000b ;retain IF.
and es:Real_Flags[edi],1111100111111111b ;lose IF.
or es:Real_Flags[edi],ax
ret
cwAPI_FarCallReal endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate a selector.
;
;Returns:
;
;Carry set on error (no more selectors) else,
;
;BX - new selector.
;
cwAPI_GetSel proc near
xor eax,eax
xor ebx,ebx
call _SetSelector
cwAPI_C2C
jc @@9
mov [ebp+Int_BX],bx
@@9: ret
cwAPI_GetSel endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate multiple selectors.
;
;On Entry:
;
;CX - Number of selectors.
;
;Returns:
;
;Carry set on error (not enough selectors) else,
;
;BX - Base selector.
;
cwAPI_GetSels proc near
;
;Get selectors from DPMI.
;
mov cx,[ebp+Int_CX]
mov ax,0000h
cwAPI_CallOld
cwAPI_C2C
jc @@9
;
mov [ebp+Int_BX],ax
movzx edx,ax
movzx ecx,cx
mov ax,Res_SEL
@@0: call RegisterResource
add edx,8
dec ecx
jnz @@0
;
@@9: ret
cwAPI_GetSels endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release a selector.
;
;On Entry:
;
;BX - Selector to release.
;
cwAPI_RelSel proc near
mov bx,[ebp+Int_BX]
mov ds,[ebp+Int_DS]
mov es,[ebp+Int_ES]
mov fs,[ebp+Int_FS]
mov gs,[ebp+Int_GS]
call _RelSelector
cwAPI_C2C
jc @@9
mov [ebp+Int_DS],ds
mov [ebp+Int_ES],es
mov [ebp+Int_FS],fs
mov [ebp+Int_GS],gs
@@9: ret
cwAPI_RelSel endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Force a selector to be type CODE.
;
;On Entry:
;
;BX - Selector.
;
cwAPI_CodeSel proc near
mov bx,[ebp+Int_BX]
call _CodeSelector
cwAPI_C2C
ret
cwAPI_CodeSel endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate a selector with type DATA that maps same memory as another selector.
;
;On Entry:
;
;BX - selector.
;
;Returns:
;
;AX - New selector.
;
cwAPI_AliasSel proc near
mov ax,000ah
mov bx,[ebp+Int_BX]
cwAPI_CallOld
cwAPI_C2C
jc @@9
;
mov [ebp+Int_AX],ax
pushm eax,edx
movzx edx,ax
mov ax,Res_SEL
call RegisterResource
popm eax,edx
;
@@9: ret
cwAPI_AliasSel endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get selector base & limit.
;
;On Entry:
;
;BX - selector.
;
;Returns:
;
;CX:DX - Linear base.
;SI:DI - Byte granular limit.
;
cwAPI_GetSelDet proc near
mov bx,[ebp+Int_BX]
call _DetSelector
cwAPI_C2C
jc @@9
;
mov ecx,eax ;get base.
mov dx,cx
shr ecx,16
mov esi,ebx ;get limit.
mov di,si
shr esi,16
mov [ebp+Int_CX],cx
mov [ebp+Int_DX],dx
mov [ebp+Int_SI],si
mov [ebp+Int_DI],di
;
@@9: ret
cwAPI_GetSelDet endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get selector base & limit.
;
;On Entry:
;
;BX - selector.
;
;Returns:
;
;EDX - base
;ECX - limit
;
cwAPI_GetSelDet32 proc near
mov bx,[ebp+Int_BX]
call _DetSelector
cwAPI_C2C
jc @@9
;
mov [ebp+Int_EDX],eax
mov [ebp+Int_ECX],ebx
;
@@9: ret
cwAPI_GetSelDet32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Set selectors base & limit.
;
;On Entry:
;
;BX - selector
;CX:DX - Linear base.
;SI:DI - Byte granular limit.
;
cwAPI_SetSelDet proc near
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
shl ecx,16 ;Get base to somewhere useful.
mov cx,dx
mov eax,ecx
shl esi,16 ;get limit to somewhere useful.
mov si,di
mov ebx,esi
mov cx,[ebp+Int_BX]
call _SizeSelector
cwAPI_C2C
ret
cwAPI_SetSelDet endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Set a selectors details.
;
;On Entry:
;
;BX - selector
;EDX - base
;ECX - limit.
;
cwAPI_SetSelDet32 proc near
mov cx,[ebp+Int_BX]
mov eax,[ebp+Int_EDX]
mov ebx,[ebp+Int_ECX]
call _SizeSelector
cwAPI_C2C
ret
cwAPI_SetSelDet32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate some memory with a selector attatched.
;
;On Entry:
;
;CX:DX - Size of block required in bytes. (-1:-1 to get maximum memory size)
;
;On Exit:
;
;Carry clear if OK &
;
;BX - Selector to access the block with.
;
;Else if CX:DX was -1, CX:DX is size of largest block available.
;
cwAPI_GetMem proc near
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16
mov cx,dx
; MED 06/25/97
push ds ; test padding flag
mov ds,cs:apiDSeg
assume ds:_cwMain
test Pad1Flag,-1
pop ds
assume ds:nothing
je gm2 ; padding flag not turned on
test ecx,0ffff0000h
jne gm2 ; don't pad >64K allocation
add ecx,1023
and ecx,NOT 1023 ; pad to 1K-boundary allocation
gm2:
call mcbGetMemLinear32
jc @@2
sys GetSel
jc @@0
mov edx,esi
jecxz @@3
dec ecx ;limit=length-1
@@3: sys SetSelDet32
mov [ebp+Int_BX],bx
clc
jmp @@1
@@0: call mcbRelMemLinear32
stc
jmp @@1
;
@@2: mov dx,cx
shr ecx,16
mov ax,[ebp+Int_CX]
shl eax,16
mov ax,[ebp+Int_DX]
cmp eax,-2
jz @@5
cmp eax,-1
jnz @@4
@@5: mov [ebp+Int_CX],cx
mov [ebp+Int_DX],dx
@@4: stc
;
@@1: cwAPI_C2C
ret
cwAPI_GetMem endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate some memory and return selector:offset (16-bit).
;
;On Entry:
;
;CX:DX - Size of block required in bytes.
;
;On Exit:
;
;Carry set on error else,
;
;SI:DI - selector:offset of allocated memory.
;
cwAPI_GetMemSO proc near
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16
mov cx,dx
call mcbGetMemLinear32 ;allocate some memory.
jc @@9
assume ds:nothing
cmp cs:mcbLastChunk,0 ;DPMI memory?
assume ds:_apiCode
jnz @@1
;
;Allocate a selector for this memory.
;
sys GetSel
jc @@8
mov edx,esi
jecxz @@0
dec ecx ;limit=length-1
@@0: sys SetSelDet32
xor dx,dx
jmp @@7
;
;Get chunk's selector.
;
@@1: push es
assume ds:nothing
mov es,cs:apiDSeg
assume es:_cwMain
mov es,RealSegment
assume es:nothing
mov edi,cs:mcbLastChunk
assume ds:_apiCode
mov bx,es:[edi+mcbChunkSel] ;get chunk selector.
pop es
mov edx,esi
sub edx,edi ;get blocks offset.
;
@@7: mov [ebp+Int_SI],bx
mov [ebp+Int_DI],dx
clc
jmp @@9
;
@@8: call mcbRelMemLinear32
stc
;
@@9: cwAPI_C2C
ret
cwAPI_GetMemSO endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;On Entry:
;
;ECX - Size of block required in bytes. (-1 to get maximum memory size)
;
;On Exit:
;
;Carry clear if OK &
;
;BX - Selector to access the block with.
;
;Else if ECX was -1, ECX is size of largest block available.
;
cwAPI_GetMem32 proc near
mov ecx,[ebp+Int_ECX]
call mcbGetMemLinear32
jc @@2
sys GetSel
jc @@0
mov edx,esi
jecxz @@3
dec ecx ;limit=length-1
sys SetSelDet32
@@3: mov [ebp+Int_BX],bx
clc
jmp @@1
@@0: call mcbRelMemLinear32
stc
jmp @@1
;
@@2: cmp d[ebp+Int_ECX],-1
jz @@5
cmp d[ebp+Int_ECX],-2
jnz @@4
@@5: mov [ebp+Int_ECX],ecx
@@4: stc
;
@@1: cwAPI_C2C
ret
cwAPI_GetMem32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated block of memory.
;
;On Entry:
;
;BX - Selector for block.
;CX:DX - New size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK.
;
cwAPI_ResMem proc near
mov bx,[ebp+Int_BX]
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16 ;convert new size to 32-bit.
mov cx,dx
push ecx
sys GetSelDet32 ;Get selector base address.
mov esi,edx
pop ecx
jc @@9
call mcbResMemLinear32 ;re-size the memory.
jc @@9
mov edx,esi
dec ecx
sys SetSelDet32
@@9: cwAPI_C2C
ret
cwAPI_ResMem endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated block of memory.
;
;On Entry:
;
;SI:DI - Selector:offset for block.
;CX:DX - New size of block required in bytes.
;
;On Exit:
;
;Carry set on error else,
;
;SI:DI - selector:offset new block address.
;
cwAPI_ResMemSO proc near
mov ds,[ebp+Int_DS]
mov es,[ebp+Int_ES]
mov fs,[ebp+Int_FS]
mov gs,[ebp+Int_GS]
;
mov bx,w[ebp+Int_SI]
sys GetSelDet32 ;get selectors details.
jc @@9
mov esi,edx
movzx eax,w[ebp+Int_DI]
add esi,eax ;get memory blocks address.
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16 ;convert new size to 32-bit.
mov cx,dx
call mcbResMemLinear32 ;re-size the memory.
jc @@9
;
;Check new block type.
;
assume ds:nothing
cmp cs:mcbLastChunk,0 ;DPMI memory?
assume ds:_apiCode
jnz @@1
;
;Update selectors details.
;
mov edx,esi
dec ecx
sys SetSelDet32
xor dx,dx
jmp @@7
;
;Get chunk's selector.
;
@@1: push es
assume ds:nothing
mov es,cs:apiDSeg
assume es:_cwMain
mov es,RealSegment
assume es:nothing
mov edi,cs:mcbLastChunk
assume ds:_apiCode
mov bx,es:[edi+mcbChunkSel] ;get chunk selector.
pop es
mov edx,esi
sub edx,edi ;get blocks offset.
;
;Check if the old block had it's own selector.
;
cmp w[ebp+Int_DI],0 ;offset of zero?
jnz @@7
push bx
mov bx,w[ebp+Int_SI]
sys RelSel ;release the selector.
pop bx
;
@@7: mov [ebp+Int_SI],bx
mov [ebp+Int_DI],dx
clc
;
@@9: cwAPI_C2C
mov [ebp+Int_DS],ds
mov [ebp+Int_ES],es
mov [ebp+Int_FS],fs
mov [ebp+Int_GS],gs
ret
cwAPI_ResMemSO endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated block of memory.
;
;On Entry:
;
;BX - Selector for block.
;ECX - New size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK.
;
cwAPI_ResMem32 proc near
mov bx,[ebp+Int_BX]
mov ecx,[ebp+Int_ECX]
push ecx
sys GetSelDet32 ;Get selector base address.
mov esi,edx
pop ecx
jc @@9
call mcbResMemLinear32 ;re-size the memory.
jc @@9
mov edx,esi
dec ecx
sys SetSelDet32
@@9: cwAPI_C2C
ret
cwAPI_ResMem32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release previously allocated block of memory. Is be used for memory allocated
;by either GetMem or GetMem32.
;
;
;On Entry:
;
;BX - Selector for block to release.
;
cwAPI_RelMem proc near
mov bx,[ebp+Int_BX]
sys GetSelDet32 ;Get selector base address.
jc @@9
mov esi,edx
mov ds,[ebp+Int_DS]
mov es,[ebp+Int_ES]
mov fs,[ebp+Int_FS]
mov gs,[ebp+Int_GS]
sys RelSel ;release the selector.
mov [ebp+Int_DS],ds
mov [ebp+Int_ES],es
mov [ebp+Int_FS],fs
mov [ebp+Int_GS],gs
call mcbRelMemLinear32 ;release the memory.
@@9: cwAPI_C2C
ret
cwAPI_RelMem endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release block of memory allocated via GetMemSO.
;
;On Entry:
;
;SI:DI - Selector:offset for block to release.
;
cwAPI_RelMemSO proc near
;
;Zero any segment registers using this selector.
;
mov bx,w[ebp+Int_SI]
and bx,0ffffh-3
jz @@bad ; MED 11/18/96, screen out null pointer releases
xor cx,cx
mov ax,w[ebp+Int_DS]
and ax,0ffffh-3
cmp ax,bx
jnz @@0
mov w[ebp+Int_DS],cx
mov ds,cx
@@0: mov ax,w[ebp+Int_ES]
and ax,0ffffh-3
cmp ax,bx
jnz @@1
mov w[ebp+Int_ES],cx
mov es,cx
@@1: mov ax,w[ebp+Int_FS]
and ax,0ffffh-3
cmp ax,bx
jnz @@2
mov w[ebp+Int_FS],cx
mov fs,cx
@@2: mov ax,w[ebp+Int_GS]
and ax,0ffffh-3
cmp ax,bx
jnz @@3
mov w[ebp+Int_GS],cx
mov gs,cx
@@3: ;
mov bx,w[ebp+Int_SI]
sys GetSelDet32 ;get selectors details.
jc @@9
mov esi,edx
movzx eax,w[ebp+Int_DI]
add esi,eax ;get memory blocks address.
call mcbRelMemLinear32 ;release the memory.
;
;Check if block had it's own selector.
;
cmp w[ebp+Int_DI],0 ;offset of zero?
jnz @@4
mov bx,w[ebp+Int_SI]
sys RelSel ;release the selector.
;
@@4: clc
;
@@9: cwAPI_C2C
ret
; MED 11/18/96
@@bad:
stc
jmp @@9
cwAPI_RelMemSO endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate a block of memory without a selector.
;
;On Entry:
;
;CX:DX - Size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK &,
;
;SI:DI - Linear address of block allocated.
;
cwAPI_GetMemLinear proc near
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16
mov cx,dx
call mcbGetMemLinear32
jc @@9
mov di,si
shr esi,16
mov [ebp+Int_SI],si
mov [ebp+Int_DI],di
clc
@@9: cwAPI_C2C
ret
cwAPI_GetMemLinear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate a block of memory without a selector.
;
;On Entry:
;
;ECX - Size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK &,
;
;ESI - Linear address of block allocated.
;
cwAPI_GetMemLinear32 proc near
mov ecx,[ebp+Int_ECX]
call mcbGetMemLinear32
cwAPI_C2C
jc @@9
mov [ebp+Int_ESI],esi
@@9: ret
cwAPI_GetMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated block of memory without a selector.
;
;On Entry:
;
;SI:DI - Linear address of block to re-size.
;CX:DX - Size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK &,
;
;SI:DI - New linear address of block.
;
cwAPI_ResMemLinear proc near
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
mov cx,[ebp+Int_CX]
mov dx,[ebp+Int_DX]
shl ecx,16
mov cx,dx
shl esi,16
mov si,di
call mcbResMemLinear32
jc @@9
mov di,si
shr esi,16
mov [ebp+Int_SI],si
mov [ebp+Int_DI],di
clc
@@9: cwAPI_C2C
ret
cwAPI_ResMemLinear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated block of memory without a selector.
;
;On Entry:
;
;ESI - Linear address of block to re-size.
;ECX - Size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK &,
;
;ESI - New linear address of block.
;
cwAPI_ResMemLinear32 proc near
mov esi,[ebp+Int_ESI]
mov ecx,[ebp+Int_ECX]
call mcbResMemLinear32
jc @@9
mov [ebp+Int_ESI],esi
@@9: cwAPI_C2C
ret
cwAPI_ResMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release previously allocated block of memory (linear address).
;
;On Entry:
;
;SI:DI - Linear address of block to release.
;
;On Exit:
;
cwAPI_RelMemLinear proc near
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
shl esi,16
mov si,di
call mcbRelMemLinear32
cwAPI_C2C
ret
cwAPI_RelMemLinear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release previously allocated block of memory (linear address).
;
;On Entry:
;
;ESI - Linear address of block to release.
;
;On Exit:
;
cwAPI_RelMemLinear32 proc near
mov esi,[ebp+Int_ESI]
call mcbRelMemLinear32
cwAPI_C2C
ret
cwAPI_RelMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate an application relative block of memory.
;
;On Entry:
;
;EBX - Size of block required in bytes.
;
;On Exit:
;
;Carry clear if OK &,
;
;ESI - Application relative linear address of block allocated.
;
cwAPI_GetMemNear proc near
mov ecx,[ebp+Int_EBX]
call mcbGetMemLinear32
jc @@9
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
sub esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
mov [ebp+Int_ESI],esi
clc
@@9: cwAPI_C2C
ret
cwAPI_GetMemNear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a previously allocated application relative block of memory.
;
;On Entry:
;
;EBX - Size of block required in bytes.
;ESI - application relative linear address of block to re-size.
;
;On Exit:
;
;Carry clear if OK &,
;
;ESI - New application relative linear address of block.
;
cwAPI_ResMemNear proc near
mov ecx,[ebp+Int_EBX]
mov esi,[ebp+Int_ESI]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
add esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
call mcbResMemLinear32
jc @@9
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
sub esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
mov [ebp+Int_ESI],esi
clc
@@9: cwAPI_C2C
ret
cwAPI_ResMemNear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release previously allocated application relative block of memory.
;
;On Entry:
;
;ESI - Application relative linear address of block to release.
;
cwAPI_RelMemNear proc near
mov esi,[ebp+Int_ESI]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
add esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
call mcbRelMemLinear32
cwAPI_C2C
ret
cwAPI_RelMemNear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Convert linear address to application relative address.
;
;On Entry:
;
;ESI - Linear address to convert.
;
;On Exit:
;
;ESI - Application relative linear address.
;
cwAPI_Linear2Near proc near
mov esi,[ebp+Int_ESI]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
sub esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
mov [ebp+Int_ESI],esi
ret
cwAPI_Linear2Near endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Convert application relative address to linear address.
;
;On Entry:
;
;ESI - Application relative linear address.
;
;On Exit:
;
;ESI - Linear address to convert.
;
cwAPI_Near2Linear proc near
mov esi,[ebp+Int_ESI]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
add esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
mov [ebp+Int_ESI],esi
ret
cwAPI_Near2Linear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Lock a region of memory.
;
;On Entry:
;
;BX:CX - Starting linear address of memory to lock.
;SI:DI - Size of region to lock in bytes.
;
;On Exit:
;
;Carry set on error, none of the memory locked, else memory is locked.
;
cwAPI_LockMem proc near
mov bx,[ebp+Int_BX]
mov cx,[ebp+Int_CX]
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
mov ax,0600h
cwAPI_CallOld
jc @@9
;
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call RegisterResource
clc
;
@@9: cwAPI_C2C
ret
cwAPI_LockMem endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Lock a region of memory.
;
;On Entry:
;
;ESI - Starting linear address of memory to lock.
;ECX - Size of region to lock in bytes.
;
;On Exit:
;
;Carry set on error, none of the memory locked, else memory is locked.
;
cwAPI_LockMem32 proc near
mov esi,[ebp+Int_ESI]
mov ecx,[ebp+Int_ECX]
xchg esi,ecx
mov ebx,ecx
shr ebx,16
mov di,si
shr esi,16
mov ax,0600h
cwAPI_CallOld
jc @@9
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call RegisterResource
clc
@@9: cwAPI_C2C
ret
cwAPI_LockMem32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Un-lock a region of memory.
;
;On Entry:
;
;BX:CX - Starting linear address of memory to unlock
;SI:DI - Size of region to unlock in bytes
;
cwAPI_UnLockMem proc near
mov bx,[ebp+Int_BX]
mov cx,[ebp+Int_CX]
mov si,[ebp+Int_SI]
mov di,[ebp+Int_DI]
mov ax,0601h
cwAPI_CallOld
jc @@9
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call ReleaseResource
clc
@@9: cwAPI_C2C
ret
cwAPI_UnLockMem endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Un-lock a region of memory.
;
;On Entry:
;
;ESI - Starting linear address of memory to unlock
;ECX - Size of region to unlock in bytes
;
;NOTES:
;
;This will allow the memory to be swapped to disk by the VMM if neccessary.
;Areas below and above the specified memory will also be un-locked if the
;specified region is not page aligned.
;
cwAPI_UnLockMem32 proc near
mov esi,[ebp+Int_ESI]
mov ecx,[ebp+Int_ECX]
xchg esi,ecx
mov ebx,ecx
shr ebx,16
mov di,si
shr esi,16
mov ax,0601h
cwAPI_CallOld
jc @@9
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call ReleaseResource
clc
@@9: cwAPI_C2C
ret
cwAPI_UnLockMem32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Lock a region of memory using application relative address.
;
;On Entry:
;
;ESI - Starting linear address of memory to lock.
;EBX - Size of region to lock in bytes.
;
;On Exit:
;
;Carry set on error, none of the memory locked, else memory is locked.
;
cwAPI_LockMemNear proc near
mov esi,[ebp+Int_ESI]
mov ebx,[ebp+Int_EBX]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
add esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
xchg esi,ebx
mov di,si
shr esi,16
mov cx,bx
shr ebx,16
mov ax,0600h
cwAPI_CallOld
jc @@9
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call RegisterResource
clc
@@9: cwAPI_C2C
ret
cwAPI_LockMemNear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Un-lock a region of memory using application relative address.
;
;On Entry:
;
;ESI - Starting linear address of memory to unlock
;EBX - Size of region to unlock in bytes
;
cwAPI_UnLockMemNear proc near
mov esi,[ebp+Int_ESI]
mov ecx,[ebp+Int_ECX]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
add esi,ds:d[EPSP_NearBase]
assume ds:_apiCode
xchg esi,ebx
mov di,si
shr esi,16
mov cx,bx
shr ebx,16
mov ax,0601h
cwAPI_CallOld
jc @@9
mov dx,bx
shl edx,16
mov dx,cx
mov cx,si
shl ecx,16
mov cx,di
mov ax,Res_LOCK
call ReleaseResource
clc
@@9: cwAPI_C2C
ret
cwAPI_UnLockMemNear endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Allocate a region of DOS (conventional) memory.
;
;On Entry:
;
;BX - Number of paragraphs (16 byte blocks) required.
;
;On Exit:
;
;If function was successful:
;Carry flag is clear.
;
;AX - Initial real mode segment of allocated block
;DX - Initial selector for allocated block
;
;If function was not successful:
;Carry flag is set.
;
;AX - DOS error code.
;BX - Size of largest available block in paragraphs.
;
cwAPI_GetMemDOS proc near
mov bx,[ebp+Int_BX]
mov ax,0100h
cwAPI_CallOld
mov [ebp+Int_AX],ax
cwAPI_C2C
jnc @@0
mov [ebp+Int_BX],bx
jmp @@9
;
@@0: mov [ebp+Int_DX],dx
movzx edx,dx
movzx ecx,bx
shl ecx,4
mov ax,Res_DOSMEM
call RegisterResource
;
@@9: ret
cwAPI_GetMemDOS endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Re-size a block of DOS (conventional) memory previously allocated with
;GetMemDOS.
;
;On Entry:
;
;BX - New block size in paragraphs
;DX - Selector of block to modify
;
;On Exit:
;
;If function was successful:
;Carry flag is clear.
;
;If function was not successful:
;Carry flag is set.
;
;AX - DOS error code:
;BX - Maximum block size possible in paragraphs
;
cwAPI_ResMemDOS proc near
mov bx,[ebp+Int_BX]
mov dx,[ebp+Int_DX]
mov ax,0102h
cwAPI_CallOld
jnc @@0
mov [ebp+Int_AX],ax
mov [ebp+Int_BX],bx
jmp @@9
;
@@0: mov ax,Res_DOSMEM
movzx edx,dx
call ReleaseResource
movzx ecx,bx
shl ecx,4
call RegisterResource
clc
;
@@9: cwAPI_C2C
ret
cwAPI_ResMemDOS endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Release a block of DOS (conventional) memory previously allocated with
;GetMemDOS.
;
;On Entry:
;
;DX - Selector of block to free.
;
;On Exit:
;
;If function was successful:
;Carry flag is clear.
;
;If function was not successful:
;Carry flag is set.
;
;AX - DOS error code.
;
cwAPI_RelMemDOS proc near
mov ds,w[ebp+INT_DS]
mov es,w[ebp+INT_ES]
mov fs,w[ebp+INT_FS]
mov gs,w[ebp+INT_GS]
mov dx,[ebp+Int_DX]
mov ax,0101h
cwAPI_CallOld
jnc @@0
mov [ebp+Int_AX],ax
jmp @@9
;
@@0: mov ax,Res_DOSMEM
movzx edx,dx
call ReleaseResource
clc
;
@@9: cwAPI_C2C
mov w[ebp+INT_DS],ds
mov w[ebp+INT_ES],es
mov w[ebp+INT_FS],fs
mov w[ebp+INT_GS],gs
ret
cwAPI_RelMemDOS endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Run another CauseWay program directly.
;
;On Entry:
;
;DS:EDX - File name.
;ES:ESI - Command line. First byte is length, then real data.
;CX - Environment selector, 0 to use existing copy.
;
;On Exit:
;
;Carry set on error and AX = error code else AL=ErrorLevel
;
cwAPI_Exec proc near
mov ds,[ebp+Int_DS]
mov edx,[ebp+Int_EDX]
mov es,[ebp+Int_ES]
mov esi,[ebp+Int_ESI]
mov cx,[ebp+Int_CX]
mov ebx,0
push ebp
call _Exec
pop ebp
jnc @@0
mov [ebp+Int_AX],ax
jmp @@9
;
@@0: mov [ebp+Int_AL],al
;
@@9: cwAPI_C2C
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugagtext1
debugagloop2:
cmp BYTE PTR ds:[edx],0
je debugagb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugagloop2
debugagb:
mov edx,OFFSET debugagtext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugagout
debugagtext1 DB 'Done with cwAPI_Exec...',0
debugagtext2 DB 13,10
debugagout:
ENDIF
ret
cwAPI_Exec endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Validate and get expanded length of a CWC'd file.
;
;On Entry:
;
;BX - File handle.
;
;On Exit:
;
;Carry set if not a CWC'd file else,
;
;ECX - Expanded data size.
;
cwAPI_cwcInfo proc near
mov bx,[ebp+Int_BX]
call GetCWCInfo
cwAPI_C2C
mov [ebp+Int_ECX],ecx
mov [ebp+Int_EAX],eax
ret
cwAPI_cwcInfo endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Load/Expand a CWC'd data file into memory.
;
;On Entry:
;
;BX - Source file handle.
;ES:EDI - Destination memory.
;
;On Exit:
;
;Carry set on error and EAX is error code else,
;
;ECX - Expanded data length.
;
cwAPI_cwcLoad proc near
mov bx,[ebp+Int_BX]
mov es,[ebp+Int_ES]
mov edi,[ebp+Int_EDI]
call DecodeCWC
mov [ebp+Int_EAX],eax
jc @@9
mov [ebp+Int_ECX],ecx
@@9: cwAPI_C2C
ret
cwAPI_cwcLoad endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
cwAPI_LinearCheck proc near
mov esi,[ebp+Int_ESI]
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
;
mov es,RealSegment
xor eax,eax
mov ax,es
lsl eax,eax
cmp eax,esi
jc @@3
mov LinearAddressCheck,1
mov al,es:[esi]
cmp LinearAddressCheck,0
mov LinearAddressCheck,0
jnz @@2
@@3: stc
jmp @@1
@@2: clc
@@1: assume ds:_apiCode
;
cwAPI_C2C
ret
cwAPI_LinearCheck endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
cwAPI_ExecDebug proc near
mov ds,[ebp+Int_DS]
mov edx,[ebp+Int_EDX]
mov es,[ebp+Int_ES]
mov esi,[ebp+Int_ESI]
mov cx,[ebp+Int_CX]
mov ebx,1
push ebp
call _Exec
jnc @@0
pop ebp
mov [ebp+Int_AX],ax
jmp @@9
;
@@0: shl esi,16
mov si,di
mov edi,ebp
pop ebp
mov [ebp+Int_EAX],eax
mov [ebp+Int_BX],bx
mov [ebp+Int_CX],cx
mov [ebp+Int_EDX],edx
mov [ebp+Int_DI],si
shr esi,16
mov [ebp+Int_SI],si
mov [ebp+Int_EBP],edi
clc
;
@@9: cwAPI_C2C
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugaitext1
debugailoop2:
cmp BYTE PTR ds:[edx],0
je debugaib
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugailoop2
debugaib:
mov edx,OFFSET debugaitext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugaiout
debugaitext1 DB 'Done with cwAPI_ExecDebug...',0
debugaitext2 DB 13,10
debugaiout:
ENDIF
ret
cwAPI_ExecDebug endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Load another CauseWay program as an overlay, ie, do relocations etc but don't
;actually execute it.
;
;On Entry:
;
;DS:EDX - File name.
;
;On Exit:
;
;Carry set on error and AX = error code else,
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI - PSP.
;
cwAPI_cwLoad proc near
mov ds,[ebp+Int_DS]
mov edx,[ebp+Int_EDX]
mov ebx,2
xor ax,ax
mov es,ax
mov fs,ax
push ebp
call _Exec
pop ebp
jnc @@0
mov [ebp+Int_AX],ax
jmp @@9
;
@@0: mov [ebp+Int_CX],cx
mov [ebp+Int_EDX],edx
mov [ebp+Int_BX],bx
mov [ebp+Int_EAX],eax
mov [ebp+Int_SI],si
;
@@9: cwAPI_C2C
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugahtext1
debugahloop2:
cmp BYTE PTR ds:[edx],0
je debugahb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugahloop2
debugahb:
mov edx,OFFSET debugahtext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugahout
debugahtext1 DB 'Done with cwAPI_cwLoad...',0
debugahtext2 DB 13,10
debugahout:
ENDIF
ret
cwAPI_cwLoad endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
cwAPI_Cleanup proc near
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
call LoseFileHandles
clc
assume ds:_apiCode
cwAPI_C2C
ret
cwAPI_Cleanup endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Use DPMI services to allocate a single selector and initialise base & limit
;as specified with type=data/read/write.
;
;On Entry:-
;
;EAX - Linear base.
;EBX - limit.
;
;On Exit:-
;
;BX - Segment selector.
;
_SetSelector proc near
call DPMICopyCheck
;
pushm eax,ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
cmp ebx,100000h
jc @@ok
cmp ebx,-1
jz @@ok
add ebx,4095
and ebx,0FFFFFFFFh-4095
dec ebx
;
@@ok: mov d[@@SelectorBase],eax
mov d[@@SelectorSize],ebx
;
;Get a new selector from DPMI.
;
mov ax,0000h
mov cx,1
cwAPI_CallOld
jc @@9
mov bx,ax
@@GotSel: ;
push bx
mov ecx,d[@@SelectorSize]
mov esi,d[@@SelectorBase]
mov ax,ds ;need RPL to base DPL on.
lar ax,ax
and ah,DescPL3
or ah,DescPresent+DescMemory+DescRWData
;
mov dx,apiSystemFlags ;use default setting.
shr dx,14
mov al,dl
xor al,1
or al,b[apiSystemFlags+2]
and al,1
shl al,6
;
cmp ecx,0fffffh ; see if we need to set g bit
jc @@3
jz @@3
shr ecx,12 ; div by 4096
or al,80h ; set g bit
@@3: mov w[DescriptorBuffer],cx ;store low word of limit.
shr ecx,16
or cl,al
mov b[DescriptorBuffer+6],cl ;store high bits of limit and gran/code size bits.
mov w[DescriptorBuffer+2],si ;store low word of linear base.
shr esi,16
mov bx,si
mov b[DescriptorBuffer+4],bl ;store mid byte of linear base.
mov b[DescriptorBuffer+7],bh ;store high byte of linear base.
mov b[DescriptorBuffer+5],ah ;store pp/dpl/dt/type bits.
pop bx
;
;Write new descriptor table entry.
;
push bx
mov ax,000ch
mov edi,offset DescriptorBuffer
push ds
pop es
cwAPI_CallOld
pop bx
jc @@9
;
movzx edx,bx
mov ax,Res_SEL
call RegisterResource
;
@@8: clc
jmp @@10
;
@@9: stc
@@10: popm eax,ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
@@SelectorBase: ;
dd ?
@@SelectorSize: ;
dd ?
_SetSelector endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_RelSelector proc near
;
;Release a segment selector table entry.
;
;On Entry:-
;
;BX - Segment selector.
;
call DPMICopyCheck
;
;Check segment registers for value we're releasing and clear
;if found.
;
pushm ax,bx,cx
and bx,0ffffh-3
xor cx,cx
mov ax,ds
and ax,0ffffh-3
cmp ax,bx
jnz @@0
mov ds,cx
@@0: mov ax,es
and ax,0ffffh-3
cmp ax,bx
jnz @@1
mov es,cx
@@1: mov ax,fs
and ax,0ffffh-3
cmp ax,bx
jnz @@2
mov fs,cx
@@2: mov ax,gs
and ax,0ffffh-3
cmp ax,bx
jnz @@3
mov gs,cx
@@3: popm ax,bx,cx
;
pushm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
pushad
movzx edx,bx
mov ax,Res_SEL
call ReleaseResource
popad
;
push bx
mov ax,0001h
cwAPI_CallOld
pop bx
jc @@9
;
clc
jmp @@10
;
@@9: stc
@@10: popm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
@@11: ret
_RelSelector endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_SizeSelector proc near
;
;Set a segment selector table entry and return a suitable segment value. Will
;use whatever method is apropriate to the system environment.
;
;On Entry:-
;
;EAX - Linear base address.
;EBX - size in bytes.
;CX - Selector.
;
;On Exit:-
;
call DPMICopyCheck
;
pushm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
mov d[@@SelectorBase],eax
mov d[@@SelectorSize],ebx
mov bx,cx
;
push bx
push ds
pop es
mov edi,offset DescriptorBuffer
mov ax,000bh
cwAPI_CallOld
pop bx
;
push bx
mov al,0
mov ecx,d[@@SelectorSize]
mov esi,d[@@SelectorBase]
cmp ecx,0fffffh ; see if we need to set g bit
jc @@2
jz @@2
shr ecx,12 ; div by 4096
or al,80h ; set g bit
@@2: mov w[DescriptorBuffer+0],cx ;store low word of limit.
shr ecx,16
or cl,al
and b[DescriptorBuffer+6],01110000b ;lose limit & G bit.
or b[DescriptorBuffer+6],cl ;store high bits of limit and G bit.
mov w[DescriptorBuffer+2],si ;store low word of linear base.
shr esi,16
mov bx,si
mov b[DescriptorBuffer+4],bl ;store mid byte of linear base.
mov b[DescriptorBuffer+7],bh ;store high byte of linear base.
pop bx
;
;Write new descriptor table entry.
;
push bx
mov ax,000ch
mov edi,offset DescriptorBuffer
push ds
pop es
cwAPI_CallOld
pop bx
jc @@9
;
clc
jmp @@10
;
@@9: stc
@@10: popm eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
@@SelectorBase: ;
dd ?
@@SelectorSize: ;
dd ?
_SizeSelector endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_DetSelector proc near
;
;Fetch selector base & limit values.
;
;On Entry:-
;
;BX - Selector.
;
;On Exit:-
;
;EAX - Linear base address.
;EBX - size in bytes.
;
call DPMICopyCheck
;
pushm ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
push bx
push ds
pop es
mov edi,offset DescriptorBuffer
mov ax,000bh
cwAPI_CallOld
pop bx
jc @@9
;
xor eax,eax
mov al,DescriptorBuffer+7 ;base 31-24
shl eax,8
mov al,DescriptorBuffer+4 ;base 23-16
shl eax,8
mov al,DescriptorBuffer+3 ;base 15-8
shl eax,8
mov al,DescriptorBuffer+2 ;base 7-0
;
xor ebx,ebx
mov bl,DescriptorBuffer+6 ;limit 19-16
and bl,0fh
shl ebx,8
mov bl,DescriptorBuffer+1 ;limit 15-8
shl ebx,8
mov bl,DescriptorBuffer+0 ;limit 7-0
test DescriptorBuffer+6,128 ;granularity
jz @@0
shl ebx,12
or ebx,0FFFh
@@0: clc
jmp @@10
@@9: stc
@@10: popm ecx,edx,esi,edi,ebp,ds,es,fs,gs
ret
_DetSelector endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_CodeSelector proc near
call DPMICopyCheck
;
pushad
call _DSizeSelector
popad
;
pushm eax,ebx,ecx,edx,esi,edi,ebp
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
push cx
push bx
mov ax,000bh
push ds
pop es
mov edi,offset DescriptorBuffer
cwAPI_CallOld
pop bx
pop cx
;
mov ax,cs
and al,11b
shl al,5
or al,DescERCode
and DescriptorBuffer+5,10010000b
or DescriptorBuffer+5,al ;
and DescriptorBuffer+6,255-(1 shl 6) ;clear code size bit.
and cl,1
shl cl,6
or DescriptorBuffer+6,cl ;code size bit.
;
mov ax,000ch
push ds
pop es
mov edi,offset DescriptorBuffer
cwAPI_CallOld
clc
jmp @@10
;
@@9: stc
@@10: popm ds,es,fs,gs
popm eax,ebx,ecx,edx,esi,edi,ebp
@@11: ret
_CodeSelector endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_DSizeSelector proc near
pushm eax,ebx,ecx,edx,esi,edi,ebp
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
push cx
push bx
mov ax,000bh
push ds
pop es
mov edi,offset DescriptorBuffer
cwAPI_CallOld
pop bx
pop cx
;
and DescriptorBuffer+6,255-(1 shl 6) ;clear code size bit.
and cl,1
shl cl,6
or DescriptorBuffer+6,cl ;code size bit.
;
mov ax,000ch
push ds
pop es
mov edi,offset DescriptorBuffer
cwAPI_CallOld
;
popm ds,es,fs,gs
popm eax,ebx,ecx,edx,esi,edi,ebp
ret
_DSizeSelector endp
mcbChunkLast equ 0 ;pointer to previous chunk in chain.
mcbChunkNext equ 4 ;pointer to next chunk in chain.
mcbBiggest equ 8 ;biggest free block in this chunk.
mcbChunkSize equ 10 ;size of this chunk.
mcbChunkSel equ 12 ;chunk's selector.
mcbChunkLen equ 16 ;length of chunk control entry.
mcbID equ 0 ;ID for corruption checking.
mcbLast equ 1 ;previous MCB pointer status.
mcbLastSize equ 2 ;pointer to previous MCB.
mcbFreeUsed equ 4 ;free or used status.
mcbNext equ 5 ;next MCB pointer status.
mcbNextSize equ 6 ;pointer to next MCB.
mcbLen equ 8 ;length of an MCB entry.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Get current MCB memory allocation block size.
;
;On Exit:
;
;ECX - Current threshold.
;
cwAPI_GetMCBSize proc near
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
mov ecx,ds:d[EPSP_mcbMaxAlloc]
add ecx,mcbChunkLen+mcbLen
assume ds:_apiCode
mov [ebp+Int_ECX],ecx
ret
cwAPI_GetMCBSize endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Set new MCB memory allocation block size.
;
;On Entry:
;
;ECX - New value to set.
;
;On Exit:
;
;Carry set on error else new value will be used.
;
cwAPI_SetMCBSize proc near
mov ecx,[ebp+Int_ECX]
add ecx,4095
and ecx,not 4095
cmp ecx,65536+1
jc @@1
stc
jmp @@9
;
@@1: assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
cmp ecx,mcbChunkLen+mcbLen
jc @@9
sub ecx,mcbChunkLen+mcbLen
@@0: mov ds:d[EPSP_mcbMaxAlloc],ecx
assume ds:_apiCode
clc
;
@@9: cwAPI_C2C
ret
cwAPI_SetMCBSize endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Replacement for CauseWay API GetMemLinear32 function.
;
mcbGetMemLinear32 proc near
push ds
push es
push fs
push eax
push ebx
push ecx
push edx
push edi
push ebp
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov fs,PSPSegment
push ds
assume ds:nothing
mov ds,cs:apiDDSEg
assume ds:_apiCode
mov mcbLastChunk,0
assume ds:_cwMain
pop ds
;
;Round size up to next dword to keep things aligned.
;
cmp ecx,-1
jz @@GetMax
cmp ecx,-2
jz @@GetMax
add ecx,3
and ecx,not 3
;
;Check MCB allocation system is enabled.
;
cmp mcbAllocations,0
jz @@GetMax
;
;Check block size is small enough for these functions.
;
cmp ecx,fs:d[EPSP_mcbMaxAlloc]
jc mGML32_0
;
;Size is above threshold so use normal API service for this request.
;
@@GetMax: mov ebx,ecx
call _GetMemory
jnc mGML32_9
cmp ecx,-2
jz @@RetMax
cmp ecx,-1
stc
jnz mGML32_9
@@RetMax: pop ebp
pop edi
pop edx
pop ecx
mov ecx,ebx
push ecx
push edx
push edi
push ebp
stc
jmp mGML32_9
;
;Size is below threshold so use local allocation scheme.
;
mGML32_0:
;
;Check if initial block has been claimed yet, allocate and initialise one if not.
;
cmp fs:d[EPSP_mcbHead],0
jnz mGML32_10
mov ebx,fs:d[EPSP_mcbMaxAlloc]
add ebx,mcbChunkLen+mcbLen ;chunk size.
call _GetMemory ;allocate it.
jc mGML32_9 ;oops, appear to be out of memory.
mov fs:d[EPSP_mcbHead],esi
;
;Initialise this chunk.
;
mov es,RealSegment
sub ebx,mcbChunkLen+mcbLen ;chunk size.
mov es:w[esi+mcbChunkSize],bx
mov es:d[esi+mcbChunkNext],0 ;set forward link address.
mov es:d[esi+mcbChunkLast],0 ;store back link address.
mov eax,fs:d[EPSP_mcbMaxAlloc]
mov es:w[esi+mcbBiggest],ax ;set biggest chunk size.
sys GetSel
jc mGML32_9
mov es:w[esi+mcbChunkSel],bx
pushm edx,ecx
mov edx,esi
mov ecx,fs:d[EPSP_mcbMaxAlloc]
add ecx,mcbChunkLen+mcbLen
sys SetSelDet32
popm edx,ecx
add esi,mcbChunkLen ;skip chunk link info.
mov es:b[esi+mcbID],"C" ;set ID byte.
mov es:b[esi+mcbLast],"D" ;mark it as last block in back link.
mov es:w[esi+mcbLastSize],0 ;clear back link entry.
mov es:b[esi+mcbFreeUsed],"J" ;mark it as a free block,
mov es:b[esi+mcbNext],"D" ;last block in MCB chain,
mov eax,fs:d[EPSP_mcbMaxAlloc]
mov es:w[esi+mcbNextSize],ax
;
;Scan through all mcb's in all chunks looking for a big enough block.
;
mGML32_10: mov es,RealSegment ;0-4G selector.
mov esi,fs:d[EPSP_mcbHead] ;start of local allocation trail.
mGML32_1: mov edi,esi ;keep a copy for chunk chaining.
mov ebp,edi ;keep a copy for mcbBiggest
;
cmp es:w[edi+mcbBiggest],cx ;check if this chunk has a big
jc mGML32_6_0 ;enough free block.
add esi,mcbChunkLen
;
;Find first free and big enough block.
;
mGML32_2: cmp es:b[esi+mcbFreeUsed],"J" ;Free block?
jz mGML32_5
mGML32_6: cmp es:b[esi+mcbNext],"M" ;Normal block (not end of chain)?
jz mGML32_4
;
;Reached the end of the chain for this chunk so we need to move onto the next
;chunk in the chain.
;
mGML32_6_0: cmp es:d[edi+mcbChunkNext],0 ;already have a link?
jnz mGML32_3
;
;Need another chunk to put in the chain so try and allocate it via normal
;CauseWay API.
;
mov ebx,fs:d[EPSP_mcbMaxAlloc]
add ebx,mcbChunkLen+mcbLen ;chunk size.
call _GetMemory
jc mGML32_9 ;oops, appear to be out of memory.
;
;Update current chunk with address of new chunk and initialise new chunk.
;
sub ebx,mcbChunkLen+mcbLen ;chunk size.
mov es:w[esi+mcbChunkSize],bx
mov es:d[edi+mcbChunkNext],esi ;store forward link address.
mov es:d[esi+mcbChunkLast],edi ;store back link address.
mov es:d[esi+mcbChunkNext],0 ;clear new forward link address.
mov eax,fs:d[EPSP_mcbMaxAlloc]
mov es:w[esi+mcbBiggest],ax ;set biggest chunk size.
sys GetSel
jc mGML32_9
mov es:w[esi+mcbChunkSel],bx
pushm edx,ecx
mov edx,esi
mov ecx,fs:d[EPSP_mcbMaxAlloc]
add ecx,mcbChunkLen+mcbLen
sys SetSelDet32
popm edx,ecx
add esi,mcbChunkLen ;skip chunk link info.
mov es:b[esi+mcbID],"C" ;set ID.
mov es:b[esi+mcbLast],"D" ;mark it as last block in back link.
mov es:w[esi+mcbLastSize],0 ;clear back link entry.
mov es:b[esi+mcbFreeUsed],"J" ;mark it as a free block,
mov es:b[esi+mcbNext],"D" ;last block in MCB chain,
mov eax,fs:d[EPSP_mcbMaxAlloc]
mov es:w[esi+mcbNextSize],ax
;
;Chain to next chunk.
;
mGML32_3: mov esi,es:d[edi+mcbChunkNext] ;pickup forward link address.
jmp mGML32_1 ;scan this MCB chain.
;
;Move to next MCB.
;
mGML32_4: movzx eax,es:w[esi+mcbNextSize] ;get block length.
add eax,mcbLen ;include size of an MCB.
add esi,eax
jmp mGML32_2
;
;Check if this block is big enough.
;
mGML32_5: cmp es:w[esi+mcbNextSize],cx ;Big enough block?
jc mGML32_6
;
;Found a big enough free block so make use of it.
;
mov es:b[esi+mcbFreeUsed],"W" ;mark it as used.
movzx ebx,es:w[esi+mcbNextSize]
sub ebx,ecx ;get spare size.
cmp ebx,mcbLen+1 ;smaller than an MCB?
jc mGML32_8
;
;Create a new MCB from whats left over.
;
sub bx,mcbLen ;MCB comes out of this size.
mov es:[esi+mcbNextSize],cx ;set allocated block's size.
mov al,es:b[esi+mcbNext] ;get next status.
mov es:b[esi+mcbNext],"M" ;make sure its not end of chain now.
mov edi,esi
add edi,ecx
add edi,mcbLen ;move to where new MCB will be.
mov es:b[edi+mcbID],"C"
mov es:b[edi+mcbLast],"M" ;not last in back link chain.
mov es:[edi+mcbLastSize],cx ;set back link size.
mov es:b[edi+mcbFreeUsed],"J" ;mark as free,
mov es:[edi+mcbNext],al ;set end of chain status.
mov es:[edi+mcbNextSize],bx ;and new block size.
;
;Check if old block used to be end of chain.
;
cmp al,"D" ;end of chain?
jz mGML32_8
;
;Update back link size of next block.
;
movzx eax,es:w[edi+mcbNextSize]
add eax,mcbLen ;include MCB size.
add edi,eax
mov es:[edi+mcbLastSize],ax
sub es:w[edi+mcbLastSize],mcbLen
;
;Time to exit.
;
mGML32_8: add esi,mcbLen ;skip the MCB.
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov mcbLastChunk,ebp
assume ds:_cwMain
pop ds
call mcbSetBiggest
clc
;
;Restore stacked registers.
;
mGML32_9: pop ebp
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop fs
pop es
pop ds
ret
assume ds:_apiCode
mcbGetMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Replacement for CauseWay API ResMemLinear32 function.
;
mcbResMemLinear32 proc near
push ds
push es
push fs
push eax
push ebx
push ecx
push edi
push ebp
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov fs,PSPSegment
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov mcbLastChunk,0
assume ds:_cwMain
pop ds
;
mov edi,esi
add ecx,3
and ecx,not 3
;
;See if MCB allocations are enabled.
;
cmp mcbAllocations,0
jz mRsML32_30
;
;See if EDI is within the range of any of the chunks in the list.
;
mov es,RealSegment
mov esi,fs:d[EPSP_mcbHead]
or esi,esi ;check mcb's are active.
jz mRsML32_8
;
mRsML32_0: cmp edi,esi
jc mRsML32_1
movzx eax,es:w[esi+mcbChunkSize]
add eax,esi
add eax,mcbChunkLen+mcbLen ;chunk size.
cmp edi,eax
jc mRsML32_2
mRsML32_1: cmp es:d[esi+mcbChunkNext],0 ;Next link field set?
jz mRsML32_8
mov esi,es:d[esi+mcbChunkNext]
jmp mRsML32_0
;
;In range of a chunk so deal with it here.
;
mRsML32_2: xchg edi,esi
mov ebp,edi
;
;Check block size is small enough for these functions.
;
cmp ecx,fs:d[EPSP_mcbMaxAlloc]
jc mRsML32_3
;
;Can't deal with a block this big so convert it to a normal API block.
;
mov edi,esi
mov ebx,ecx
call _GetMemory ;try and allocate a normal block.
jc mRsML32_9
;
;Copy existing block to new block.
;
push ecx
push esi
push edi
xchg esi,edi
sub esi,mcbLen
movzx ecx,es:w[esi+mcbNextSize]
add esi,mcbLen
push ds
mov ds,RealSegment
;
push ecx
shr ecx,2
rep movsd
pop ecx
and ecx,3
rep movsb
pop ds
pop esi
;
;Release origional block and return address of new block.
;
call mcbRelMemLinear32
pop esi
pop ecx
jmp mRsML32_9
;
;Get block's current size.
;
mRsML32_3: sub esi,mcbLen ;move back to MCB.
cmp cx,es:[esi+mcbNextSize]
jz mRsML32_7
jnc mRsML32_4 ;extending block.
;
;Block is shrinking so build another MCB at the end of this one.
;
movzx ebx,es:w[esi+mcbNextSize]
sub ebx,ecx ;get size differance.
cmp ebx,mcbLen+1 ;enough for a new MCB?
jnc @@0
;
;Before we abandon this block size change as too small we should check if the
;next block is free and join the new space onto that if it is.
;
cmp es:b[esi+mcbNext],"M" ;end of the chain?
jnz mRsML32_7 ;yep, can't be another block.
mov edi,esi
movzx eax,es:w[esi+mcbNextSize]
add eax,mcbLen
add edi,eax ;point to the next block.
cmp es:b[edi+mcbFreeUsed],"J" ;Free block?
jnz mRsML32_7 ;no, so leave things alone.
mov es:[esi+mcbNextSize],cx ;set new size.
push esi
push ecx
mov eax,ecx
add eax,mcbLen
add esi,eax
xchg esi,edi
mov ecx,mcbLen
pushm ds,es
pop ds
rep movsb
pop ds
sub edi,mcbLen
add es:[edi+mcbNextSize],bx ;update block size.
sub es:[edi+mcbLastSize],bx ;update last size.
pop ecx
pop esi
cmp es:b[edi+mcbNext],"M" ;end of chain?
jnz mRsML32_7
movzx eax,es:w[edi+mcbNextSize]
add edi,eax
add edi,mcbLen
mov es:[edi+mcbLastSize],ax
jmp mRsML32_7 ;leave things as they are.
;
@@0: sub ebx,mcbLen ;need space for a new MCB.
mov es:[esi+mcbNextSize],cx ;set new size.
mov al,es:[esi+mcbNext] ;get next status.
mov es:b[esi+mcbNext],"M" ;force not end of chain.
mov edi,esi
add edi,ecx
add edi,mcbLen ;move to new MCB.
mov es:b[edi+mcbID],"C" ;set ID.
mov es:b[edi+mcbLast],"M" ;not last in last chain.
mov es:[edi+mcbLastSize],cx ;set last link size.
mov es:b[edi+mcbNext],al ;set next status.
mov es:b[edi+mcbFreeUsed],"J" ;mark it as free.
mov es:[edi+mcbNextSize],bx ;set next link size.
cmp al,"D" ;end of chain?
jz mRsML32_7
;
;Update last link size of next MCB.
;
movzx eax,es:w[edi+mcbNextSize]
mov ebx,edi
add ebx,eax
add ebx,mcbLen ;move to next block.
mov es:[ebx+mcbLastSize],ax
;
;Check if next block is free and join it to the newly created block if it is,
;
cmp es:b[ebx+mcbFreeUsed],"J" ;Free block?
jnz mRsML32_7
;
;Join next block to this one.
;
movzx eax,es:w[ebx+mcbNextSize] ;get block's size.
add eax,mcbLen ;include size of an mcb.
add es:[edi+mcbNextSize],ax
mov al,es:[ebx+mcbNext]
mov es:[edi+mcbNext],al ;copy next status.
cmp al,"D" ;end of chain?
jz mRsML32_7
;
;Update next blocks last link size.
;
movzx eax,es:w[edi+mcbNextSize]
add edi,eax
add edi,mcbLen ;move to next block.
mov es:[edi+mcbLastSize],ax
jmp mRsML32_7
;
;Need to expand the block so check out the block above this one.
;
mRsML32_4: cmp es:b[esi+mcbNext],"D" ;end of the chain?
jz mRsML32_6
mov edi,esi
movzx eax,es:w[esi+mcbNextSize]
add eax,mcbLen ;move to next block.
add edi,eax
cmp es:b[edi+mcbFreeUsed],"J" ;This block free?
jnz mRsML32_6
mov ebx,ecx
sub bx,es:w[esi+mcbNextSize] ;Get size needed.
movzx eax,es:w[edi+mcbNextSize]
add eax,mcbLen
cmp eax,ebx ;Big enough block?
jc mRsML32_6
;
;Next block is big enough, is it big enough to leave a free block behind still?
;
sub eax,ebx ;Get size differance.
cmp eax,mcbLen+1
jnc mRsML32_5
;
;Swollow new block whole and update next blocks last link entry.
;
movzx eax,es:w[edi+mcbNextSize]
add eax,mcbLen
add es:[esi+mcbNextSize],ax ;update block size.
mov al,es:[edi+mcbNext] ;get next status.
mov es:[esi+mcbNext],al
cmp al,"D" ;end of the chain?
jz mRsML32_7
movzx eax,es:w[esi+mcbNextSize]
mov edi,esi
add edi,eax
add edi,mcbLen
mov es:[edi+mcbLastSize],ax
jmp mRsML32_7
;
;Create a new MCB in the right place.
;
mRsML32_5: mov al,es:[edi+mcbNext] ;Get next status.
movzx ebx,es:w[edi+mcbNextSize] ;Get size of this block.
add bx,es:w[esi+mcbNextSize]
mov es:[esi+mcbNextSize],cx ;set new size of this block.
sub ebx,ecx ;get size remaining.
mov edi,esi
add edi,ecx
add edi,mcbLen
mov es:b[edi+mcbID],"C" ;set ID.
mov es:b[edi+mcbLast],"M" ;not last in last chain.
mov es:[edi+mcbLastSize],cx ;last link size.
mov es:b[edi+mcbFreeUsed],"J" ;mark it as free again.
mov es:[edi+mcbNext],al ;set next status.
mov es:[edi+mcbNextSize],bx ;set next link size.
cmp al,"D" ;end of the chain?
jz mRsML32_7
add edi,ebx
add edi,mcbLen ;move to next block.
mov es:[edi+mcbLastSize],bx
jmp mRsML32_7
;
;Have to try and allocate another block and copy the current blocks contents.
;
mRsML32_6: add esi,mcbLen
mov edi,esi
call mcbGetMemLinear32
jc mRsML32_9
push ecx
push esi
push edi
xchg esi,edi
sub esi,mcbLen
movzx ecx,es:w[esi+mcbNextSize]
add esi,mcbLen
push ds
mov ds,RealSegment
push ecx
shr ecx,2
rep movsd
pop ecx
and ecx,3
rep movsb
pop ds
pop esi
call mcbRelMemLinear32 ;release origional block.
pop esi
pop ecx
clc
jmp mRsML32_9
;
;Setup block address to return and exit.
;
mRsML32_7: add esi,mcbLen
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov mcbLastChunk,ebp
assume ds:_cwMain
pop ds
call mcbSetBiggest
clc
jmp mRsML32_9
;
;Not in range of any local chunks so pass it to CauseWay API function.
;
mRsML32_8: cmp ecx,fs:d[EPSP_mcbMaxAlloc]
jc mRsML32_11
mRsML32_30: mov esi,edi
mov ebx,ecx
call _ResMemory
jmp mRsML32_9
;
;Convert normal API block to local MCB block. This assumes that a none MCB block
;comeing through here is bigger than mcbMaxAlloc and therefore is shrinking.
;
mRsML32_11: call mcbGetMemLinear32
jc mRsML32_9
;
;Copy origional block contents.
;
push esi
push edi
xchg esi,edi
push ds
mov ds,RealSegment
push ecx
shr ecx,2
rep movsd
pop ecx
and ecx,3
rep movsb
pop ds
pop esi
call _RelMemory ;release origional block.
pop esi
;
;Return to caller.
;
mRsML32_9: pop ebp
pop edi
pop ecx
pop ebx
pop eax
pop fs
pop es
pop ds
ret
assume ds:_apiCode
mcbResMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Replacement for CauseWay API RelMemLinear32 function.
;
mcbRelMemLinear32 proc near
push ds
push es
push fs
pushad
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov fs,PSPSegment
mov edi,esi
;
;See if MCB blocks are enabled.
;
cmp mcbAllocations,0
jz mRML32_8
;
;See if EDI is within the range of any of the chunks in the list.
;
mov es,RealSegment
mov esi,fs:d[EPSP_mcbHead]
or esi,esi ;check mcb's are active.
jz mRML32_8
;
mRML32_0: cmp edi,esi
jc mRML32_1
movzx eax,es:w[esi+mcbChunkSize]
add eax,esi
add eax,mcbChunkLen+mcbLen ;chunk size.
cmp edi,eax
jc mRML32_2
mRML32_1: cmp es:d[esi+mcbChunkNext],0 ;Next link field set?
jz mRML32_8
mov esi,es:d[esi+mcbChunkNext]
jmp mRML32_0
;
;In range of a chunk so deal with it here.
;
mRML32_2: xchg edi,esi
mov ebp,edi
sub esi,mcbLen
mov es:b[esi+mcbFreeUsed],"J" ;mark it as free.
;
;Check if next block is free and join it to this one if it is.
;
mRML32_11: cmp es:b[esi+mcbNext],"D" ;last block in chain?
jz mRML32_3
movzx eax,es:w[esi+mcbNextSize]
mov ebx,esi
add eax,mcbLen
add ebx,eax
cmp es:b[ebx+mcbFreeUsed],"J" ;free block?
jnz mRML32_3
movzx eax,es:w[ebx+mcbNextSize]
add eax,mcbLen
add es:[esi+mcbNextSize],ax ;update block size.
mov al,es:[ebx+mcbNext]
mov es:[esi+mcbNext],al ;copy next status.
cmp al,"D" ;last block in chain?
jz mRML32_3
;
;Update next blocks last block pointer.
;
movzx eax,es:w[esi+mcbNextSize]
add eax,mcbLen
add esi,eax
mov es:[esi+mcbLastSize],ax
sub es:w[esi+mcbLastSize],mcbLen
sub esi,eax
;
;Check if current block is end of next chain and end of last chain. If it
;is we can release this chunk because it isn't being used anymore.
;
mRML32_3: cmp es:b[esi+mcbNext],"M"
jz mRML32_4
cmp es:b[esi+mcbLast],"M"
jz mRML32_4
;
;Un-link and release this chunk, its not being used.
;
mov esi,edi ;Get chunk address.
mov edi,es:[esi+mcbChunkLast]
mov eax,es:[esi+mcbChunkNext]
or edi,edi ;First chunk?
jnz mRML32_5
mov fs:d[EPSP_mcbHead],eax ;Set new head chunk, 0 is valid.
jmp mRML32_6
mRML32_5: mov es:[edi+mcbChunkNext],eax ;link to next chunk.
mRML32_6: xchg eax,edi
or edi,edi ;is there a next chunk?
jz mRML32_7
mov es:[edi+mcbChunkLast],eax ;link to last chunk.
mRML32_7: mov bx,es:[esi+mcbChunkSel]
sys RelSel ;release this selector.
call _RelMemory ;release this memory for real.
jmp mRML32_9 ;exit, we're all done.
;
;Check if previous block is free and join this one to it if it is.
;
mRML32_4: cmp es:b[esi+mcbLast],"M" ;last block in last chain?
jnz mRML32_10
;
;Move back to previous block, see if its free and let the next block join code
;deal with it if it is.
;
movzx eax,es:w[esi+mcbLastSize]
add eax,mcbLen
sub esi,eax
cmp es:b[esi+mcbFreeUsed],"J"
jz mRML32_11
;
;Finished but we couldn't release this chunk.
;
mRML32_10: call mcbSetBiggest
clc
jmp mRML32_9
;
;Not in range of any local chunks so pass it to CauseWay API function.
;
mRML32_8: mov esi,edi
call _RelMemory
;
mRML32_9: popad
pop fs
pop es
pop ds
ret
assume ds:_apiCode
mcbRelMemLinear32 endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Set mcbBiggest entry in chunk header.
;
;On Entry:
;
;ES:EBP - Chunk header.
;
mcbSetBiggest proc near
pushm eax,ecx,esi
mov esi,ebp
add esi,mcbChunkLen
xor ecx,ecx
@@0: cmp es:b[esi+mcbFreeUsed],"J"
jnz @@1
cmp cx,es:w[esi+mcbNextSize]
jnc @@1
mov cx,es:w[esi+mcbNextSize]
@@1: cmp es:b[esi+mcbNext],"M" ;last block in last chain?
jnz @@2
movzx eax,es:w[esi+mcbNextSize]
add esi,eax
add esi,mcbLen
jmp @@0
@@2: mov es:w[ebp+mcbBiggest],cx
popm eax,ecx,esi
ret
mcbSetBiggest endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_GetMemory proc near
;
;Attempt to allocate a block of memory.
;
;On Entry:-
;
;EBX - Size of block required. (-1 to get size of free memory).
;
;On Exit:-
;
;Carry set on error, else:-
;
;ESI - linear address of memory.
;
;ALL registers may be corrupted.
;
call DPMICopyCheck
;
pushm ecx,edx,edi,ebp,ds,es
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
pushm d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
;
cmp ebx,-2
jz @@Special
cmp ebx,-1 ;special value to get memory free?
jnz @@NotSpecial
@@Special: call _GetMemoryMax ;call free memory code.
stc
popm d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
popm ecx,edx,edi,ebp,ds,es
ret
;
@@NotSpecial: mov d[@@BlockSize],ebx ;store real block size.
;
mov cx,bx
shr ebx,16
mov ax,0501h ;Allocate memory block.
cwAPI_CallOld
jc @@9
shl ebx,16
mov bx,cx
mov d[@@BlockBase],ebx ;store linear base address.
shl esi,16
mov si,di
mov d[@@BlockHandle],esi ;store access handle.
;
mov ax,Res_MEM
mov edx,ebx
mov ecx,esi
mov ebx,d[@@BlockSize]
call RegisterResource
;
mov esi,edx
clc
jmp @@10
;
@@9: stc
@@10: popm d[@@BlockSize],d[@@BlockBase],d[@@BlockHandle]
popm ecx,edx,edi,ebp,ds,es
ret
@@BlockBase: ;
dd ?
@@BlockHandle: ;
dd ?
@@BlockSize: ;
dd ?
_GetMemory endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_GetMemoryMax proc near
;
;Work out biggest memory block remaining.
;
call DPMICopyCheck
;
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
COMMENT ! MED 02/15/96
cmp ebx,-1 ;normal max reporting?
jz @@normal
push ds
mov ds,apiDSeg
assume ds:_cwMain
cmp ProtectedType,2
assume ds:_apiCode
pop ds
jz @@normal
;
;Get free disk space remaining.
;
push ds
mov ax,KernalDS
mov ds,ax
assume ds:_cwRaw
pushm eax,ebx,ecx,esi,edi
xor edx,edx
cmp VMMHandle,0
jz @@500_1
mov dl,VMMName ;get drive letter for this media.
sub dl,'A' ;make it real.
inc dl ;adjust for current type select.
mov ah,36h ;get free space.
int 21h ;/
xor edx,edx
cmp ax,-1 ;invalid drive?
jz @@500_1
mul cx ;Get bytes per cluster.
mul bx ;Get bytes available.
shl edx,16
mov dx,ax
add edx,SwapFileLength ;include current size.
shr edx,12
;
;Work out how much of the VMM space is extra.
;
mov eax,LinearLimit
sub eax,LinearBase
shr eax,12
sub edx,eax
jmp @@500_2
;
@@500_1:
mov edx,TotalPhysical
@@500_2: add edx,FreePages
;
popm eax,ebx,ecx,esi,edi
assume ds:_apiCode
pop ds
mov ebx,edx
shl ebx,12
jmp @@exit
END COMMENT !
@@normal: push es
mov edi,offset @@dpmembuff
push ds
pop es
push ebx
mov ax,0500h
cwAPI_CallOld
pop ebx
pop es
cmp ebx,-2
jnz @@normal2
mov ebx,d[@@dpmembuff+1Ch]
shl ebx,12
jmp @@exit
@@normal2: mov ebx,d[@@dpmembuff]
;
@@exit: pop ds
ret
@@dpmembuff: ;
db 30h dup (0)
_GetMemoryMax endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_ResMemory proc near
;
;Re-size a block of memory.
;
;On Entry:-
;
;ESI - Linear address of memory.
;EBX - New size.
;
;On Exit:-
;
;ESI - New linear address of memory.
;
call DPMICopyCheck
;
pushm eax,ebx,ecx,edx,edi,ebp,ds,es
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
push d[@@OldESI]
mov d[@@OldESI],esi
push d[@@OldEBX]
mov d[@@OldEBX],ebx
pushm LastResource,LastResource+4
;
mov edx,esi
mov ax,Res_MEM
call FindResource
jc @@9
;
mov ebx,d[@@OldEBX]
mov esi,ecx
mov di,si
shr esi,16
mov cx,bx
shr ebx,16 ;set block size.
mov ax,0503h ;release the block.
cwAPI_CallOld
jc @@9
shl ebx,16
mov bx,cx
shl esi,16
mov si,di
xchg esi,ebx
;
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edx,LastResource
mov es:[edx],esi ;update base.
add edx,4
mov es:[edx],ebx ;update handle.
add edx,4
mov ebx,d[@@OldEBX]
mov es:[edx],ebx ;update size.
;
clc
jmp @@10
;
@@9: stc
@@10: popm LastResource,LastResource+4
pop d[@@OldEBX]
pop d[@@OldESI]
popm eax,ebx,ecx,edx,edi,ebp,ds,es
ret
@@OldEBX: ;
dd 0
@@OldESI: ;
dd 0
_ResMemory endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
_RelMemory proc near
;
;Release a previously allocated block of memory.
;
;On Entry:-
;
;ESI - Near DS pointer.
;
call DPMICopyCheck
;
pushm ds,es
pushad
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
pushm LastResource,LastResource+4
;
mov edx,esi
mov ax,Res_MEM
call FindResource
jc @@9
;
mov esi,ecx
mov di,si
shr esi,16
mov ax,0502h ;release the block.
cwAPI_CallOld
jc @@9
;
mov di,bx
shr ebx,16
mov si,bx
mov cx,dx
shr edx,16
mov bx,dx
mov ax,0703h ;discard the block.
cwAPI_CallOld
;
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov esi,LastResource
mov edi,LastResource+4
xor eax,eax
mov es:[edi],ax
mov es:[edi+2],al
mov es:[esi],eax
mov es:[esi+4],eax
mov es:[esi+8],eax
;
clc
;
@@9: popm LastResource,LastResource+4
popad
popm ds,es
ret
_RelMemory endp
;-------------------------------------------------------------------------
;
;Register a new resource.
;
;On Entry:
;
;AL - Resource type to register.
;EDX - Key value.
;ECX - optional second value.
;EBX - optional third value.
;
RegisterResource proc near
pushm ds,es,fs
pushad
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov es,RealSegment
mov fs,PSPSegment
;
cmp ResourceTracking,0
jz @@9
cmp fs:d[EPSP_Resource],0 ;allocated memory for list yet?
jnz @@0
;
;Allocate initial resource list space.
;
pushad
call @@GetAndInit
jc @@1
mov fs:d[EPSP_Resource],esi
@@1: popad
cmp fs:d[EPSP_Resource],0
jz @@90
;
@@0: ;Search list for free slot.
;
cld
mov ebp,ecx ;Copy value 2.
mov ah,al ;Copy type.
mov esi,fs:d[EPSP_Resource]
@@FreeLoop: mov edi,esi
add edi,ResHead ;point to types.
mov ecx,ResCount ;get number of entries.
@@2: or ecx,ecx
jz @@2_0
js @@2_0
xor al,al
repne scasb ;Find NULL entry.
jz @@3
@@2_0: cmp es:d[esi+8],0 ;link field setup?
jz @@Extend
mov esi,es:[esi+8] ;link to next block.
jmp @@FreeLoop
;
@@Extend: ;Extend the list.
;
push esi
call @@GetAndInit
pop ecx
jc @@90
mov es:[esi+4],ecx ;store back link address.
mov es:[ecx+8],esi ;store forward link address.
jmp @@FreeLoop
;
;Check if enough entries are free.
;
@@3: cmp ah,Res_SEL
jz @@sel
cmp ah,Res_MEM
jz @@mem
cmp ah,Res_LOCK
jz @@lock
cmp ah,Res_DOSMEM
jz @@dosmem
cmp ah,Res_CALLBACK
jz @@callback
cmp ah,Res_PSP
jz @@psp
jmp @@sel
;
;Check for 2 free entries for DOS memory.
;
@@dosmem: cmp es:b[edi],0
jnz @@2
dec edi
mov ecx,edi
sub ecx,ResHead ;Get offset from list start.
sub ecx,esi
shl ecx,2
add ecx,ResNum+ResHead
add ecx,esi
mov es:b[edi],ah ;Store type.
mov es:d[ecx],edx
inc edi
add ecx,4
mov ah,Res_CHAIN
mov es:b[edi],ah
mov es:d[ecx],ebp
jmp @@9
;
;Check for 3 free entries for callback.
;
@@callback: cmp es:w[edi],0 ;2 more entries?
jnz @@2
dec edi
mov ecx,edi
sub ecx,ResHead ;Get offset from list start.
sub ecx,esi
shl ecx,2
add ecx,ResNum+ResHead
add ecx,esi
mov es:b[edi],ah ;Store type.
mov es:d[ecx],edx
inc edi
add ecx,4
mov ah,Res_CHAIN
mov es:b[edi],ah
mov es:d[ecx],ebp
inc edi
add ecx,4
mov es:b[edi],ah
mov es:d[ecx],ebx
jmp @@9
;
;Check for 3 free entries for memory.
;
@@mem: cmp es:w[edi],0 ;2 more entries?
jnz @@2
dec edi
mov ecx,edi
sub ecx,ResHead ;Get offset from list start.
sub ecx,esi
shl ecx,2
add ecx,ResNum+ResHead
add ecx,esi
mov es:b[edi],ah ;Store type.
mov es:d[ecx],edx
inc edi
add ecx,4
mov ah,Res_CHAIN
mov es:b[edi],ah
mov es:d[ecx],ebp
inc edi
add ecx,4
mov es:b[edi],ah
mov es:d[ecx],ebx
jmp @@9
;
;Check for 2 free entries for lock's.
;
@@lock: cmp es:b[edi],0
jnz @@2
dec edi
mov ecx,edi
sub ecx,ResHead ;Get offset from list start.
sub ecx,esi
shl ecx,2
add ecx,ResNum+ResHead
add ecx,esi
mov es:b[edi],ah ;Store type.
mov es:d[ecx],edx
inc edi
add ecx,4
mov ah,Res_CHAIN
mov es:b[edi],ah
mov es:d[ecx],ebp
jmp @@9
;
;Only one free entry needed for selectors.
;
@@psp: ;
@@sel: dec edi
mov ecx,edi
sub ecx,ResHead ;Get offset from list start.
sub ecx,esi
shl ecx,2
add ecx,ResNum+ResHead
add ecx,esi
mov es:b[edi],ah ;Store type.
mov es:d[ecx],edx
jmp @@9
;
@@90: stc
jmp @@100
;
@@9: clc
@@100: popad
popm ds,es,fs
ret
;
@@GetAndInit: pushm eax,ebx,ecx,edx,ebp
mov cx,4096
xor bx,bx
mov ax,0501h ;Allocate memory block.
cwAPI_CallOld
jc @@GAIerror
shl esi,16
mov si,di
shl ebx,16
mov bx,cx
xchg esi,ebx
mov edi,esi
xor eax,eax
mov ecx,ResSize/4
cld
rep stosd ;init memory.
mov es:d[esi+12],ebx ;store the handle.
clc
@@GAIerror: popm eax,ebx,ecx,edx,ebp
ret
assume ds:_apiCode
RegisterResource endp
;-------------------------------------------------------------------------
;
;Release a resource entry. If it's a PSP then release its resources.
;
;On Entry:
;
;AL - Resource type.
;EDX - Key value.
;
ReleaseResource proc near
pushm ds,es,fs
pushad
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov fs,PSPSegment
cmp ResourceTracking,0
jz @@9
cmp fs:d[EPSP_Resource],0
jz @@9
xchg eax,edx
mov es,RealSegment
cld
mov esi,fs:d[EPSP_Resource]
@@LookLoop: mov edi,esi
add edi,ResHead+ResNum
mov ecx,ResNum ;get number of entries.
@@2: repne scasd
jz @@0
mov esi,es:[esi+8] ;link to next list.
or esi,esi
jz @@9
jmp @@LookLoop
;
@@0: mov ebx,edi
sub ebx,4+ResHead+ResNum
sub ebx,esi
shr ebx,2
add ebx,esi
add ebx,ResHead
cmp es:b[ebx],dl ;Right type?
jz @@1
cmp dl,Res_SEL ;Selector?
jnz @@2
cmp es:b[ebx],Res_PSP
jnz @@2
;
@@1: ;At this point we have a match.
;
xor eax,eax
sub edi,4
mov dl,es:[ebx]
xor dh,dh
cmp dl,Res_SEL
jz @@rel_1
cmp dl,Res_LOCK
jz @@Rel_2
cmp dl,Res_MEM
jz @@Rel_3
cmp dl,Res_DOSMEM
jz @@Rel_2
cmp dl,Res_CALLBACK
jz @@Rel_3
cmp dl,Res_PSP
jz @@psp
jmp @@9
;
@@Rel_3: mov es:b[ebx],dh
mov es:d[edi],eax
inc ebx
add edi,4
@@Rel_2: mov es:b[ebx],dh
mov es:d[edi],eax
inc ebx
add edi,4
@@Rel_1: mov es:b[ebx],dh
mov es:d[edi],eax
jmp @@9
;
;Release a PSP. Assumes that the PSP memory will be released by the caller.
;
@@psp: mov es:[ebx],dh
push w[PSPSegment]
mov bx,es:[edi]
mov fs,bx
;
;Remove links to all other modules.
;
cmp fs:d[EPSP_Imports],0
jz @@no_imports
pushm ecx,esi,edi
mov esi,fs:d[EPSP_Imports]
mov ecx,es:[esi]
add esi,4
@@imp0: or ecx,ecx
jz @@imp1
mov edi,es:[esi]
call UnFindModule
add esi,4
dec ecx
jmp @@imp0
@@imp1: popm ecx,esi,edi
@@no_imports:
cmp fs:[EPSP_Resource],0
jnz @@normal_res
;
;This must be a cwLoad PSP.
;
;release program selectors and memory manually.
;
pushad
movzx ecx,fs:w[EPSP_SegSize]
shr ecx,3
mov bx,fs:w[EPSP_SegBase]
or ecx,ecx
jz @@frelsel9
@@frelsel: sys RelSel
add bx,8
dec ecx
jnz @@frelsel
@@frelsel9: mov esi,fs:[EPSP_MemBase]
sys RelMemLinear32
mov esi,fs:[EPSP_Exports]
or esi,esi
jz @@frelsel0
sys RelMemLinear32
@@frelsel0: popad
;
@@normal_res: ;Take this PSP out of the linked list.
;
pushad
mov bx,fs
sys GetSelDet32
mov esi,es:EPSP_NextPSP[edx]
mov edi,es:EPSP_LastPSP[edx]
or esi,esi
jz @@ChainPSP0
mov es:EPSP_LastPSP[esi],edi
@@ChainPSP0: or edi,edi
jz @@ChainPSP1
mov es:EPSP_NextPSP[edi],esi
@@ChainPSP1: popad
;
mov ah,50h
int 21h ;set new PSP.
;
;Search for PSP's and release them first.
;
mov esi,fs:[EPSP_Resource] ;Get resource pointer.
@@fPSP0: or esi,esi
jz @@NoPSPSearch
mov ebp,ResNum
mov edi,esi
add edi,16
mov edx,esi
add edx,ResHead+ResNum
@@fPSP1: cmp es:b[edi],Res_PSP
jnz @@fPSP2
push ebx
mov ebx,es:[edx] ;Get selector.
sys RelMem
pop ebx
@@fPSP2: inc edi
add edx,4
dec ebp
jnz @@fPSP1
mov esi,es:[esi+8] ;link to next list.
jmp @@fPSP0
;
@@NoPSPSearch: ;Now release all other types of resource.
;
cmp fs:w[EPSP_DPMIMem],0 ;Any DPMI save buffer?
jz @@psp_0
xor bx,bx
xchg bx,fs:w[EPSP_DPMIMem]
sys RelMem
@@psp_0: ;
cmp fs:d[EPSP_INTMem],0 ;Any int/excep vector memory?
jz @@psp_1
xor esi,esi
xchg esi,fs:d[EPSP_INTMem]
sys RelMemLinear32
@@psp_1: ;
mov esi,fs:[EPSP_Resource] ;Get resource pointer.
or esi,esi
jz @@psp_9
@@psp_2: cmp es:d[esi+8],0 ;Found last entry in chain?
jz @@psp_3
mov esi,es:d[esi+8]
jmp @@psp_2
@@psp_3: ;
mov ebp,ResNum
mov edi,esi
add edi,16
mov edx,esi
add edx,ResHead+ResNum
@@psp_4: cmp es:b[edi],Res_NULL
jz @@psp_5
cmp es:b[edi],Res_SEL
jz @@sel
cmp es:b[edi],Res_MEM
jz @@mem
cmp es:b[edi],Res_LOCK
jz @@lock
cmp es:b[edi],Res_DOSMEM
jz @@dosmem
cmp es:b[edi],Res_CALLBACK
jz @@callback
cmp es:b[edi],Res_PSP
jz @@rel_psp
jmp @@psp_5
;
;Release a selector.
;
@@sel: mov es:b[edi],Res_NULL
pushm esi,edi,ebp,edx
mov ebx,es:[edx]
push ResourceTracking
mov ResourceTracking,0
call _RelSelector
pop ResourceTracking
popm esi,edi,ebp,edx
jmp @@psp_5
;
;Release some memory.
;
@@mem: mov ForcedFind,edx
mov ForcedFind+4,edi
mov es:b[edi],Res_NULL
mov eax,es:[edx]
inc edi
add edx,4
mov es:b[edi],Res_NULL
inc edi
add edx,4
mov es:b[edi],Res_NULL
pushm esi,edi,ebp,edx
mov esi,eax
call _RelMemory
popm esi,edi,ebp,edx
sub ebp,2
jmp @@psp_5
;
;Release a lock.
;
@@lock: mov es:b[edi],Res_NULL
mov eax,es:[edx]
inc edi
add edx,4
mov es:b[edi],Res_NULL
pushm esi,edi,ebp,edx
mov ecx,es:[edx]
mov esi,eax
push ResourceTracking
mov ResourceTracking,0
sys UnLockMem32
pop ResourceTracking
popm esi,edi,ebp,edx
dec ebp
jmp @@psp_5
;
;Release DOS memory.
;
@@dosmem: mov es:b[edi],Res_NULL
mov eax,es:[edx]
inc edi
add edx,4
mov es:b[edi],Res_NULL
pushm eax,edx
mov edx,eax
push ResourceTracking
mov ResourceTracking,0
sys RelMemDOS
pop ResourceTracking
popm eax,edx
dec ebp
jmp @@psp_5
;
;Release a call-back.
;
@@callback: mov es:b[edi],Res_NULL
mov eax,es:[edx]
inc edi
add edx,4
mov es:b[edi],Res_NULL
inc edi
add edx,4
mov es:b[edi],Res_NULL
pushm eax,ecx,edx
mov ecx,eax
mov dx,cx
shr ecx,16
mov ax,0304h
push ResourceTracking
mov ResourceTracking,0
cwAPI_CallOld
assume ds:_cwMain
pop ResourceTracking
popm eax,ecx,edx
sub ebp,2
jmp @@psp_5
;
;Release another PSP.
;
@@rel_psp: pushm esi,edi,ebp,edx
mov ebx,es:[edx]
sys RelMem
popm esi,edi,ebp,edx
;
@@psp_5: inc edi
add edx,4
dec ebp
jnz @@psp_4
mov eax,es:d[esi+4] ;get back link pointer.
push eax
push esi
mov esi,es:[esi+12] ;get memory handle.
mov di,si
shr esi,16
mov ax,0502h ;release the block.
cwAPI_CallOld
pop esi
pushm ebx,ecx,edi
mov cx,si
shr esi,16
mov bx,si
xor si,si
mov di,4096
mov ax,0703h ;discard the block.
cwAPI_CallOld
popm ebx,ecx,edi
pop esi
or esi,esi
jz @@psp_9
mov es:d[esi+8],0 ;make sure link pointer is clear
jmp @@psp_3
@@psp_9: ;
;Switch back to the old PSP
;
pop bx
mov ah,50h
int 21h ;go back to old PSP.
;
@@9: popad
popm ds,es,fs
ret
assume ds:_apiCode
ReleaseResource endp
;-------------------------------------------------------------------------
;
;Check if a resource exists.
;
;On Entry:
;
;AL - Resource type.
;EDX - Key value.
;
;On Exit:
;
;Carry clear if it does and,
;
;ECX - Optional second value.
;EBX - Optional third value.
;
FindResource proc near
pushm ds,es,fs
pushm eax,edx,esi,edi,ebp
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov es,RealSegment
mov fs,PSPSegment
xchg eax,edx
xor edi,edi
xchg edi,ForcedFind
mov ebp,ForcedFind+4
or edi,edi
jnz @@Found
cmp ResourceTracking,0
jz @@8
cmp fs:d[EPSP_Resource],0
jz @@8
;
mov esi,fs:d[EPSP_Resource]
@@LookLoop: mov ecx,ResNum ;get number of entries.
mov edi,esi
add edi,ResHead+ResNum
cld
@@0: repne scasd
jz @@1
mov esi,es:[esi+8] ;link to next list.
or esi,esi
jnz @@LookLoop
stc
jmp @@9
@@1: mov ebp,edi
sub ebp,4+ResHead+ResNum
sub ebp,esi
shr ebp,2
add ebp,ResHead
add ebp,esi
cmp es:[ebp],dl
jnz @@0
sub edi,4
;
@@Found: cmp dl,Res_SEL
jz @@8
cmp dl,Res_MEM
jz @@2
cmp dl,Res_LOCK
jz @@8
cmp dl,Res_DOSMEM
jz @@8
cmp dl,Res_CALLBACK
jz @@8
cmp dl,Res_PSP
jz @@8
stc
jmp @@9
;
@@2: assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov LastResource,edi
mov LastResource+4,ebp
add edi,4
mov ecx,es:[edi]
add edi,4
mov ebx,es:[edi]
;
@@8: clc
;
@@9: popm eax,edx,esi,edi,ebp
popm ds,es,fs
ret
FindResource endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
SaveExecState proc near
push es
push ds
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
;
;Get memory for the interrupt/exception vector save buffer.
;
mov ecx,(256*6)+(256*4)+(32*6)
sys GetMemLinear32
jc @@9
mov es,PSPSegment
mov es:d[EPSP_INTMem],esi
mov edi,esi
mov es,RealSegment
;
;Get protected mode interrupt vectors.
;
mov bl,0
mov bp,256
@@GetPVect: pushm bx,edi,bp,es
sys GetVect
popm bx,edi,bp,es
mov es:d[edi],edx
mov es:w[edi+4],cx
add edi,6
inc bl
dec bp
jnz @@GetPVect
;
;Get protected mode exception vectors.
;
mov bp,32
mov bl,0
@@GetEVect: pushm bx,edi,bp,es
sys GetEVect
popm bx,edi,bp,es
mov es:d[edi],edx
mov es:w[edi+4],cx
add edi,6
inc bl
dec bp
jnz @@GetEVect
;
;Get real mode interrupt vectors.
;
mov bp,256
mov bl,0
@@GetRVect: pushm bx,edi,bp,es
sys GetRVect
popm bx,edi,bp,es
mov es:w[edi],dx
mov es:w[edi+2],cx
add edi,4
inc bl
dec bp
jnz @@GetRVect
;
;Get memory for DPMI state buffer.
;
cmp d[DPMIStateSize],0
jz @@NoDPMISave
mov ecx,d[DPMIStateSize]
sys GetMem32
jc @@9
;
;Save DPMI state.
;
mov es,PSPSegment
mov es:w[EPSP_DPMIMem],bx
mov es,bx
xor edi,edi
mov al,0
test SystemFlags,1
jz @@DPMISave32
db 66h
call f[DPMIStateAddr]
jmp @@NoDPMISave
@@DPMISave32: call f[DPMIStateAddr]
@@NoDPMISave: ;
clc
@@9: pop ds
assume ds:_apiCode
pop es
ret
SaveExecState endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
LoadExecState proc near
push es
push ds
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
;
;Set protected mode interrupt vectors.
;
mov es,PSPSegment
mov edi,es:d[EPSP_INTMem]
or edi,edi
jz @@NoIntRel
mov es,RealSegment
mov bl,0
mov bp,256
@@SetPVect: pushm bx,edi,bp,es
sys GetVect
pushm ecx,edx
mov edx,es:d[edi]
mov cx,es:w[edi+4]
sys SetVect
popm ecx,edx
cmp edx,es:d[edi]
jnz @@Pdiff
cmp cx,es:w[edi+4]
jnz @@Pdiff
mov es:w[edi+4],-1
jmp @@Pdone
@@Pdiff: mov es:d[edi],edx
mov es:w[edi+4],cx
@@Pdone: popm bx,edi,bp,es
add edi,6
inc bl
dec bp
jnz @@SetPVect
;
;Set protected mode exception vectors.
;
mov bp,32
mov bl,0
@@SetEVect: pushm bx,edi,bp,es
sys GetEVect
pushm ecx,edx
mov edx,es:d[edi]
mov cx,es:w[edi+4]
sys SetEVect
popm ecx,edx
cmp edx,es:[edi]
jnz @@Ediff
cmp cx,es:[edi+4]
jnz @@Ediff
mov es:w[edi+4],-1
jmp @@Edone
@@Ediff: mov es:[edi],edx
mov es:[edi+4],cx
@@Edone: popm bx,edi,bp,es
add edi,6
inc bl
dec bp
jnz @@SetEVect
;
;Set real mode interrupt vectors.
;
mov bp,256
mov bl,0
@@SetRVect: pushm bx,edi,bp,es
sys GetRVect
pushm cx,dx
mov dx,es:w[edi]
mov cx,es:w[edi+2]
sys SetRVect
popm cx,dx
cmp dx,es:[edi]
jnz @@Rdiff
cmp cx,es:[edi+2]
jnz @@Rdiff
mov es:w[edi+2],-1
jmp @@Rdone
@@Rdiff: mov es:[edi],dx
mov es:[edi+2],cx
@@Rdone: popm bx,edi,bp,es
add edi,4
inc bl
dec bp
jnz @@SetRVect
;
;Restore DPMI stack state.
;
@@NoIntRel: mov es,PSPSegment
mov ax,es:w[EPSP_DPMIMem]
or ax,ax
jz @@NoDPMIRel
jmp @@NoDPMIRel
mov es,ax
xor edi,edi
mov al,1
test SystemFlags,1
jz @@SaveDPMI32
db 66h
call f[DPMIStateAddr]
jmp @@NoDPMIRel
@@SaveDPMI32: call f[DPMIStateAddr]
@@NoDPMIRel: ;
pop ds
assume ds:_apiCode
pop es
ret
LoadExecState endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Create a new PSP complete with command line, environment & saved state.
;
;On Entry:
;
;EBX - flags, as passed to _Exec
;DS:EDX - program name
;ES:ESI - command line.
;CX - environment.
;
;On Exit:
;
;Carry set on error &,
;
;BX - new PSP (zero if error).
;
CreatePSP proc near
mov ax,ds
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
mov d[@@Name],edx
mov w[@@Name+4],ax
mov d[@@Flags],ebx
mov d[@@Command],esi
mov w[@@Command+4],es
mov w[@@Environment],cx
;
mov w[@@PSP],0
;
;Allocate PSP memory.
;
mov ecx,(size PSP_Struc)+(size EPSP_Struc)
sys GetMemLinear32
jc @@error ;Not enough memory.
push ds
mov ds,apiDSeg
assume ds:_cwMain
push ResourceTracking
mov ResourceTracking,0
sys GetSel
jnc @@memOK
pop ResourceTracking
pop ds
sys RelMemLinear32
jmp @@error
@@memOK: mov edx,esi
mov ecx,(size PSP_Struc)+(size EPSP_Struc)
sys SetSelDet32
pop ResourceTracking
assume ds:_apiCode
pop ds
;
;Register this selector as a PSP.
;
mov ax,Res_PSP
movzx edx,bx
call RegisterResource ;register this PSP.
jnc @@memOK2
;
push ds
mov ds,apiDSeg
assume ds:_cwMain
push ResourceTracking
mov ResourceTracking,0
sys RelSel
sys RelMemLinear32
pop ResourceTracking
assume ds:_apiCode
pop ds
jmp @@error
;
@@memOK2: mov w[@@PSP],bx
;
;Copy parent PSP to this PSP.
;
push ds
mov es,bx
mov ds,apiDSeg
assume ds:_cwMain
mov ds,PSPSegment
assume ds:_apiCode
xor esi,esi
xor edi,edi
mov ecx,256/4
cld
rep movsd
mov ax,ds:[EPSP_RealENV] ;copy real mode environment
mov es:[EPSP_RealENV],ax ;segment.
mov eax,ds:[EPSP_ExecCount]
mov es:[EPSP_ExecCount],eax
pop ds
;
;Initialise PSP fields.
;
push fs
mov fs,apiDSeg
assume fs:_cwMain
mov fs,fs:PSPSegment
assume fs:nothing
mov es,bx
mov es:d[EPSP_Resource],0 ;Clear memory fields.
mov es:d[EPSP_INTMem],0
mov es:d[EPSP_DPMIMem],0
mov es:w[EPSP_Parent],fs ;set parent PSP.
mov es:d[EPSP_DTA],80h ;Use default PSP DTA.
mov es:w[EPSP_DTA+4],es
mov ax,fs:w[EPSP_TransProt] ;inherit current transfer buffer.
mov es:w[EPSP_TransProt],ax
mov ax,fs:w[EPSP_TransReal]
mov es:w[EPSP_TransReal],ax
mov eax,fs:d[EPSP_TransSize]
mov es:d[EPSP_TransSize],eax
mov eax,fs:d[EPSP_mcbMaxAlloc]
mov es:d[EPSP_mcbMaxAlloc],eax
mov es:d[EPSP_mcbHead],0
cmp d[@@Flags],2 ;cwLoad?
jz @@NoNext
mov fs:w[EPSP_Next],es
@@NoNext: mov es:w[EPSP_Next],0
mov es:w[PSP_Environment],0
mov es:w[EPSP_SegBase],0
mov es:w[EPSP_SegSize],0
mov es:d[EPSP_Exports],0
mov es:d[EPSP_Imports],0
mov es:d[EPSP_Links],0
mov es:w[EPSP_EntryCSEIP+4],0
mov es:w[EPSP_PSPSel],es
pop fs
;
;Update PSP linked list.
;
push es
mov es,apiDSeg
assume es:_cwMain
mov esi,es:BasePSPAddress
mov es,es:RealSegment
assume es:nothing
@@ChainPSP0: cmp es:EPSP_NextPSP[esi],0
jz @@ChainPSP1
mov esi,es:EPSP_NextPSP[esi]
jmp @@ChainPSP0
@@ChainPSP1: sys GetSelDet32
mov es:EPSP_NextPSP[esi],edx
mov es:EPSP_LastPSP[edx],esi
mov es:EPSP_NextPSP[edx],0
pop es
;
;Switch to this PSP.
;
cmp d[@@Flags],2 ;cwLoad?
jz @@NoPSwitch0
mov ah,50h
int 21h ;set new PSP.
;
;Set new DTA address.
;
@@NoPSwitch0: cmp d[@@Flags],2
jz @@NoDTA
push ds
lds edx,es:f[EPSP_DTA]
mov ah,1ah
int 21h
pop ds
;
;Preserve current state.
;
@@NoDTA: cmp d[@@Flags],2
jz @@NoSave
call SaveExecState ;do old state save.
jc @@error ;Not enough memory.
;
;Build command line.
;
@@NoSave: cmp w[@@Command+4],0
jz @@NoCommand
mov es,w[@@PSP]
mov edi,80h
mov es:d[edi],0
push ds
lds esi,f[@@Command]
movzx ecx,b[esi]
inc ecx
cld
rep movsb
mov es:b[edi],13
pop ds
;
;Check what's needed with the environment selector.
;
@@NoCommand: cmp d[@@Flags],2 ;cwLoad?
jz @@CopyEnv ;NoEnv
mov ax,w[@@Environment]
or ax,ax
jz @@ParentEnv
mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov es:w[PSP_Environment],ax
jmp @@GotEnv
@@CopyEnv: push es
mov es,apiDSeg
assume es:_cwMain
mov ax,es:PSPSegment
assume es:nothing
mov es,w[@@PSP]
mov es:w[PSP_Environment],ax
pop es
jmp @@NoEnv
;
;Need to make a copy of the parent environment string.
;
@@ParentEnv: mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov es,es:w[EPSP_Parent] ;Get parent PSP.
mov es,es:w[PSP_Environment] ;Get parents environment.
;
;Find out how long current environment is.
;
xor esi,esi
@@gp2: mov al,es:[esi] ;Get a byte.
inc esi ;/
or al,al ;End of a string?
jnz @@gp2 ;keep looking.
mov al,es:[esi] ;Double zero?
or al,al ;/
jnz @@gp2 ;keep looking.
add esi,3 ;Skip last 0 and word count.
mov ecx,esi
add ecx,256 ;allow for exec name length.
sys GetMem32
jc @@error
mov ax,es
mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov es:w[PSP_Environment],bx
mov ecx,esi ;get length again.
push ds
mov ds,ax
mov es,bx
xor esi,esi
xor edi,edi
rep movsb ;copy current strings.
pop ds
;
;Add execution path and name to environment strings.
;
@@GotEnv: mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov es,es:w[PSP_Environment]
xor esi,esi
@@gp0: mov al,es:[esi] ;Get a byte.
inc esi ;/
or al,al ;End of a string?
jnz @@gp0 ;keep looking.
mov al,es:[esi] ;Double zero?
or al,al ;/
jnz @@gp0 ;keep looking.
add esi,3 ;Skip last 0 and word count.
mov ebp,esi
;
;Now build the file name.
;
push ds
lds esi,f[@@Name]
mov al,b[esi+1]
pop ds
mov edi,ebp
cmp al,":" ;drive specification?
jz @@NoGetPath
push edi
mov ah,19h ;get current disc
int 21h
mov dl,al
add al,'A' ;make it a character
pop esi
mov es:[esi],al
inc esi
mov es:b[esi],":"
inc esi
;
push ds
push esi
lds esi,f[@@Name]
mov al,b[esi]
pop esi
pop ds
mov edi,esi
cmp al,"\"
jz @@NoGetPath
;
mov es:b[esi],"\"
inc esi
mov es:b[esi],0
mov ah,47h ;get current directory
xor dl,dl ;default drive
push ds
push es
pop ds
int 21h ;get text
pop ds
mov esi,ebp
push ds
push es
pop ds
@@gp1: lodsb
or al,al
jnz @@gp1
pop ds
dec esi
mov edi,esi
mov al,"\"
stosb
;
;Append EXE file name to EDI.
;
@@NoGetPath: push ds
lds esi,f[@@Name]
@@gp3: lodsb
stosb
or al,al
jnz @@gp3
pop ds
;
;Return to caller.
;
@@NoEnv: clc
jmp @@exit
;
;Not enough memory.
;
@@error: stc
;
@@exit: mov bx,w[@@PSP]
popm ds,es,fs,gs
ret
;
@@PSP: ;
dw 0
@@Command: ;
df 0
@@Name: ;
df 0
@@Environment: ;
dw 0
@@Flags: ;
dd 0
CreatePSP endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
DeletePSP proc near
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
mov d[@@Flags],eax
mov w[@@PSP],bx
;
cmp d[@@Flags],2
jz @@NoIRel
call LoadExecState
;
;Close all open files.
;
call LoseFileHandles
;
;Restore resources.
;
@@NoIRel: mov es,apiDSeg
assume es:_cwMain
cmp es:w[TerminationHandler],offset cwClose
jnz @@YesRelRes
cmp es:DebugDump,0
jnz @@NoNRel
@@YesRelRes: assume es:nothing
mov es,w[@@PSP]
mov bx,es:w[EPSP_Parent]
cmp d[@@Flags],2
jz @@NoPRel
mov ah,50h
int 21h ;restore old PSP.
@@NoPRel: mov bx,es
sys RelMem
cmp d[@@Flags],2
jz @@NoNRel
mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov es:w[EPSP_Next],0
@@NoNRel: ;
popm ds,es,fs,gs
ret
;
@@PSP: ;
dw ?
@@Flags: ;
dd ?
DeletePSP endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Find a module with the right main EXPORT name. If it's not already resident
;search for it on disk and load it if found.
;
;On Entry:
;
;ES:ESI - Module name linear address (ES must address 0-4G)
;
;On Exit:
;
;Carry set on error & EAX is error code else,
;
;EDI - Linear address of modules PSP.
;
;Error codes match cwLoad values.
;
;All other registers preserved.
;
FindModule proc near
pushm ebx,ecx,edx,esi,ebp,ds,es
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
;Search resident modules first.
;
push fs
mov fs,apiDSeg
assume fs:_cwMain
mov edi,fs:BasePSPAddress ;Point to start of PSP chain.
assume fs:nothing
pop fs
;
;Skip partial path if there is one.
;
push esi
movzx ecx,es:b[esi]
inc esi
mov ebx,esi
mov ebp,ecx
@@5: inc esi
cmp es:b[esi-1],"\"
jnz @@6
mov ebx,esi
mov ebp,ecx
@@6: dec ecx
jnz @@5
mov esi,ebx
;
@@imp1: mov ebx,esi
mov edx,es:EPSP_Exports[edi] ;Point to export memory.
or edx,edx ;Any exports?
jz @@imp3
mov edx,es:[edx+4] ;Point to module name.
mov ecx,ebp
cmp cl,es:[edx] ;Right name length?
jnz @@imp3
inc edx
@@imp2: mov al,es:[ebx]
cmp al,es:[edx] ;right char?
jnz @@imp3
inc ebx
inc edx
dec ecx
jnz @@imp2
;
pop esi
jmp @@imp5 ;got it!
;
@@imp3: mov edi,es:EPSP_NextPSP[edi]
or edi,edi ;check there is something else to look at.
jnz @@imp1
pop esi
;
;Shit, not a resident module so look for it on disk.
;
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugaatext1
debugaaloop2:
cmp BYTE PTR ds:[edx],0
je debugaab
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugaaloop2
debugaab:
mov edx,OFFSET debugaatext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugaaout
debugaatext1 DB 'Not a resident module...',0
debugaatext2 DB 13,10
debugaaout:
ENDIF
;
;Try current PSP's execution path.
;
push esi
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:PSPSegment
assume es:nothing
mov bx,es:w[PSP_Environment]
pop es
pushm edx,ecx
sys GetSelDet32
mov esi,edx
popm edx,ecx
@@imp3_0:
mov al,es:[esi] ;Get a byte.
inc esi ;/
or al,al ;End of a string?
jnz @@imp3_0 ;keep looking.
mov al,es:[esi] ;Double zero?
or al,al ;/
jnz @@imp3_0 ;keep looking.
add esi,3 ;Skip last 0 and word count.
;
;Copy up to last "\"
;
mov edi,offset DLLNameSpace
mov ebp,edi
@@imp3_1: mov al,es:[esi]
inc esi
mov [edi],al
inc edi
cmp al,"\"
jnz @@imp3_2
mov ebp,edi
@@imp3_2: or al,al
jnz @@imp3_1
mov edi,ebp
pop esi
cmp BYTE PTR es:[esi+2],':' ; see if module name has absolute path
jne chkmodname
cmp BYTE PTR es:[esi],4
jb chkmodname ; name not long enough for absolute path
mov edi,offset DLLNameSpace ; reset DLL path to receive module name path only
;
;Check if module name has any path in it.
;
chkmodname:
push esi
movzx ecx,es:b[esi]
inc esi
mov ebp,esi
@@0:
inc esi
cmp es:b[esi-1],"\"
jnz @@1
mov ebp,esi
@@1:
dec ecx
jnz @@0
mov ecx,esi
sub ecx,ebp
pop esi
push esi
inc esi
@@2:
cmp esi,ebp
jnc @@3
mov al,es:[esi]
mov [edi],al
inc esi
inc edi
jmp @@2
@@3:
mov b[edi],0
;
;Copy module name into work space.
;
mov edi,offset MODNameSpace
mov [edi],cl
inc edi
@@4:
mov al,es:[esi]
mov [edi],al
inc esi
inc edi
dec ecx
jnz @@4
pop esi
;
;Try and find the module.
;
push es
push ds
pop es
mov esi,offset MODNameSpace
mov edi,offset DLLNameSpace
call SearchModule ;look for module with right name.
pop es
jnc @@8
;
;Couldn't find the module so return an error.
;
mov eax,1
jmp @@error
;
;Try loading the module found.
;
@@8:
push ExecMCount
mov ExecMCount,ecx
;
;Set master PSP.
;
assume ds:nothing
mov ds,apiDSeg
assume ds:_cwMain
push PSPSegment
mov bx,BasePSP
mov ah,50h
int 21h
;
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov edx,offset DLLNameSpace
sys cwLoad ;call ourselves.
;
;Go back to origional PSP
;
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
pop PSPSegment
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
pop ExecMCount
jc @@error
;
mov bx,si ;get the PSP
pushm ecx,edx
sys GetSelDet32 ;need a 32-bit address for it.
mov edi,edx
popm ecx,edx
;
;Call DLL's initialisation code.
;
mov es:w[edi+EPSP_EntryCSEIP+4],cx
mov es:d[edi+EPSP_EntryCSEIP],edx
or cx,cx
jz @@imp5
xor eax,eax
mov ax,es:w[edi+EPSP_EntryCSEIP+4]
lar eax,eax
test eax,00400000h
jnz @@imp6_0
mov es:w[edi+EPSP_EntryCSEIP+2],cx
@@imp6_0: pushm ds,es,fs,gs
pushad
push es
pop fs
mov ds,si
mov es,si
test eax,00400000h
mov eax,0
jnz @@imp6
db 66h
@@imp6: call fs:f[edi+EPSP_EntryCSEIP]
or ax,ax
popad
popm ds,es,fs,gs
mov eax,1
jnz @@error
;
;Update modules referance count.
;
@@imp5: inc es:EPSP_Links[edi]
;
;Return module PSP address to caller.
;
xor eax,eax
clc
jmp @@imp10
;
;Couldn't find name so return error to caller.
;
@@error: stc
;
@@imp10: popm ebx,ecx,edx,esi,ebp,ds,es
ret
;
DLLNameSpace db 256 dup (0)
MODNameSpace db 256 dup (0)
FindModule endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Reverse the FindModule process.
;
;On Entry:
;
;ES:EDI - module PSP (ES must address 0-4G)
;
;This basicly DEC's the modules referance count and if it becomes zero it
;removes the module from memory.
;
UnFindModule proc near
pushm ds,es,fs,gs
pushad
;
dec es:EPSP_Links[edi]
jnz @@8
;
;Get this PSP's selector.
;
mov fs,es:EPSP_PSPSel[edi]
;
;Call DLL's exit code.
;
cmp fs:w[EPSP_EntryCSEIP+4],0
jz @@imp5
xor eax,eax
mov ax,fs:w[EPSP_EntryCSEIP+4]
lar eax,eax
pushm ds,es,fs,gs
pushad
mov ax,fs
mov ds,ax
mov es,ax
test eax,00400000h
mov eax,1
jnz @@imp6
db 66h
@@imp6: call fs:f[EPSP_EntryCSEIP]
or ax,ax
popad
popm ds,es,fs,gs
;
;Switch to the master PSP.
;
@@imp5: assume ds:nothing
mov ds,apiDSeg
assume ds:_cwMain
push PSPSegment
mov bx,BasePSP
mov ah,50h
int 21h
;
;Release module.
;
mov bx,fs
sys RelSel
;
;Go back to origional PSP
;
pop PSPSegment
assume ds:_apiCode
;
@@8: clc
popad
popm ds,es,fs,gs
ret
UnFindModule endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Search specified path for a file with the right module name.
;
;On Entry:
;
;DS:EDI - path string.
;ES:ESI - module name.
;
;On Exit:
;
;Carry set on error else,
;
;Path string specified in DS:EDI has file name appended to it.
;
;ECX - module number within file.
;
SearchModule proc near
mov ax,ds
pushm ds,es
pushad
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
mov d[@@Path],edi
mov w[@@Path+4],ax
mov d[@@Name],esi
mov w[@@Name+4],es
; MED 01/05/96
push eax
push es
mov ah,2fh ; get DTA in es:ebx
int 21h
mov DWORD PTR EntryDTAAddress,ebx
mov WORD PTR EntryDTAAddress+4,es
pop es
mov edx,OFFSET TemporaryDTA
mov ah,1ah ; set DTA in ds:edx
int 21h
pop eax
;
;Get path length so we don't have to keep scanning the string.
;
push ds
mov ds,ax
xor ecx,ecx
@@0: cmp b[edi],0
jz @@1
inc edi
inc ecx
jmp @@0
@@1: pop ds
mov d[@@Length],ecx
;
;Setup initial mask pointer.
;
mov d[@@Mask],offset @@Masks
;
;Get DTA address.
;
push es
mov ah,2fh
int 21h
mov d[@@Dta],ebx
mov w[@@Dta+4],es
pop es
;
;Work through all mask types.
;
@@2: mov esi,d[@@Mask]
cmp b[esi],0 ;end of the list?
jz @@9
;
;Add new mask to path string.
;
add d[@@Mask],4 ;move to next mask.
les edi,f[@@Path]
add edi,d[@@Length] ;point to end of path string.
mov es:b[edi],"*"
inc edi
movsd ;copy extension.
mov es:b[edi],0
;
;Work through all files with the right extension.
;
push ds
lds edx,f[@@Path]
xor cx,cx
mov ah,4eh ;find first file
int 21h
pop ds
jc @@2
jmp @@4
;
@@3: mov ah,4fh
int 21h
jc @@2
;
;Add this name to the path string?
;
@@4: les edi,f[@@DTA]
test es:b[edi+21],16 ;DIR?
jnz @@3
push ds
mov eax,d[@@Length] ;point to end of path string.
lds esi,f[@@Path]
add esi,eax
lea edi,[edi+1eh] ;point to file name.
mov ecx,13
cld
@@5: mov al,es:[edi]
mov [esi],al
inc esi
inc edi
or al,al
jz @@6
dec ecx
jnz @@5
@@6: mov b[esi],0 ;terminate the name.
pop ds
;
;Find out what the files "module" name is.
;
;
;Open the file.
;
push ds
lds edx,f[@@Path]
mov ax,3d00h
int 21h
pop ds
jc @@7
mov w[@@Handle],ax
mov bx,ax
mov d[@@Count],0
;
@@11: ;See what sort of file it is.
;
mov edx,offset @@ID
mov ecx,2
mov ah,3fh
int 21h
jc @@7
cmp ax,cx
jnz @@7
cmp w[@@ID],"ZM"
jz @@MZ
cmp w[@@ID],"P3"
jz @@3P
jmp @@7
;
;Process an MZ section.
;
@@MZ: mov edx,offset @@ID+2
mov ecx,1bh-2
mov ah,3fh
int 21h
jc @@7
cmp ax,cx
jnz @@7
cmp w[@@ID+18h],40h
jz @@LE
;
;Find out how long the MZ bit is.
;
mov ax,w[@@ID+2+2] ;get length in 512 byte blocks
; MED 04/26/96
cmp WORD PTR [@@ID+2],0
je medexe4 ; not rounded if no modulo
dec ax ;lose 1 cos its rounded up
medexe4:
add ax,ax ;mult by 2
mov dh,0
mov dl,ah
mov ah,al
mov al,dh ;mult by 256=*512
add ax,w[@@ID+2] ;add length mod 512
adc dx,0 ;add any carry to dx
mov cx,ax
sub cx,1bh ;account for the header.
sbb dx,0
xchg cx,dx ;swap round for DOS.
mov ax,4201h ;set new file offset.
int 21h
jmp @@11
;
;Process what should be an LE section.
;
@@LE: mov ecx,3ch
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h ;move to LE offset.
mov edx,offset @@ID
mov ecx,4
mov ah,3fh
int 21h ;read LE offset.
jc @@7
cmp ax,4
jnz @@7
cmp d[@@ID],0
jz @@7
mov ecx,d[@@ID]
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h ;point to LE section.
mov edx,offset @@ID+4
mov ah,3fh
mov ecx,2
int 21h ;read ID string.
jc @@7
cmp ax,2
jnz @@7
cmp w[@@ID+4],"EL"
jz medle1
IFDEF LXWORK
mov eax,DWORD PTR [@@ID+4]
mov cs:[0],al
cmp w[@@ID+4],"XL" ; MED
jnz @@7
mov cs:[0],bl
ENDIF
jmp @@7
;
;Process an LE section.
;
medle1:
mov ecx,LE_ResidentNames-2
mov dx,cx
shr ecx,16
mov ax,4201h
int 21h ;move to module name offset.
mov edx,offset @@ID+4
mov ecx,4
mov ah,3fh
int 21h ;read module name offset.
jc @@7
cmp ax,4
jnz @@7
mov ecx,d[@@ID]
add ecx,d[@@ID+4]
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h ;move to module name.
mov edx,offset @@ID
mov ecx,256
mov ah,3fh
int 21h ;read the module name.
;
;See if this module has right name.
;
push es
les edx,f[@@Name] ;point to name we're looking for.
mov edi,offset @@ID
movzx ecx,b[edi]
cmp cl,es:[edx] ;right length?
jnz @@le7
@@le5: inc edx
inc edi
mov al,es:[edx]
cmp al,[edi]
jnz @@le7
dec ecx
jnz @@le5
pop es
;
;Close the file.
;
xor bx,bx
xchg bx,w[@@Handle]
mov ah,3eh
int 21h
jmp @@8
;
@@le7: pop es
jmp @@7
;
;Process a 3P section.
;
@@3P: mov edx,offset @@ID+2
mov ecx,size NewHeaderStruc-2
mov ah,3fh
int 21h
jc @@7
cmp ax,cx
jnz @@7
sub d[NewSize+@@ID],size NewHeaderStruc
;
;Check this file has exports.
;
cmp d[NewExports+@@ID],0
jz @@3p6
;
;Skip segment definitions.
;
movzx edx,w[NewSegments+@@ID]
shl edx,3
sys cwcInfo
jc @@3p0
mov edx,eax
@@3p0: sub d[NewSize+@@ID],edx
mov cx,dx
shr edx,16
xchg cx,dx
mov ax,4201h
int 21h
;
;Skip relocations.
;
mov edx,d[NewRelocs+@@ID]
shl edx,2
or edx,edx
jz @@3p1
sys cwcInfo
jc @@3p1
mov edx,eax
@@3p1: sub d[NewSize+@@ID],edx
mov cx,dx
shr edx,16
xchg cx,dx
mov ax,4201h
int 21h
;
;Load export details.
;
mov ecx,d[NewExports+@@ID]
sys GetMemLinear32
jc @@7 ;treat memory error as no file.
mov edx,ecx
push ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
assume ds:_apiCode
sys cwcInfo
jc @@3p2
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
sub d[NewSize+@@ID],ecx
pop ds
push es
mov ax,ds
mov es,ax
mov edi,esi
sys cwcLoad
pop es
jc @@3p3
jmp @@3p4
@@3p2: push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
sub d[NewSize+@@ID],edx
pop ds
mov ecx,edx
mov edx,esi
call ReadFile
jc @@3p3
cmp eax,ecx
jz @@3p4
@@3p3: pop ds
sys RelMemLinear32
jmp @@7
@@3p4: mov ax,ds
mov es,ax
pop ds
;
;See if this module has right name.
;
push ds
lds edx,f[@@Name] ;point to name we're looking for.
mov edi,esi
add edi,es:[edi+4] ;get offset of module name.
movzx ecx,es:b[edi]
cmp cl,[edx] ;right length?
jnz @@3p7
@@3p5: inc edx
inc edi
mov al,[edx]
cmp al,es:[edi]
jnz @@3p7
dec ecx
jnz @@3p5
pop ds
;
;Release EXPORT record memory.
;
sys RelMemLinear32
;
;Close the file.
;
xor bx,bx
xchg bx,w[@@Handle]
mov ah,3eh
int 21h
jmp @@8
;
;Not this one, move to next part of the file.
;
@@3p7: pop ds
sys RelMemLinear32
@@3p6: mov edx,d[NewSize+@@ID]
mov cx,dx
shr edx,16
xchg cx,dx
mov ax,4201h
int 21h
inc d[@@Count]
jmp @@11
;
;Make sure file is closed.
;
@@7: xor bx,bx
xchg bx,w[@@Handle]
or bx,bx
jz @@3
mov ah,3eh
int 21h
jmp @@3
;
@@8: clc
jmp @@10
;
@@9: stc
;
@@10:
; MED 01/05/96
pushf
push ds
lds edx,EntryDTAAddress
mov ah,1ah ; set DTA in ds:edx
int 21h
pop ds
popf
popad
mov ecx,d[@@Count]
popm ds,es
ret
;
@@ID: ;
db 256 dup (0)
@@Handle: ;
dw 0
@@DTA: ;
df 0
@@Path: ;
df 0
@@Name: ;
df 0
@@Length: ;
dd 0
@@Count: ;
dd 0
@@Mask: ;
dd 0
@@Masks: ;
db ".DLL"
db ".EXE"
db 0
; temporary DTA storage so PSP isn't munged, MED 01/03/96
TemporaryDTA DB 80h DUP (?)
EntryDTAAddress DF 0 ; Entry DTA address
SearchModule endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Search a modules export table for name specified.
;
;On Entry:
;
;ES:EDI - Export table.
;ES:EBP - function name.
;
;On Exit:
;
;Carry set on error else,
;
;ES:EDI - matched export entry.
;
;All other registers preserved.
;
FindFunction proc near
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugamtext1
debugamloop2:
cmp BYTE PTR ds:[edx],0
je debugamb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugamloop2
debugamb:
mov edx,OFFSET debugamtext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugamout
debugamtext1 DB 'Entering FindFunction...',0
debugamtext2 DB 13,10
debugamout:
ENDIF
pushm eax,ebx,ecx,edx,esi,ebp
;
mov edx,es:[edi] ;get number of exports.
add edi,4+4 ;skip entry count and module name.
;
@@imp11: push edi
mov edi,es:[edi] ;point to name string.
mov ebx,ebp
xor ecx,ecx
mov cl,es:[edi+6]
cmp cl,es:[ebx]
jnz @@imp13
add edi,6+1
COMMENT !
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push edi
push ds
push cs
pop ds
mov edx,OFFSET debugaktext1
push cx
debugakloop2:
cmp BYTE PTR ds:[edx],0
je debugakb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugakloop2
debugakb:
pop cx
push es
pop ds
debugakloop1:
mov edx,edi
mov bx,1
mov ah,40h
int 21h
debugaka:
mov edx,OFFSET debugaktext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edi
pop edx
pop ecx
pop ebx
pop eax
jmp debugakout
debugaktext1 DB 'Checking against function: ',0
debugaktext2 DB 13,10
debugakout:
ENDIF
END COMMENT !
inc ebx
;
@@imp12: mov al,es:[edi]
cmp al,es:[ebx]
jnz @@imp13
inc edi
inc ebx
dec ecx
jnz @@imp12
jmp @@imp14
;
@@imp13: pop edi
add edi,4
dec edx
jnz @@imp11
jmp @@error
;
@@imp14: pop edi
mov edi,es:[edi]
clc
jmp @@10
;
@@error: stc
@@10: popm eax,ebx,ecx,edx,esi,ebp
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugaltext1
debugalloop2:
cmp BYTE PTR ds:[edx],0
je debugalb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugalloop2
debugalb:
mov edx,OFFSET debugaltext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugalout
debugaltext1 DB 'Done with FindFunction...',0
debugaltext2 DB 13,10
debugalout:
ENDIF
ret
FindFunction endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Load, relocate and execute the application code. All format loader.
;
;On Entry:
;
;EBX - Mode.
; 0 - Normal EXEC.
; 1 - Load for debug.
; 2 - Load for overlay.
;DS:EDX - File name.
;ES:ESI - Command line.
;CX - Environment selector, 0 to use existing copy.
;
;On Exit:
;
;Carry set on error and AX = error code else,
;
;If Mode=0
;
;AL = ErrorLevel (returned by child's terminate)
;
;If Mode=1
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI - PSP.
;DI - Auto DS.
;EBP - Segment definition memory.
;
;If Mode=2
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI - PSP.
;
;Error codes:
;
;1 - DOS file access error.
;2 - Not a recognisable format.
;3 - Not enough memory.
;
_Exec proc near
mov ax,ds
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
call DPMICopyCheck
;
;Preserve details.
;
mov d[@@Name],edx
mov w[@@Name+4],ax
mov d[@@Flags],ebx
mov d[@@Command],esi
mov w[@@Command+4],es
mov w[@@Environment],cx
mov w[@@Handle],0
;
;Try and open the file.
;
push ds
lds edx,f[@@Name]
mov ax,3d00h ;open, read only.
int 21h
pop ds
jc @@no_file_error
mov w[@@Handle],ax ;store the handle.
;
;Find out what format the current section is.
;
@@0: mov bx,w[@@Handle]
mov edx,offset @@Temp
mov ecx,2
mov ah,3fh
int 21h
jc @@file_error
cmp ax,cx
jnz @@file_error
;
cmp w[@@Temp],"ZM" ;MZ EXE?
jz @@MZ
cmp w[@@Temp],"EL" ;LE EXE?
jz @@LE
cmp w[@@Temp],"P3" ;3P EXE?
jz @@3P
IFDEF LXWORK
cmp w[@@Temp],"XL" ;LX EXE? -- MED
jz @@LE
mov cs:[0],dl
ENDIF
jmp @@file_error
;
@@MZ: ;Look for an LE offset.
;
mov bx,w[@@Handle]
mov dx,18h
xor cx,cx
mov ax,4200h
int 21h
mov edx,offset @@Temp
mov ecx,2
mov ah,3fh
int 21h ;Fetch LE offset.
jc @@file_error
cmp ax,cx
jnz @@file_error
cmp w[@@Temp],40h ;LE offset present?
jnz @@MZ2
;
;Fetch the NE/LE/LX offset.
;
mov bx,w[@@Handle]
mov dx,3ch
xor cx,cx
mov ax,4200h
int 21h
mov edx,offset @@Temp
mov ecx,4
mov ah,3fh
int 21h ;Fetch LE offset.
jc @@file_error
cmp ax,cx
jnz @@file_error
cmp d[@@Temp],0 ;any offset?
jz @@MZ2
mov eax,d[@@Temp]
mov dx,ax
shr eax,16
mov cx,ax
mov bx,w[@@Handle]
mov ax,4200h
int 21h
jmp @@0
;
@@MZ2: ;Get MZ length and skip it.
;
mov dx,2
xor cx,cx
mov ax,4200h
mov bx,w[@@Handle]
int 21h
mov edx,offset @@Temp
mov ecx,4
mov ah,3fh
mov bx,w[@@Handle]
int 21h
jc @@file_error
cmp ax,cx
jnz @@file_error
mov ax,w[@@Temp+2] ;get length in 512 byte blocks
; MED 04/26/96
cmp WORD PTR [@@Temp],0
je medexe5 ; not rounded if no modulo
dec ax ;lose 1 cos its rounded up
medexe5:
add ax,ax ;mult by 2
mov dh,0
mov dl,ah
mov ah,al
mov al,dh ;mult by 256=*512
add ax,w[@@Temp] ;add length mod 512
adc dx,0 ;add any carry to dx
mov cx,ax
xchg cx,dx ;swap round for DOS.
mov ax,4200h ;set absolute position.
mov bx,w[@@Handle]
int 21h
jmp @@0
;
;Run an LE format program.
;
@@LE: mov d[@@ExecAdd],offset LoadLE
jmp @@exec
;
;Run a 3P format program.
;
@@3P: mov d[@@ExecAdd],offset Load3P
;
;Close the file.
;
@@exec: mov bx,w[@@Handle]
mov w[@@Handle],0
mov ah,3eh
int 21h
;
;Fetch registers & call format specific loader.
;
mov edx,d[@@Name]
mov ax,w[@@Name+4]
mov ebx,d[@@Flags]
mov esi,d[@@Command]
mov es,w[@@Command+4]
mov cx,w[@@Environment]
mov ds,ax
assume ds:nothing
call cs:d[@@ExecAdd]
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
@@exit: pushf
push eax
cmp w[@@Handle],0
jz @@e0
mov bx,w[@@Handle]
mov ah,3eh
int 21h
@@e0: pop eax
popf
;
pop ds
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
mov edx,OFFSET debugajtext1
debugajloop2:
cmp BYTE PTR ds:[edx],0
je debugajb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugajloop2
debugajb:
mov edx,OFFSET debugajtext2
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugajout
debugajtext1 DB 'Done with _Exec...',0
debugajtext2 DB 13,10
debugajout:
ENDIF
ret
;
@@no_file_error: mov eax,1
stc
jmp @@exit
@@file_error: mov eax,2
stc
jmp @@exit
@@mem_error: mov eax,3
stc
jmp @@exit
;
@@Name: ;
df 0
@@Flags: ;
dd 0
@@Command: ;
df 0
@@Environment: ;
dw 0
@@Handle: ;
dw 0
@@Temp: ;
dd 0
@@ExecAdd: ;
dd 0
_Exec endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Load, relocate and execute the application code. 3P format loader.
;
;On Entry:
;
;EBX - Mode.
; 0 - Normal EXEC.
; 1 - Load for debug.
; 2 - Load for overlay.
;DS:EDX - File name.
;ES:ESI - Command line.
;CX - Environment selector, 0 to use existing copy.
;
;On Exit:
;
;Carry set on error and AX = error code else,
;
;If Mode=0
;
;AL = ErrorLevel (returned by child's terminate)
;
;If Mode=1
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI - PSP.
;DI - Auto DS.
;EBP - Segment definition memory.
;
;If Mode=2
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI - PSP.
;
;Error codes:
;
;1 - DOS file access error.
;2 - Not a 3P file.
;3 - Not enough memory.
;
Load3P proc near
mov ax,ds
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
pushm w[@@SegSS],d[@@SegMem],w[@@EntryDS]
pushm d[@@ExpMem],d[@@EntryEIP],w[@@SegCS],d[@@EntryESP]
pushm d[@@SegMem],d[@@RelocMem],d[@@ProgBase],d[@@Segs],w[@@PSP]
pushm d[@@AutoOffset],d[@@Command],w[@@Command+4],d[@@Flags]
pushm d[@@Name],w[@@Name+4],w[@@Environment],d[@@SystemFlags]
pushm d[@@ModLink],d[@@ImpMem],d[@@ImpCnt],d[@@3PStart]
;
mov d[@@Name],edx
mov w[@@Name+4],ax
mov d[@@Flags],ebx
mov d[@@Command],esi
mov w[@@Command+4],es
mov w[@@Environment],cx
;
mov w[@@PSP],0
mov w[@@Handle],0
mov d[@@SegMem],0
mov d[@@RelocMem],0
mov d[@@AutoOffset],0
mov d[@@ExpMem],0
mov d[@@ModLink],0
mov d[@@ImpMem],0
;
;Try and open the file.
;
push ds
lds edx,f[@@Name]
mov ax,3d00h ;open, read only.
int 21h
pop ds
jc @@no_file_error
mov w[@@Handle],ax ;store the handle.
;
;Check for just a 3P file with no extender.
;
@@Look3P: mov bx,w[@@Handle]
mov edx,offset apiNewHeader ;somewhere to put the info.
mov ecx,size NewHeaderStruc ;size of it.
mov ah,3fh
int 21h
jc @@file_error
cmp ax,size NewHeaderStruc ;did we read right amount?
jnz @@file_error
;
cmp w[apiNewHeader],'ZM'
jnz @@CheckNew
;
;Move back to EXE details.
;
mov bx,w[@@Handle]
mov dx,-(size NewHeaderStruc)
mov cx,-1
mov ax,4201h
int 21h ;move back to start of the header.
;
mov bx,w[@@Handle]
mov edx,offset apiExeSignature ;somewhere to put the info.
mov ecx,1bh ;size of it.
mov ah,3fh
int 21h
jc @@file_error
cmp ax,1bh ;did we read right amount?
jnz @@file_error
;
mov ax,w[apiExeLength+2] ;get length in 512 byte blocks
; MED 01/17/96
cmp WORD PTR [apiExeLength],0
je medexe3 ; not rounded if no modulo
dec ax ;lose 1 cos its rounded up
medexe3:
add ax,ax ;mult by 2
mov dh,0
mov dl,ah
mov ah,al
mov al,dh ;mult by 256=*512
add ax,w[apiExeLength] ;add length mod 512
adc dx,0 ;add any carry to dx
mov cx,ax
xchg cx,dx ;swap round for DOS.
mov ax,4200h ;set absolute position.
int 21h
jmp @@Look3P
;
@@CheckNew: cmp w[apiNewHeader],'P3' ;ID ok?
jnz @@file_error
;
;Check if this is the right module.
;
cmp ExecMCount,0
jz @@emc0
dec ExecMCount
mov edx,d[apiNewHeader+NewSize]
sub edx,size NewHeaderStruc
mov cx,dx
shr edx,16
xchg cx,dx
mov ax,4201h
int 21h
jmp @@Look3P
;
;Get file offset and store it.
;
@@emc0: mov bx,w[@@Handle]
xor cx,cx
xor dx,dx
mov ax,4201h
int 21h
shl edx,16
mov dx,ax
mov d[@@3PStart],edx
;
;Close the file again.
;
mov bx,w[@@Handle]
mov ah,3eh
int 21h
mov w[@@Handle],0
;
;Create a new PSP.
;
push ds
mov ebx,d[@@Flags]
mov cx,w[@@Environment]
les esi,f[@@command]
lds edx,f[@@name]
call CreatePSP
pop ds
mov w[@@PSP],bx
jc @@mem_error
;
;Open the input file again.
;
push ds
lds edx,f[@@Name]
mov ax,3d00h ;open, read only.
int 21h
pop ds
jc @@file_error
mov w[@@Handle],ax ;store the handle.
;
;Move past 3P header again.
;
mov edx,d[@@3PStart]
mov cx,dx
shr edx,16
xchg dx,cx
mov ax,4200h
mov bx,w[@@Handle]
int 21h
;
;Grab flags.
;
mov esi,offset apiNewHeader
mov eax,NewFlags[esi]
mov d[@@SystemFlags],eax
test b[@@SystemFlags+3],128 ;compressed?
jz @@noret
cmp d[@@Flags],1 ;debug load?
jnz @@noret
jmp @@file_error
;
;Setup auto stack stuff if its needed.
;
@@noret: mov esi,offset apiNewHeader
cmp NewEntryESP[esi],0 ;Need an automatic stack?
jnz @@NotAutoESP
mov eax,NewAutoStack[esi] ;Get auto stack size.
or eax,eax
jnz @@GotAutoSize
mov eax,1024
@@GotAutoSize: mov NewEntryESP[esi],eax ;Setup ESP value.
mov ebx,NewAlloc[esi]
add NewAlloc[esi],eax ;update memory size needed.
mov d[@@AutoOffset],ebx ;store it for later.
;
;Get EXPORT memory.
;
@@NotAutoESP: mov esi,offset apiNewHeader
mov ecx,NewExports[esi]
or ecx,ecx
jz @@NoExports0
sys GetMemLinear32
jc @@mem_error
mov d[@@ExpMem],esi
;
;Get IMPORT module link table memory.
;
@@NoExports0: mov esi,offset apiNewHeader
mov ecx,NewImportModCnt[esi]
or ecx,ecx
jz @@NoImports0
shl ecx,2 ;dword per entry.
add ecx,4 ;allow for count dword.
sys GetMemLinear32
jc @@mem_error
mov d[@@ModLink],esi
push es
mov es,apiDSeg
assume es:_cwMain
mov es,RealSegment
assume es:nothing
mov es:d[esi],0 ;clear entry count for now.
mov es,w[@@PSP]
mov es:d[EPSP_Imports],esi
pop es
;
;Get program main memory.
;
@@NoImports0: mov esi,offset apiNewHeader
mov ecx,NewAlloc[esi] ;get memory size required.
sys GetMemLinear32 ;Get segment/selector.
jc @@mem_error ;Not enough memory.
mov d[@@ProgBase],esi
;
;Get segment definition memory, selectors and details.
;
mov esi,offset apiNewHeader
movzx ecx,NewSegments[esi] ;get number of segments.
cmp d[@@AutoOffset],0 ;need auto SS?
jz @@NoAutoSeg
inc cx ;one more for the stack.
@@NoAutoSeg: push cx
shl ecx,3 ;8 bytes per entry.
sys GetMemLinear32
pop cx
jc @@mem_error
mov d[@@SegMem],esi
sys GetSels
jc @@mem_error
mov w[@@Segs],bx ;store base selector.
mov w[@@Segs+2],cx ;store number of selectors.
;
;Update programs memory and selector details in PSP and variables.
;
push es
mov es,w[@@PSP]
mov ax,w[@@Segs] ;get base selector.
mov es:w[EPSP_SegBase],ax
mov ax,w[@@Segs+2] ;get number of selectors.
shl ax,3
mov es:w[EPSP_SegSize],ax
mov eax,d[@@ProgBase] ;get memory address.
mov es:d[EPSP_MemBase],eax
mov es:d[EPSP_NearBase],eax
mov edi,offset apiNewHeader
mov eax,NewAlloc[edi] ;get memory size.
mov es:d[EPSP_MemSize],eax
pop es
;
;Read segment definitions.
;
test b[@@SystemFlags+3],128 ;compressed?
jz @@ncp0
mov bx,w[@@Handle]
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edi,d[@@SegMem]
sys cwcLoad
pop es
or ax,ax
jnz @@file_error
jmp @@ncp1
;
@@ncp0: mov esi,offset apiNewHeader
movzx ecx,NewSegments[esi] ;get number of segments.
shl ecx,3 ;8 bytes per entry.
mov bx,w[@@Handle]
mov edx,d[@@SegMem]
push ecx
push ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile
assume ds:_apiCode
pop ds
pop ecx
jc @@file_error
cmp eax,ecx
jnz @@file_error
;
;Setup a segment definition for auto-stack if needed.
;
@@ncp1: cmp d[@@AutoOffset],0
jz @@NoAutoMake
mov esi,offset apiNewHeader
movzx edi,NewSegments[esi] ;get number of segments.
mov NewEntrySS[esi],di ;store SS number.
shl edi,3 ;8 bytes per entry.
add edi,d[@@SegMem] ;offset to space for new entry.
inc NewSegments[esi] ;update number of segments.
mov eax,d[@@AutoOffset]
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov es:[edi],eax ;setup base.
mov eax,NewEntryESP[esi] ;get limit.
cmp eax,100000h
jc @@NoAutoGBit
shr eax,12
or eax,1 shl 20 ;set G bit.
@@NoAutoGBit: or eax,2 shl 21 ;set class 'stack'
mov es:[edi+4],eax ;setup limit entry.
;
;Get relocation table memory.
;
@@NoAutoMake: mov esi,offset apiNewHeader
mov ecx,NewRelocs[esi] ;get number of relocation entries.
or ecx,ecx
jz @@NoRelocsMem
shl ecx,2 ;4 bytes per entry.
sys GetMemLinear32
jc @@mem_error
mov d[@@RelocMem],esi
;
;Read relocation entries.
;
test b[@@SystemFlags+3],128 ;compressed?
jz @@ncp2
mov bx,w[@@Handle]
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edi,d[@@RelocMem]
sys cwcLoad
pop es
or ax,ax
jnz @@file_error
jmp @@NoRelocsMem
;
@@ncp2: mov esi,offset apiNewHeader
mov ecx,NewRelocs[esi] ;get number of relocation entries.
shl ecx,2 ;4 bytes per entry.
mov bx,w[@@Handle]
mov edx,d[@@RelocMem]
pushm ecx,ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile
assume ds:_apiCode
popm ecx,ds
jc @@file_error
cmp eax,ecx ;did we get enough?
jnz @@file_error
;
;Read export table.
;
@@NoRelocsMem: mov esi,offset apiNewHeader
mov ecx,NewExports[esi] ;get length of export table.
or ecx,ecx
jz @@NoExpMem
;
test b[@@SystemFlags+3],128 ;compressed?
jz @@ncp3
mov bx,w[@@Handle]
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edi,d[@@ExpMem]
sys cwcLoad
pop es
or ax,ax
jnz @@file_error
jmp @@NoExpMem
;
@@ncp3: mov bx,w[@@Handle]
mov edx,d[@@ExpMem]
pushm ecx,ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile
assume ds:_apiCode
popm ecx,ds
jc @@file_error
cmp eax,ecx ;did we get enough?
jnz @@file_error
;
;Get IMPORT memory.
;
@@NoExpMem: mov esi,offset apiNewHeader
mov ecx,NewImports[esi] ;get size of IMPORT table.
or ecx,ecx
jz @@NoImpMem1
shl ecx,2 ;4 bytes per entry.
sys GetMemLinear32
jc @@mem_error
mov d[@@ImpMem],esi
;
;Read IMPORT entries.
;
test b[@@SystemFlags+3],128 ;compressed?
jz @@ncp20
mov bx,w[@@Handle]
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edi,d[@@ImpMem]
sys cwcLoad
pop es
or ax,ax
jnz @@file_error
jmp @@NoImpMem1
;
@@ncp20: mov esi,offset apiNewHeader
mov ecx,NewImports[esi] ;get size of IMPORT table.
mov bx,w[@@Handle]
mov edx,d[@@ImpMem]
pushm ecx,ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile
assume ds:_apiCode
popm ecx,ds
jc @@file_error
cmp eax,ecx ;did we get enough?
jnz @@file_error
;
;Read exe image.
;
@@NoImpMem1: mov esi,offset apiNewHeader
test NewFlags[esi],1 shl 31 ;compressed?
jz @@NotComp
mov bx,w[@@Handle]
push es
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov edi,d[@@ProgBase]
sys cwcLoad
pop es
or ax,ax
jnz @@file_error
jmp @@ImageLoaded
;
@@NotComp: test NewFlags[esi],1 shl 30
jz @@LoadAll
jmp @@LoadVMM
@@LoadAll: mov edx,d[@@ProgBase]
mov ecx,NewLength[esi] ;get image length.
mov bx,w[@@Handle]
pushm ecx,ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile ;read the file.
assume ds:_apiCode
popm ecx,ds
jc @@file_error ;problems problems.
cmp eax,ecx ;did we get right amount?
jnz @@file_error
jmp @@ImageLoaded
;
;Break the file read up into 8K chunks that suit the relocations.
;
@@LoadVMM: mov eax,offset apiNewHeader
mov eax,NewRelocs[eax] ;get number of relocation entries.
mov d[@@SL_RelocLeft],eax
mov eax,d[@@RelocMem]
mov d[@@SL_RelocPnt],eax
mov eax,offset apiNewHeader
mov eax,NewLength[eax]
mov d[@@SL_LoadLeft],eax
mov eax,d[@@ProgBase]
mov d[@@SL_LoadPnt],eax
mov d[@@EntryEIP],0
;
@@sl0: ;Anything left to load?
;
cmp d[@@SL_LoadLeft],0
jz @@ImageLoaded
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
;
;Work out how much we should load.
;
mov ecx,d[@@SL_LoadLeft]
cmp d[@@SL_RelocLeft],0
jz @@sl3
mov esi,d[@@SL_RelocPnt]
mov eax,es:[esi] ;get fixup address.
and eax,0FFFFFFFh
add eax,4 ;allow for cross page fixup.
add eax,8191
and eax,not 8191 ;get terminal offset.
mov ebx,d[@@SL_LoadPnt]
sub ebx,d[@@ProgBase]
sub eax,ebx ;get relative offset.
cmp eax,ecx
jnc @@sl1
mov ecx,eax
;
;Load next program chunk.
;
@@sl1:
or ecx,ecx
jnz @@sl3
mov eax,d[@@EntryEIP]
or bx,-1
mov es,bx
@@sl3:
mov edx,d[@@SL_LoadPnt]
mov bx,w[@@Handle]
pushm ecx,ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
call ReadFile ;read the file.
assume ds:_apiCode
popm ecx,ds
jc @@file_error ;problems problems.
cmp eax,ecx ;did we get right amount?
jnz @@file_error
;
;Update variables.
;
add d[@@SL_LoadPnt],ecx
sub d[@@SL_LoadLeft],ecx
;
;Process all fixups in range of what we loaded.
;
mov esi,d[@@SL_RelocPnt]
mov ecx,d[@@SL_RelocLeft]
mov fs,w[@@PSP]
;
mov bx,w[@@Segs]
mov edi,fs:d[EPSP_MemBase]
add edi,fs:d[EPSP_MemSize]
mov dx,fs:w[EPSP_SegSize]
shr dx,3
@@SL_RelocLoop: or ecx,ecx
jz @@SL_DoneRelocs
mov ebp,es:[esi] ;get linear offset.
mov eax,ebp
and ebp,0FFFFFFFh ;Lose relocation type.
shr eax,28 ;Get relocation type.
add ebp,d[@@ProgBase] ;get linear address.
cmp ebp,edi
jnc @@file_error2
or al,al
jz @@SL_Seg16
dec al
jz @@SL_Offset32
jmp @@file_error2
;
@@SL_Offset32: mov eax,ebp
add eax,4-1
cmp eax,d[@@SL_LoadPnt] ;beyond what we loaded?
jnc @@SL_DoneRelocs
mov eax,es:[ebp] ;Get offset.
add eax,d[@@ProgBase]
cmp eax,edi ;Beyond program?
jnc @@file_error2
mov eax,d[@@ProgBase]
add es:d[ebp],eax ;Do the relocation.
jmp @@SL_NextReloc
;
@@SL_Seg16: mov eax,ebp
add eax,2-1
cmp eax,d[@@SL_LoadPnt] ;beyond what we loaded?
jnc @@SL_DoneRelocs
mov ax,es:[ebp] ;get selector number.
cmp ax,dx
jnc @@file_error2
shl ax,3 ;*8 for selector value.
add ax,bx ;add base selector.
mov es:[ebp],ax ;set segment selector.
;
@@SL_NextReloc:
add esi,4 ;next relocation entry.
inc d[@@EntryEIP]
dec ecx
jnz @@SL_RelocLoop
;
@@SL_DoneRelocs:
mov d[@@SL_RelocPnt],esi
mov d[@@SL_RelocLeft],ecx
mov esi,offset apiNewHeader
mov NewRelocs[esi],ecx
jmp @@sl0
;
;Close the file now we're done with it.
;
@@ImageLoaded: pushm ds,ds
popm es,fs
;
mov bx,w[@@Handle] ;grab handle again,
mov w[@@Handle],0
mov ah,3eh ;and close it.
int 21h
;
;Process relocations.
;
mov esi,offset apiNewHeader
mov ecx,NewRelocs[esi] ;get number of relocation entries.
or ecx,ecx
jz @@DoneReloc
mov esi,d[@@RelocMem]
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov fs,w[@@PSP]
;
mov d[@@EntryEIP],0
mov bx,w[@@Segs]
mov edi,fs:d[EPSP_MemBase]
add edi,fs:d[EPSP_MemSize]
mov dx,fs:w[EPSP_SegSize]
shr dx,3
@@RelocLoop: mov ebp,es:[esi] ;get linear offset.
mov eax,ebp
and ebp,0FFFFFFFh ;Lose relocation type.
shr eax,28 ;Get relocation type.
add ebp,d[@@ProgBase] ;get linear address.
cmp ebp,edi
jnc @@file_error2
or al,al
jz @@Seg16
dec al
jz @@Offset32
jmp @@file_error2
;
@@Offset32: mov eax,es:[ebp] ;Get offset.
add eax,d[@@ProgBase]
cmp eax,edi ;Beyond program?
jnc @@file_error2
mov eax,d[@@ProgBase]
add es:d[ebp],eax ;Do the relocation.
jmp @@NextReloc
;
@@Seg16: mov ax,es:[ebp] ;get selector number.
cmp ax,dx
jnc @@file_error2
shl ax,3 ;*8 for selector value.
add ax,bx ;add base selector.
mov es:[ebp],ax ;set segment selector.
;
@@NextReloc: add esi,4 ;next relocation entry.
inc d[@@EntryEIP]
dec ecx
jnz @@RelocLoop
pushm ds,ds
popm es,fs
;
;Set selector details.
;
@@DoneReloc: mov esi,offset apiNewHeader
movzx ecx,NewSegments[esi] ;get number of segments.
mov esi,d[@@SegMem]
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov bx,w[@@Segs] ;base selector.
@@SegLoop: pushm ebx,ecx,esi
;
mov eax,es:[esi+4] ;Get limit.
mov ecx,eax
and ecx,0fffffh ;mask to 20 bits.
test eax,1 shl 20 ;G bit set?
jz @@NoGBit
shl ecx,12
or ecx,4095
@@NoGBit: or ecx,ecx
jz @@NoDecLim
cmp ecx,-1
jz @@NoDecLim
dec ecx
@@NoDecLim: mov edx,es:[esi] ;get base.
;
test eax,1 shl 27 ;FLAT segment?
jz @@NotFLATSeg
;
push fs
mov fs,w[@@PSP]
mov fs:d[EPSP_NearBase],0 ;Make sure NEAR functions work.
pop fs
;
add edx,d[@@ProgBase]
or ecx,-1 ;Update the limit.
xor edx,edx
jmp @@DoSegSet
;
@@NotFLATSeg: add edx,d[@@ProgBase] ;offset within real memory.
;
@@DoSegSet: sys SetSelDet32
mov cx,w[@@SystemFlags] ;use default setting.
shr cx,14
xor cl,1
or cl,b[@@SystemFlags+2]
and cl,1
call _DSizeSelector
;
mov eax,es:[esi+4] ;Get class.
shr eax,21 ;move type into useful place.
and eax,0fh ;isolate type.
or eax,eax
jz @@CodeSeg
jmp @@SegDone
;
@@CodeSeg: mov eax,es:[esi+4] ;Get type bits.
mov cx,0 ;Set 16 bit seg.
test eax,1 shl 25
jnz @@Default
mov cx,1
test eax,1 shl 26 ;32 bit seg?
jnz @@Default
mov cx,w[@@SystemFlags] ;use default setting.
shr cx,14
and cx,1 ;get code size
xor cx,1 ;flip it for selector function.
@@Default: sys CodeSel
;
@@SegDone: popm ebx,ecx,esi
add esi,8 ;next definition.
add ebx,8 ;next selector.
dec ecx
jnz @@SegLoop
;
;Update export table values.
;
cmp d[@@ExpMem],0
jz @@exp9
push es
mov es,w[@@PSP]
mov esi,d[@@ExpMem]
mov edi,d[@@SegMem]
mov es:d[EPSP_Exports],esi
mov dx,es:[EPSP_SegBase]
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
mov ecx,es:[esi]
mov ebp,esi
add esi,4
;
;Do module name entry.
;
add es:[esi],ebp ;turn offset into an address.
add esi,4
;
;Do all other entries.
;
@@exp0: add es:[esi],ebp ;turn offset into an address.
mov ebx,es:[esi] ;get address of export entry.
movzx eax,es:w[ebx+4] ;get segment def.
add es:w[ebx+4],dx ;update seg
shl eax,3
add eax,edi ;point into seg defs.
test es:d[eax+4],1 shl 27 ;FLAT seg?
jz @@exp1
mov eax,d[@@ProgBase]
add es:d[ebx],eax ;update to reflect FLAT
@@exp1: add esi,4
dec ecx
jnz @@exp0
pop es
@@exp9: ;
;
;Setup entry regs.
;
mov esi,offset apiNewHeader
;
mov ebx,NewEntryEIP[esi] ;get entry address.
movzx eax,NewEntryCS[esi]
shl eax,3
add ax,w[@@Segs]
mov w[@@SegCS],ax
sub ax,w[@@Segs]
add eax,d[@@SegMem] ;point to this segments entry.
test es:d[eax+4],1 shl 27 ;FLAT segment?
jz @@NotFLATEIP
add ebx,es:[eax] ;include segments offset within image.
add ebx,d[@@ProgBase]
@@NotFLATEIP: mov d[@@EntryEIP],ebx
;
mov ebx,NewEntryESP[esi]
movzx eax,NewEntrySS[esi]
shl eax,3
add ax,w[@@Segs]
mov w[@@SegSS],ax
sub ax,w[@@Segs]
add eax,d[@@SegMem] ;point to this segments entry.
test es:d[eax+4],1 shl 27 ;FLAT segment?
jz @@NotFLATESP
add ebx,es:[eax] ;include segments offset within image.
add ebx,d[@@ProgBase]
@@NotFLATESP: mov d[@@EntryESP],ebx
;
push es
mov es,w[@@PSP]
mov ax,es
pop es
cmp NewAutoDS[esi],0
jz @@NotAUTODS
mov ax,NewAutoDS[esi]
dec ax
shl ax,3
add ax,w[@@Segs]
@@NotAUTODS: mov w[@@EntryDS],ax
;
;Convert import module names to pointers to export tables.
;
cmp d[@@ImpMem],0 ;any imports?
jz @@imp9
mov d[@@ImpCnt],0 ;Clear the counter.
mov es,apiDSeg
assume es:_cwMain
mov es,es:RealSegment
assume es:nothing
@@imp0: mov esi,d[@@ImpMem]
add esi,es:d[esi] ;move to module name list.
mov eax,d[@@ImpCnt]
cmp eax,es:d[esi] ;Done all modules?
jnc @@imp6
add esi,es:[esi+4+eax*4] ;Point to this module name.
;
;Try and find the module.
;
call FindModule
jnc @@got_module
;
;Put module's name into command line error message.
;
;ES:ESI is the name string.
;
push ds
push ax
mov ds,apiDSeg
assume ds:_cwMain
cmp ax,1
jnz @@egm1
mov edi,offset ErrorM10_T
movzx ecx,es:b[esi]
inc esi
mov b[edi],'"'
inc edi
@@egm0: mov al,es:[esi]
mov [edi],al
inc esi
inc edi
dec ecx
jnz @@egm0
mov b[edi+0],'"'
mov b[edi+1],13
mov b[edi+2],10
mov b[edi+3],"$"
@@egm1: pop ax
assume ds:_apiCode
pop ds
stc
jmp @@error
;
@@got_module: ;Update the module link table and usage count.
;
mov esi,d[@@ModLink]
inc es:d[esi] ;update count.
mov eax,d[@@ImpCnt]
mov es:[esi+4+eax*4],edi ;store EPSP link pointer.
;
;Move onto next module name.
;
inc d[@@ImpCnt]
jmp @@imp0
;
;Now it's time to work through the relocations performing the fixups.
;
@@imp6: mov esi,d[@@ImpMem]
add esi,es:d[esi+8] ;move to fixup list.
mov eax,es:[esi] ;get number of entries.
or eax,eax
jz @@imp9
mov d[@@ImpCnt],eax
add esi,4
@@imp7: xor eax,eax
mov al,es:[esi]
mov d[@@ImpType],eax
mov eax,es:[esi+1]
mov d[@@ImpFlags],eax
add esi,1+4
;
;Point to the right modules export list.
;
mov ecx,d[@@ImpFlags] ;get flags
shr ecx,30
xor eax,eax
@@imp8: shl eax,8
mov al,es:[esi]
inc esi
dec ecx
jnz @@imp8
mov edi,d[@@ModLink]
mov edi,es:[edi+4+eax*4]
mov edi,es:EPSP_Exports[edi]
;
;Point to the import name string.
;
mov ecx,d[@@ImpFlags]
shr ecx,28
and ecx,3
xor eax,eax
@@imp10: shl eax,8
mov al,es:[esi]
inc esi
dec ecx
jnz @@imp10
;
;Ordinal or string import?
;
test d[@@ImpType],128 ;ordinal?
jz @@imp14
cmp es:[edi],eax ;check number of entries.
jc @@file_error
mov edi,es:[edi+4+eax*4]
jmp @@imp11
;
@@imp14: mov ebp,d[@@ImpMem]
add ebp,es:[ebp+4] ;point to name list.
add ebp,es:[ebp+4+eax*4] ;point to name string.
;
;Try and find name string in export list.
;
call FindFunction
jc @@file_error
;
@@imp11: ;Found the right entry, now do the fixup.
;
mov ebx,d[@@ImpFlags]
and ebx,0FFFFFFFh
add ebx,d[@@ProgBase]
mov edx,es:[edi]
xor ecx,ecx
mov cx,es:[edi+4]
mov eax,d[@@ImpType]
;
;Check if this is self relative.
;
test eax,64
jz @@imp15
and eax,63
mov edx,ebx ;must be flat.
cmp eax,1
jz @@imp18
mov edx,d[@@ImpFlags]
and edx,0FFFFFFFh
@@imp18: add edx,2
test eax,1
jz @@imp16
add edx,2
@@imp16: sub edx,es:[edi]
neg edx
@@imp15: and eax,63
or eax,eax
jz @@imp_offset16
dec eax
jz @@imp_offset32
dec eax
jz @@imp_pointer16
dec eax
jz @@imp_pointer32
dec eax
jz @@imp_base
jmp @@file_error
;
;Do a 16-bit offset fixup.
;
@@imp_offset16: mov es:[ebx],dx
jmp @@imp17
;
;Do a 32-bit offset fixup.
;
@@imp_offset32: mov es:[ebx],edx
jmp @@imp17
;
;Do a 16-bit pointer fixup.
;
@@imp_pointer16: mov es:[ebx],dx
mov es:[ebx+2],cx
jmp @@imp17
;
;Do a 32-bit pointer fixup.
;
@@imp_pointer32: mov es:[ebx],edx
mov es:[ebx+4],cx
jmp @@imp17
;
;Do a base fixup.
;
@@imp_base: mov es:[ebx],cx
;
@@imp17: dec d[@@ImpCnt]
jnz @@imp7
@@imp9: ;
;
;Lose relocation memory.
;
mov esi,d[@@RelocMem]
sys RelMemLinear32 ;release relocation list memory.
mov d[@@RelocMem],0
;
;Lose import memory.
;
mov esi,d[@@ImpMem] ;release IMPORT memory.
or esi,esi
jz @@NoRelImp9
sys RelMemLinear32
mov d[@@ImpMem],0
;
;Lose segment definitions.
;
@@NoRelImp9: cmp d[@@Flags],1
jz @@NoSegMemRel
mov esi,d[@@SegMem]
sys RelMemLinear32 ;release segment memory.
mov d[@@SegMem],0
;
;Check if this is an exec or just a load.
;
@@NoSegMemRel: cmp d[@@Flags],0
jz @@Exec
;
;Switch back to parents PSP if this is a debug load.
;
cmp d[@@Flags],2
jz @@NoPSwitch2
push fs
mov fs,w[@@PSP]
mov bx,fs:w[EPSP_Parent]
pop fs
mov ah,50h
int 21h
mov ebp,d[@@SegMem]
;
;Return program details to caller.
;
@@NoPSwitch2: mov edx,d[@@EntryEIP]
mov cx,w[@@SegCS]
mov eax,d[@@EntryESP]
mov bx,w[@@SegSS]
mov si,w[@@PSP]
mov di,w[@@EntryDS]
clc
jmp @@exit
;
;Run it.
;
@@Exec: mov eax,d[@@Flags]
mov ebx,d[@@EntryEIP]
mov cx,w[@@SegCS]
mov edx,d[@@EntryESP]
mov si,w[@@SegSS]
mov di,w[@@PSP]
mov bp,w[@@EntryDS]
call ExecModule
clc
;
;Shut down anything still hanging around.
;
@@error: pushf
push ax
;
;Make sure file is closed.
;
pushf
xor bx,bx
xchg bx,w[@@Handle]
or bx,bx
jz @@NoClose
mov ah,3eh
int 21h
;
;Make sure all work spaces are released.
;
@@NoClose: mov esi,d[@@RelocMem]
or esi,esi
jz @@NoRelRel
sys RelMemLinear32 ;release relocation list memory.
mov d[@@RelocMem],0
@@NoRelRel: mov esi,d[@@SegMem]
or esi,esi
jz @@NoSegRel
sys RelMemLinear32 ;release segment memory.
mov d[@@SegMem],0
@@NoSegRel: mov esi,d[@@ImpMem]
or esi,esi
jz @@NoImpRel
sys RelMemLinear32
;
;Restore previous state.
;
@@NoImpRel: popf
jnc @@RelPSP
cmp w[@@PSP],0
jz @@NoRelRes
;
;Restore vectors & DPMI state.
;
@@RelPSP: pushm ds,ds,ds
popm es,fs,gs
mov eax,d[@@Flags]
mov bx,w[@@PSP]
call DeletePSP
;
;Return to caller.
;
@@NoRelRes: pop ax
popf
;
@@exit: popm d[@@ModLink],d[@@ImpMem],d[@@ImpCnt],d[@@3PStart]
popm d[@@Name],w[@@Name+4],w[@@Environment],d[@@SystemFlags]
popm d[@@AutoOffset],d[@@Command],w[@@Command+4],d[@@Flags]
popm d[@@SegMem],d[@@RelocMem],d[@@ProgBase],d[@@Segs],w[@@PSP]
popm d[@@ExpMem],d[@@EntryEIP],w[@@SegCS],d[@@EntryESP]
popm w[@@SegSS],d[@@SegMem],w[@@EntryDS]
;
popm ds,es,fs,gs
ret
;
;Not enough memory error.
;
@@mem_error: mov ax,3
stc
jmp @@error
;
;Couldn't find the file.
;
@@no_file_error: mov ax,1
stc
jmp @@error
;
;Not a 3P file.
;
@@file_error: mov ax,2
stc
jmp @@error
;
;Corrupt file.
;
@@file_error2: mov eax,d[@@EntryEIP] ;Get the relocation number.
push ds
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov b[ErrorM11_0+0]," "
mov b[ErrorM11_0+1]," "
mov b[ErrorM11_0+2]," "
mov ecx,8
mov edi,offset ErrorM11_1
call Bin2HexA
assume ds:_apiCode
pop ds
mov ax,2
stc
jmp @@error
;
@@Name: ;
df 0,0
@@Environment: ;
dw 0
@@SystemFlags: ;
dd ?
@@AutoOffset: ;
dd ?
@@Command: ;
df ?,0
@@Flags: ;
dd 0
@@ErrorCode: ;
dw 0 ;error number.
@@Handle: ;
dw 0 ;file handle.
@@EntryEIP: ;
dd 0
@@SegCS: ;
dw 0
@@EntryESP: ;
dd 0
@@SegSS: ;
dw 0
@@SegMem: ;
dd 0
@@RelocMem: ;
dd 0
@@ProgBase: ;
dd 0
@@Segs: ;
dd 0
@@PSP: ;
dw 0
@@EntryDS: ;
dw 0
@@ExpMem: ;
dd 0
@@ModLink: ;
dd 0
@@ImpMem: ;
dd 0
@@ImpCnt: ;
dd 0
@@ImpFlags: ;
dd 0
@@ImpType: ;
dd 0
@@3PStart: ;
dd 0
@@SL_RelocPnt: ;
dd 0
@@SL_RelocLeft: ;
dd 0
@@SL_LoadPnt: ;
dd 0
@@SL_LoadLeft: ;
dd 0
Load3P endp
;-------------------------------------------------------------------------
;
;Execute module.
;
;On Entry:
;
;EAX - Flags.
;EBX - Entry EIP
;CX - Entry CS
;EDX - Entry ESP
;SI - Entry SS
;DI - Entry ES
;BP - Entry DS
;
ExecModule proc near
pushm ds,es
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
pushm d[@@Flags],d[@@EntryEIP],w[@@EntryCS],d[@@EntryESP]
pushm w[@@EntrySS],w[@@EntryES],w[@@EntryDS],w[@@PSP]
;
mov d[@@Flags],eax
mov d[@@EntryEIP],ebx
mov w[@@EntryCS],cx
mov d[@@EntryESP],edx
mov w[@@EntrySS],si
mov w[@@EntryES],di
mov w[@@EntryDS],bp
mov w[@@PSP],di
;
push es
mov es,di
mov es:d[EPSP_Links],8000000h
pop es
;
;Patch Int 21h for function 4ch.
;
push w[@@OldInt21h+6]
mov w[@@OldInt21h+6],0
mov eax,d[@@OldInt21h]
or ax,w[@@OldInt21h+4]
or eax,eax ;Already patched?
jnz @@NoPatch21h
;
mov w[@@OldInt21h+6],-1
mov bl,21h
sys GetVect
test apiSystemFlags,1 ;16/32 bit?
jz @@Use32Bit100
mov w[@@OldInt21h+2],cx
mov w[@@OldInt21h],dx
jmp @@Use16Bit100
@@Use32Bit100: mov w[@@OldInt21h+4],cx
mov d[@@OldInt21h],edx
@@Use16Bit100: mov bl,21h
mov cx,cs
mov edx,offset @@Int21Patch
sys SetVect ;put us in the running.
;
;Patch exception termination handler address.
;
@@NoPatch21h: mov es,apiDSeg
assume es:_cwMain
push es:d[TerminationHandler]
push es:d[TerminationHandler+4]
mov es:w[TerminationHandler+4],cs
mov es:d[TerminationHandler],offset @@KillIt
assume es:nothing
mov es,w[@@PSP]
mov es:d[EPSP_SSESP],esp
mov es:w[EPSP_SSESP+4],ss
lss esp,f[@@EntryESP] ;fetch new stack address.
xor eax,eax
mov ebx,eax
mov ecx,eax
mov edx,eax
mov esi,eax
mov edi,eax
mov ebp,eax
mov fs,ax
mov gs,ax
mov ds,cs:w[@@EntryDS]
sti
assume ds:nothing
jmp cs:f[@@EntryEIP] ;pass control to program.
;
@@Int21Patch: cmp ah,4ch ;terminate?
jz @@CheckKillIt
cmp ah,31h ;TSR?
jnz @@OldVect
;
;Clean things up and exit.
;
mov ax,cs:apiDSeg
mov ds,ax
assume ds:_cwMain
mov ax,TSRSize
assume ds:nothing
mov edi,offset Int21Buffer
push ds
pop es
mov Real_EAX[edi],3100h
mov Real_EDX[edi],eax
mov bl,21h
sys IntXX
jmp @@KillIt ;just incase!
;
@@OldVect: test cs:apiSystemFlags,1 ;16/32?
jz @@Use32Bit101
db 66h
jmp cs:f[@@OldInt21h] ;pass control to old handler.
@@Use32Bit101: jmp cs:f[@@OldInt21h]
;
@@CheckKillIt: push ds
mov ds,cs:apiDSeg
assume ds:_cwMain
cmp Int21hExecCount,0
assume ds:nothing
pop ds
jnz @@OldVect
;
;Clean things up and return to caller.
;
@@KillIt: mov ds,cs:apiDDSeg ;make our data addressable.
assume ds:_apiCode
mov w[@@errorcode],ax
mov es,w[@@PSP]
lss esp,es:f[EPSP_SSESP]
mov es,apiDSeg
assume es:_cwMain
pop es:d[TerminationHandler+4]
pop es:d[TerminationHandler]
assume es:nothing
pushm ds,ds,ds
popm es,fs,gs
sti ;turn interupts back on.
;
cmp w[@@OldInt21h+6],0
jz @@NoRel21h
test apiSystemFlags,1 ;16/32?
jz @@Use32Bit102
mov cx,w[@@OldInt21h+2]
movzx edx,w[@@OldInt21h]
jmp @@Use16Bit102
@@Use32Bit102: mov cx,w[@@OldInt21h+4]
mov edx,d[@@OldInt21h]
@@Use16Bit102: mov bl,21h
sys SetVect ;restore old handler.
@@NoRel21h: pop w[@@OldInt21h+6]
;
;Get mouse event target state.
;
push ds
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov ds,w[Int33hExtension+20] ;Get mouse data segment.
assume ds:_Int33h
xor eax,eax
xor ebx,ebx
cmp Int33hUserOK,0
jz @@meventnodum
test cs:apiSystemFlags,1
jz @@mevent32
movzx eax,w[Int33hUserCode]
movzx ebx,w[Int33hUserCode+2]
jmp @@mevent16
@@mevent32: mov eax,d[Int33hUserCode]
movzx ebx,w[Int33hUserCode+4]
@@mevent16: cmp bx,Int33hCSeg
jnz @@meventnodum
cmp eax,offset Int33hDummy
jnz @@meventnodum
xor eax,eax
xor ebx,ebx
@@meventnodum: mov ds,Int33hDSeg
assume ds:_cwMain
mov MouseETarget,eax
mov MouseETarget+4,ebx
pop ds
assume ds:_apiCode
;
; mov ax,0 ;reset mouse if present.
; int 33h
mov ax,w[@@errorcode]
;
popm w[@@EntrySS],w[@@EntryES],w[@@EntryDS],w[@@PSP]
popm d[@@Flags],d[@@EntryEIP],w[@@EntryCS],d[@@EntryESP]
popm ds,es
ret
;
@@OldInt21h: ;
df 0,0
@@errorcode: ;
dw 0
@@Flags: ;
dd 0
@@EntryEIP: ;
dd 0
@@EntryCS: ;
dw 0
@@EntryESP: ;
dd 0
@@EntrySS: ;
dw 0
@@EntryES: ;
dw 0
@@EntryDS: ;
dw 0
@@PSP: ;
dw 0
ExecModule endp
;-------------------------------------------------------------------------
;
;Convert number into ASCII Hex version.
;
;On Entry:-
;
;EAX - Number to convert.
;CX - Digits to do.
;DS:EDI - Buffer to put string in.
;
Bin2HexA proc near
pushm eax,ebx,ecx,edx,edi
movzx ecx,cx
mov ebx,offset HexTableA
add edi,ecx
dec edi
mov edx,eax
@@0: mov al,dl
shr edx,4
and al,15
xlat cs:[ebx]
mov [edi],al
dec edi
dec ecx
jnz @@0
popm eax,ebx,ecx,edx,edi
push ecx
movzx ecx,cx
add edi,ecx
pop ecx
ret
HexTableA db '0123456789ABCDEF'
Bin2HexA endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
LosefileHandles proc near
if 0
pushm ds,es,fs
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
mov fs,PSPSegment
cmp fs:w[PSP_HandlePtr+2],0
jz @@donehandles
les di,fs:d[PSP_HandlePtr]
mov cx,fs:w[PSP_Handles]
if 0
@@RelHandles: cmp es:b[di],255
jz @@NoRelHandle
movzx bx,es:b[di]
mov ah,3eh
int 21h
@@NoRelHandle: inc di
dec cx
jnz @@RelHandles
endif
mov ax,fs
mov bx,es
cmp ax,bx
jz @@donehandles
sys RelMem
if 0
;
;Reduce real mode handle count.
;
mov edi,offset Int21Buffer
mov ax,TotalHandles ;get current count.
sub ax,fs:w[PSP_Handles]
or ax,1 ;force bit 0 for DOS bug.
mov [edi].Real_EAX,6700h
mov [edi].Real_EBX,eax
mov bl,21h
push ds
pop es
sys IntXX
sub TotalHandles,20 ;update total handle count.
endif
@@donehandles:
popm ds,es,fs
endif
ret
assume ds:_apiCode
LosefileHandles endp
;-------------------------------------------------------------------------
;
;Read some data from a file.
;
;On Entry:
;
;DS:EDX - Address to read to.
;ECX - length to read.
;EBX - file handle.
;
;On Exit:
;
;EAX - bytes read.
;
ReadFile proc near
call DPMICopyCheck
pushm ecx,edx,esi
xor esi,esi ;reset length read.
@@0: pushm ebx,ecx,edx,esi
cmp ecx,65535 ;size of chunks to load.
jc @@1
mov ecx,65535 ;as close to 64k as can get.
@@1: mov ah,3fh
int 21h ;read from the file.
popm ebx,ecx,edx,esi
jc @@2 ;DOS error so exit NOW.
movzx eax,ax ;get length read.
add esi,eax ;update length read counter.
add edx,eax ;move memory pointer.
sub ecx,eax ;update length counter.
jz @@2 ;read as much as was wanted.
or eax,eax ;did we read anything?
jnz @@0
@@2: mov eax,esi
popm ecx,edx,esi
ret
ReadFile endp
;-------------------------------------------------------------------------
;
;Patch exceptions to do register dump and terminate.
;
PatchExc proc near
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
;Patch some interrupts.
;
mov bl,23h
sys GetVect
test apiSystemFlags,1
jz @@iUse32
mov w[OldInt23],dx
mov w[OldInt23+2],cx
jmp @@iDone3216
@@iUse32: mov d[OldInt23],edx
mov w[OldInt23+4],cx
@@iDone3216: mov edx,offset Int23Handler
mov cx,cs
mov bl,23h
sys SetVect
;
mov bl,24h
sys GetVect
test apiSystemFlags,1
jz @@i24Use32
mov w[OldInt24],dx
mov w[OldInt24+2],cx
jmp @@i24Done3216
@@i24Use32: mov d[OldInt24],edx
mov w[OldInt24+4],cx
@@i24Done3216: mov edx,offset Int24Handler
mov cx,cs
mov bl,24h
sys SetVect
;
;Patch 1Bh vector.
;
;
;Get a call back.
;
pushm ds,es,ds
pop es
mov esi,offset CtrlBrkEvent
mov edi,offset CtrlBrkEventTab
push cs
pop ds
sys GetCallBack
popm ds,es
jc @@0
;
;Get current protected mode 1Bh vector.
;
pushm cx,dx
mov bl,1bh
sys GetVect
test apiSystemFlags,1
jz @@1
movzx edx,dx
@@1: mov d[OldInt1BhP],edx
mov w[OldInt1BhP+4],cx
;
;Install our own handler.
;
mov edx,offset Int1bHandler
mov cx,cs
mov bl,1bh
sys SetVect
popm cx,dx
;
;Get current real mode 1Bh vector.
;
pushm cx,dx
mov al,1bh
sys GetRVect
mov w[OldInt1bh],dx
mov w[OldInt1bh+2],cx
popm cx,dx
mov w[Int1bhcall],dx
mov w[Int1bhcall+2],cx
;
;Install call-back.
;
mov bl,1bh
sys SetRVect
@@0: mov ds,apiDSeg
assume ds:_cwMain
or apiExcepPatched,-1
assume ds:_apiCode
;
pop ds
db 66h
retf
PatchExc endp
;-------------------------------------------------------------------------
;
;Remove exception patchs.
;
UnPatchExc proc near
push ds
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
;Release real mode hardware interupt vectors and call back entries.
;
cmp d[OldInt1bh],0
jz @@no1b
mov dx,w[OldInt1bh]
mov cx,w[OldInt1bh+2]
mov bl,1bh
sys SetRVect
mov cx,w[Int1bhcall+2]
mov dx,w[Int1bhcall]
sys RelCallBack
mov edx,d[OldInt1bhP]
mov cx,w[OldInt1bhP+4]
mov bl,1bh
sys SetVect
;
@@no1b: cmp d[OldInt23],0
jz @@i0
test apiSystemFlags,1
jz @@iUse32
mov dx,w[OldInt23]
mov cx,w[OldInt23+2]
jmp @@iDone3216
@@iUse32: mov edx,d[OldInt23]
mov cx,w[OldInt23+4]
@@iDone3216: mov bl,23h
sys SetVect
@@i0: ;
cmp d[OldInt24],0
jz @@i1
test apiSystemFlags,1
jz @@i24Use32
mov dx,w[OldInt24]
mov cx,w[OldInt24+2]
jmp @@i24Done3216
@@i24Use32: mov edx,d[OldInt24]
mov cx,w[OldInt24+4]
@@i24Done3216: mov bl,24h
sys SetVect
@@i1: ;
pop ds
db 66h
retf
UnPatchExc endp
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
CtrlBrkEvent proc far
push ax
push ds
mov ds,cs:apiDSeg
assume ds:_cwMain
test SystemFlags,1
assume ds:_apiCode
pop ds
jz @@start32
;
mov ax,[si] ;get stacked offset.
mov es:Real_IP[di],ax
mov ax,2[si]
mov es:Real_CS[di],ax
mov ax,4[si]
mov es:Real_Flags[di],ax
add es:Real_SP[di],6
jmp @@start0
;
@@start32:
; mov ax,[esi] ;get stacked offset.
mov ax,[si] ;get stacked offset. MED 01/24/96
mov es:Real_IP[edi],ax
; mov ax,2[esi]
mov ax,2[si] ; MED 01/24/96
mov es:Real_CS[edi],ax
; mov ax,4[esi]
mov ax,4[si] ; MED 01/24/96
mov es:Real_Flags[edi],ax
add es:Real_SP[edi],6
;
@@start0: pop ax
;
;Give protected mode handler a shout.
;
int 1bh
;
;Go back to caller.
;
assume ds:nothing
test cs:apiSystemFlags,1
assume ds:_apiCode
jz @@Use32Bit2
iret
@@Use32Bit2: ;
iretd
;
OldInt1bh dd 0
Int1bhcall dd 0
CtrlBrkEventTab db size RealRegsStruc dup (0)
CtrlBrkEvent endp
;==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==
;
;Base handler for protected mode int 1bh's.
;
Int1bHandler proc far
push es
pushad
assume ds:nothing
;
;Need to chain to origional real mode handler.
;
mov es,cs:apiDDSeg
mov edi,offset Int1bRegs
mov eax,cs:d[OldInt1bh]
mov es:Real_IP[edi],ax
shr eax,16
mov es:Real_CS[edi],ax
mov es:Real_SS[edi],0
mov es:Real_SP[edi],0
mov ax,0302h
xor ecx,ecx
xor ebx,ebx
int 31h
;
;Return to caller.
;
popad
pop es
test cs:apiSystemFlags,1
jz @@0
iret
@@0: iretd
assume ds:_apiCode
;
OldInt1BhP df 0
Int1bRegs db size RealRegsStruc dup (0)
Int1bHandler endp
;-------------------------------------------------------------------------
;
;Handle a ctrl-break key press by terminating this application cleanly.
;
Int23Handler proc near
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
pushm ds,ds,ds
popm es,fs,gs
sti
jmp f[TerminationHandler]
assume ds:_apiCode
OldInt23 df 0
Int23Handler endp
;-------------------------------------------------------------------------
Int24Handler proc near
pushm ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
pushm ds,ds,ds
popm es,fs,gs
;
@@0: mov edx,offset CriticalPrompt
mov ah,9
int 21h
mov ah,1
int 21h
mov edi,offset CriticalKeys
mov ecx,8
cld
push ds
pop es
repne scasb
jnz @@0
movzx eax,b[edi+7]
cmp eax,2
jz @@Terminate
popm ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
assume ds:nothing
test cs:apiSystemFlags,1
assume ds:_apiCode
jz @@Use32_2
iret
@@Use32_2: ;
iretd
;
@@Terminate: assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
pushm ds,ds,ds
popm es,fs,gs
sti
jmp f[TerminationHandler]
assume ds:_apiCode
;
OldInt24 df 0
CriticalPrompt db 13,10,'Critical Error: Abort, Retry, Ignore, Fail? $'
CriticalKeys db 'aArRiIfF'
CriticalCodes db 2,2,1,1,0,0,3,3
Int24Handler endp
; remembered to defang this ancient artifact, MED, 11/01/99
;-------------------------------------------------------------------------
DPMICopyCheck proc near
COMMENT !
pushf
pushm ax,ds,si
assume ds:nothing
mov ds,cs:apiDSeg
assume ds:_cwMain
lea si,Copyright
add si,CopyCount
cmp b[si],0
jnz @@0
sub si,CopyCount
mov CopyCount,0
@@0: inc CopyCount
mov al,b[CopyCheck+si]
cmp al,255
jz @@1
add al,44
cmp al,b[si]
jz @@1
sub DPMIStackOff,32
;
@@1: popm ax,ds,si
popf
assume ds:_apiCode
END COMMENT !
ret
DPMICopyCheck endp
;-------------------------------------------------------------------------
Borda proc near
pushm ax,dx
mov ah,al
mov dx,3dah
in al,dx
mov dl,0c0h
mov al,11h
out dx,al
mov al,ah
out dx,al
mov al,20h
out dx,al
popm ax,dx
ret
Borda endp
;-------------------------------------------------------------------------
;
apiSystemFlags dw 0,0
DescriptorBuffer db 8 dup (?)
apiDSeg dw ?
apiDDSeg dw ?
;
apiNewHeader NewHeaderStruc <> ;make space for a header.
;
apiExeSignature db ? ;00 Identifier text.
db ? ;01 /
apiExeLength dw ? ;02 Length of file MOD 512
dw ? ;04 Length of file in 512 byte blocks.
apiExeRelocNum dw ? ;06 Number of relocation items.
apiExeHeaderSize dw ? ;08 Length of header in 16 byte paragraphs.
apiExeMinAlloc dw ? ;0A Minimum number of para's needed above program.
apiExeMaxAlloc dw ? ;0C Maximum number of para's needed above program.
apiExeStackSeg dw ? ;0E Segment displacement of stack module.
apiExeEntrySP dw ? ;10 value for SP at entry.
apiExeCheckSum dw ? ;12 Check sum...
apiExeEntryIP dw ? ;14 Contents of IP at entry.
apiExeEntryCS dw ? ;16 Segment displacement of CS at entry.
apiExeRelocFirst dw ? ;18 First relocation item offset.
apiExeOverlayNum db ? ;1A Overlay number.
;
LastResource dd 0,0
;
PatchTable dd 16 dup (0)
;
include loadle\loadle.asm
include decode_c.asm
mcbLastChunk dd 0
ExecMCount dd 0
;
;Export table for base PSP. EXPORT's internal functions.
;
apiEXPORT_cwMainCode equ 0
apiEXPORT_cwMainData equ 1
apiEXPORT_apiCode equ 2
apiEXPORT_apiData equ 3
apiExports dd 10
;
dd apiExportName
;
dd apiExport01
dd apiExport02
dd apiExport03
dd apiExport04
dd apiExport05
dd apiExport06
dd apiExport07
dd apiExport08
dd apiExport09
dd apiExport10
;
apiExportName db 15,"CAUSEWAY_KERNAL"
;
apiExport01 dd __cwAPI_CreatePSP
dw apiEXPORT_apiCode
db 17,"__CWAPI_CREATEPSP"
;
apiExport02 dd __cwAPI_DeletePSP
dw apiEXPORT_apiCode
db 17,"__CWAPI_DELETEPSP"
;
apiExport03 dd __cwAPI_ExecModule
dw apiEXPORT_apiCode
db 18,"__CWAPI_EXECMODULE"
;
apiExport04 dd __cwAPI_DSizeSelector
dw apiEXPORT_apiCode
db 21,"__CWAPI_DSIZESELECTOR"
;
apiExport05 dd __cwAPI_FindModule
dw apiEXPORT_apiCode
db 18,"__CWAPI_FINDMODULE"
;
apiExport06 dd __cwAPI_UnFindModule
dw apiEXPORT_apiCode
db 20,"__CWAPI_UNFINDMODULE"
;
apiExport07 dd __cwAPI_FindFunction
dw apiEXPORT_apiCode
db 20,"__CWAPI_FINDFUNCTION"
;
apiExport08 dd __cwAPI_GetMemLinear32
dw apiEXPORT_apiCode
db 22,"__CWAPI_GETMEMLINEAR32"
;
apiExport09 dd __cwAPI_ResMemLinear32
dw apiEXPORT_apiCode
db 22,"__CWAPI_RESMEMLINEAR32"
;
apiExport10 dd __cwAPI_RelMemLinear32
dw apiEXPORT_apiCode
db 22,"__CWAPI_RELMEMLINEAR32"
__cwAPI_CreatePSP proc far
call CreatePSP
ret
__cwAPI_CreatePSP endp
__cwAPI_DeletePSP proc far
call DeletePSP
ret
__cwAPI_DeletePSP endp
__cwAPI_ExecModule proc far
call ExecModule
ret
__cwAPI_ExecModule endp
__cwAPI_DSizeSelector proc far
call _DSizeSelector
ret
__cwAPI_DSizeSelector endp
__cwAPI_FindModule proc far
call FindModule
ret
__cwAPI_FindModule endp
__cwAPI_UnFindModule proc far
call UnFindModule
ret
__cwAPI_UnFindModule endp
__cwAPI_FindFunction proc far
call FindFunction
ret
__cwAPI_FindFunction endp
__cwAPI_GetMemLinear32 proc far
call mcbGetMemLinear32
ret
__cwAPI_GetMemLinear32 endp
__cwAPI_ResMemLinear32 proc far
call mcbResMemLinear32
ret
__cwAPI_ResMemLinear32 endp
__cwAPI_RelMemLinear32 proc far
call mcbRelMemLinear32
ret
__cwAPI_RelMemLinear32 endp
db 4 dup (?)
_apiCodeEnd label byte
_apiCode ends
.286