
;--- CauseWay file for simple dll support.
;--- defines LoadLibrary, FreeLibrary, GetProcAddress, LoadModule, FreeModule

	.386
	.model flat

MODULEAPI equ 1     ;1=use CauseWay's API directly (v5 only);0=use CauseWay's CWAPI exports.

PUSHADS struct
_edi	dd ?
_esi	dd ?
_ebp	dd ?
		dd ?
_ebx	dd ?
_edx	dd ?   
_ecx	dd ?   
_eax	dd ?   
PUSHADS ends

	include cw.inc

if MODULEAPI
cwFindModule   equ 0ff33h
cwUnFindModule equ 0ff34h
cwFindFunction equ 0ff35h
else
	externdef __CWAPI_FINDMODULE:far
	externdef __CWAPI_UNFINDMODULE:far
	externdef __CWAPI_FINDFUNCTION:far
endif

	public LoadLibrary
	public FreeLibrary
	public LoadModule
	public FreeModule
	public GetProcAddress

	.data

NameSpace	db 257 dup (0)

	.code

	assume fs:nothing

;****************************************************************************
;Load a module by file name. If the module already exists in memory a new
;version will still be loaded.
;
;Usage: LoadLibrary(file_name);
;
;Returns:
;
;EAX	zero on error else module handle.
;
;file_name is a standard zero terminated string.
;
;Handles returned by this function should always be released via FreeLibrary()
;
;****************************************************************************
LoadLibrary proc c
	pushad
;
;Let cwLoad have a go at loading it.
;
	mov edx,[esp+sizeof PUSHADS+4]
	sys cwLoad
	jnc @@4
	xor edx,edx
	jmp @@5
;
;CX:EDX=CS:EIP
;BX:EAX=SS:ESP
;SI=PSP
;
@@4:
	push es
	mov es,esi
	mov edi,EPSP_Struc.EPSP_EntryCSEIP
	mov dword ptr es:[edi+0],edx
	mov word ptr es:[edi+4],cx
	pop es
;
;Get PSP linear address.
;
	mov bx,si
	sys GetSelDet32
;
;Call entry code.
;
	push ds
	push es
	push fs
	push gs
	pushad
	push ebx
	pop fs
	mov ds,ebx
	mov es,ebx
	xor eax,eax
	mov ax,es:word ptr[edi+4]
	lar eax,eax
	test eax,00400000h
	mov eax,0  ;0=load
	jnz @@6
	db 66h     ;changes call FAR32 to call FAR16
@@6:
	call fword ptr fs:[edi]
	or ax,ax
	popad
	pop gs
	pop fs
	pop ds
	pop es
	jz @@5
;
;Initialisation failed so release this PSP.
;
	mov bx,si
	sys RelMem
	xor edx,edx
;
;Return handle (or error) to caller.
;
@@5:
	mov [esp].PUSHADS._eax,edx
	popad
	ret
LoadLibrary endp


;****************************************************************************
;Releases a LoadLibrary module handle back to the system.
;
;Usage: FreeLibrary(module_handle);
;
;Returns:
;
;nothing.
;
;module_handle is the value returned by LoadLibrary();
;
;****************************************************************************
FreeLibrary proc c
	pushad
;
;Call terminate code.
;
	mov edx,[esp+sizeof PUSHADS+4]
	xor ebx,ebx
	mov bx,[edx].EPSP_Struc.EPSP_PSPSel
	push ds
	push es
	push fs
	push gs
	pushad
	push ebx
	pop fs
	mov ds,ebx
	mov es,ebx
	xor eax,eax
	mov edi,EPSP_Struc.EPSP_EntryCSEIP
	mov ax,word ptr es:[edi+4]
	lar eax,eax
	test eax,00400000h
	mov eax,1     ;1=unload
	jnz @@7
	db 66h
@@7:
	call fword ptr fs:[edi]
	popad
	pop gs
	pop fs
	pop ds
	pop es
;
;Release the module.
;
	mov bx,[edx].EPSP_Struc.EPSP_PSPSel
	sys RelSel
;
	popad
	ret
FreeLibrary endp


;****************************************************************************
;Load a module by module name. If the module is already in memory then just
;return the handle for the existing copy.
;
;Usage: LoadModule(module_name);
;
;Returns:
;
;EAX 	zero on error else module handle.
;
;module_name is a standard zero terminated string.
;
;Handles returned by this function should always be released via FreeModule()
;
;****************************************************************************
LoadModule proc c
	pushad
;
;Build the module name string in the format CauseWay API likes.
;
	mov esi,[esp+sizeof PUSHADS+4]	;Point to module name
	mov edi,esi
	or ecx,-1
	xor al,al
	cld
	repnz scasb		;get the strings length.
	not ecx
	dec ecx		;Don't include terminator.
	mov edi,offset NameSpace
	mov [edi],cl
	inc edi
	rep movsb
;
;Call API code.
;
	mov esi,offset NameSpace
if MODULEAPI
	sys cwFindModule
else
	call __CWAPI_FindModule
endif
	jnc @@0
	xor edi,edi		;Zero the handle
;
;Return handle (or error) to caller.
;
@@0:
	mov [esp].PUSHADS._eax,edi
	popad
	ret
LoadModule endp


;****************************************************************************
;Releases a LoadModule() module handle back to the system.
;
;Usage: FreeModule(module_handle);
;
;Returns:
;
;nothing.
;
;module_handle is the value returned by LoadModule();
;
;****************************************************************************
FreeModule proc c
	pushad
;
;Call API code.
;
	mov edi,[esp+sizeof PUSHADS+4]
if MODULEAPI
	sys cwUnFindModule
else
	call __CWAPI_UnFindModule
endif
	popad
	ret
FreeModule endp


;****************************************************************************
;Returns the address of a symbol in a module.
;
;Usage: GetProcAddress(module_handle,function_name);
;
;Returns:
;
;zero on error else function address. (EDX:EAX, use just EAX for FLAT)
;
;module_handle is the value returned by LoadModule() or LoadLibrary()
;module_name is a standard zero terminated string.
;
;****************************************************************************
GetProcAddress proc c
	pushad
;
;Build the function name string in the format CauseWay API likes.
;
	mov esi,[esp+sizeof PUSHADS+4+4]
	mov edi,esi
	or  ecx,-1
	xor al,al
	cld
	repnz scasb		;get the strings length.
	not ecx
	dec ecx		;Don't include terminator.
	mov edi,offset NameSpace
	mov [edi],cl
	inc edi
	rep movsb
;
;Call API code.
;
	mov ebp,offset NameSpace
	mov edi,[esp+sizeof PUSHADS+4]
	mov edi,[edi].EPSP_Struc.EPSP_Exports
if MODULEAPI
	sys cwFindFunction
else
	call __CWAPI_FindFunction
endif
	jnc @@2
	xor ecx,ecx		;Zero the address
	xor edx,edx
	jmp @@3
;
;Fetch function address.
;
@@2:
	mov edx,[edi+0]
	movzx ecx,word ptr [edi+4]
;
;Return function (or error) to caller.
;
@@3:
	mov [esp].PUSHADS._eax,edx
	mov [esp].PUSHADS._edx,ecx
	popad
	ret
GetProcAddress endp

	end

