;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;============================================================================
;
;   External kernel dependencies (libraries) loading
;
;============================================================================

$Revision: 2455 $

if 0
; The code currently does not work. Kill "if 0/end if" only after correcting
; to current kernel (dll.inc).
macro library [name,fname]
{
  forward
    dd __#name#_library_table__,__#name#_library_name__
  common
    dd 0
  forward
    __#name#_library_name__ db fname,0
}

macro import lname,[name,sname]
{
  common
    align 4
    __#lname#_library_table__:
  forward
    name dd __#name#_import_name__
  common
    dd 0
  forward
    __#name#_import_name__ db sname,0
}

macro export [name,sname]
{
align 4
  forward
    dd __#name#_export_name__,name
  common
    dd 0
  forward
    __#name#_export_name__ db sname,0
}



align 4            ; loading library (use kernel functions)
proc load_k_library stdcall, file_name:dword
           locals
             coff      dd ?
             sym       dd ?
             strings   dd ?
             img_size  dd ?
             img_base  dd ?
             exports   dd ?
           endl

        cli

        stdcall load_file, [file_name]
        test    eax, eax
        jz      .fail

        mov     [coff], eax
        movzx   ecx, [eax+CFH.nSections]
        xor     ebx, ebx

        lea     edx, [eax+20]
@@:
        add     ebx, [edx+CFS.SizeOfRawData]
        add     ebx, 15
        and     ebx, not 15
        add     edx, COFF_SECTION_SIZE
        dec     ecx
        jnz     @B
        mov     [img_size], ebx

        stdcall kernel_alloc, [img_size]

        test    eax, eax
        jz      .fail
        mov     [img_base], eax

        mov     edx, [coff]
        movzx   ebx, [edx+CFH.nSections]
        mov     edi, [img_base]
        lea     eax, [edx+20]
@@:
        mov     [eax+CFS.VirtualAddress], edi
        mov     esi, [eax+CFS.PtrRawData]
        test    esi, esi
        jnz     .copy
        add     edi, [eax+CFS.SizeOfRawData]
        jmp     .next
.copy:
        add     esi, edx
        mov     ecx, [eax+CFS.SizeOfRawData]
        cld
        rep movsb
.next:
        add     edi, 15
        and     edi, not 15
        add     eax, COFF_SECTION_SIZE
        dec     ebx
        jnz     @B

        mov     ebx, [edx+CFH.pSymTable]
        add     ebx, edx
        mov     [sym], ebx
        mov     ecx, [edx+CFH.nSymbols]
        add     ecx, ecx
        lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
        add     ecx, [sym]
        mov     [strings], ecx

        lea     eax, [edx+20]

        stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols], \
                [strings], dword 0
        test    eax, eax
        jnz     @F

@@:
        mov     edx, [coff]
        movzx   ebx, [edx+CFH.nSections]
        mov     edi, 0
        lea     eax, [edx+20]
@@:
        add     [eax+CFS.VirtualAddress], edi ;patch user space offset
        add     eax, COFF_SECTION_SIZE
        dec     ebx
        jnz     @B

        add     edx, 20
        stdcall fix_coff_relocs, [coff], edx, [sym]

        mov     ebx, [coff]
        stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szEXPORTS
        mov     [exports], eax

        stdcall kernel_free, [coff]

        mov     eax, [exports]
        ret
.fail:
        xor     eax, eax
        ret
endp


proc dll.Load, import_table:dword
        mov     esi, [import_table]
  .next_lib:
        mov     edx, [esi]
        or      edx, edx
        jz      .exit
        push    esi

        mov     edi, s_libname

        mov     al, '/'
        stosb
        mov     esi, sysdir_path
            @@:
        lodsb
        stosb
        or      al, al
        jnz     @b
        dec     edi
        mov     [edi], dword '/lib'
        mov     [edi+4], byte '/'
        add     edi, 5
        pop     esi
        push    esi
        mov     esi, [esi+4]
            @@:
        lodsb
        stosb
        or      al, al
        jnz     @b

        pushad
        stdcall load_k_library, s_libname
        mov     [esp+28], eax
        popad
        or      eax, eax
        jz      .fail
        stdcall dll.Link, eax, edx
        stdcall dll.Init, [eax+4]
        pop     esi
        add     esi, 8
        jmp     .next_lib
  .exit:
        xor     eax, eax
        ret
  .fail:
        add     esp, 4
        xor     eax, eax
        inc     eax
        ret
endp

proc dll.Link, exp:dword,imp:dword
        push    eax
        mov     esi, [imp]
        test    esi, esi
        jz      .done
  .next:
        lodsd
        test    eax, eax
        jz      .done
        stdcall dll.GetProcAddress, [exp], eax
        or      eax, eax
        jz      @f
        mov     [esi-4], eax
        jmp     .next
            @@:
        mov     dword[esp], 0
  .done:
        pop     eax
        ret
endp

proc dll.Init, dllentry:dword
        pushad
        mov     eax, mem.Alloc
        mov     ebx, mem.Free
        mov     ecx, mem.ReAlloc
        mov     edx, dll.Load
        stdcall [dllentry]
        popad
        ret
endp

proc dll.GetProcAddress, exp:dword,sz_name:dword
        mov     edx, [exp]
  .next:
        test    edx, edx
        jz      .end
        stdcall strncmp, [edx], [sz_name], dword -1
        test    eax, eax
        jz      .ok
        add     edx, 8
        jmp     .next
  .ok:
        mov     eax, [edx+4]
  .end:
        ret
endp

;-----------------------------------------------------------------------------
proc mem.Alloc size ;/////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
        push    ebx ecx
;       mov     eax,[size]
;       lea     ecx,[eax+4+4095]
;       and     ecx,not 4095
;       stdcall kernel_alloc, ecx
;       add     ecx,-4
;       mov     [eax],ecx
;       add     eax,4

        stdcall kernel_alloc, [size]

        pop     ecx ebx
        ret
endp

;-----------------------------------------------------------------------------
proc mem.ReAlloc mptr,size;///////////////////////////////////////////////////
;-----------------------------------------------------------------------------
        push    ebx ecx esi edi eax
        mov     eax, [mptr]
        mov     ebx, [size]
        or      eax, eax
        jz      @f
        lea     ecx, [ebx+4+4095]
        and     ecx, not 4095
        add     ecx, -4
        cmp     ecx, [eax-4]
        je      .exit
    @@:
        mov     eax, ebx
        call    mem.Alloc
        xchg    eax, [esp]
        or      eax, eax
        jz      .exit
        mov     esi, eax
        xchg    eax, [esp]
        mov     edi, eax
        mov     ecx, [esi-4]
        cmp     ecx, [edi-4]
        jbe     @f
        mov     ecx, [edi-4]
    @@:
        add     ecx, 3
        shr     ecx, 2
        cld
        rep movsd
        xchg    eax, [esp]
        call    mem.Free
  .exit:
        pop     eax edi esi ecx ebx
        ret
endp

;-----------------------------------------------------------------------------
proc mem.Free mptr ;//////////////////////////////////////////////////////////
;-----------------------------------------------------------------------------
;       mov     eax,[mptr]
;       or      eax,eax
;       jz      @f
;       push    ebx ecx
;       lea     ecx,[eax-4]
;       stdcall kernel_free, ecx
;       pop     ecx ebx
;    @@: ret
        stdcall kernel_free, [mptr]
        ret
endp

uglobal
s_libname  db 64 dup (0)
endg
end if