Subversion Repositories Kolibri OS

Rev

Rev 2455 | Rev 2489 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 2486 $
  9.  
  10.  
  11. DRV_COMPAT   equ  5  ;minimal required drivers version
  12. DRV_CURRENT  equ  6  ;current drivers model version
  13.  
  14. DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
  15. PID_KERNEL  equ 1    ;os_idle thread
  16.  
  17.  
  18.  
  19. align 4
  20. proc get_notify stdcall, p_ev:dword
  21.  
  22. .wait:
  23.         mov     ebx, [current_slot]
  24.         test    dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
  25.         jz      @f
  26.         and     dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
  27.         mov     edi, [p_ev]
  28.         mov     dword [edi], EV_INTR
  29.         mov     eax, [ebx+APPDATA.event]
  30.         mov     dword [edi+4], eax
  31.         ret
  32. @@:
  33.         call    change_task
  34.         jmp     .wait
  35. endp
  36.  
  37. align 4
  38. proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
  39.         push    ebx
  40.         xor     eax, eax
  41.         xor     ebx, ebx
  42.         mov     ah, byte [bus]
  43.         mov     al, 6
  44.         mov     bh, byte [devfn]
  45.         mov     bl, byte [reg]
  46.         call    pci_read_reg
  47.         pop     ebx
  48.         ret
  49. endp
  50.  
  51. align 4
  52. proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
  53.         push    ebx
  54.         xor     eax, eax
  55.         xor     ebx, ebx
  56.         mov     ah, byte [bus]
  57.         mov     al, 5
  58.         mov     bh, byte [devfn]
  59.         mov     bl, byte [reg]
  60.         call    pci_read_reg
  61.         pop     ebx
  62.         ret
  63. endp
  64.  
  65. align 4
  66. proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
  67.         push    ebx
  68.         xor     eax, eax
  69.         xor     ebx, ebx
  70.         mov     ah, byte [bus]
  71.         mov     al, 4
  72.         mov     bh, byte [devfn]
  73.         mov     bl, byte [reg]
  74.         call    pci_read_reg
  75.         pop     ebx
  76.         ret
  77. endp
  78.  
  79. align 4
  80. proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  81.         push    ebx
  82.         xor     eax, eax
  83.         xor     ebx, ebx
  84.         mov     ah, byte [bus]
  85.         mov     al, 8
  86.         mov     bh, byte [devfn]
  87.         mov     bl, byte [reg]
  88.         mov     ecx, [val]
  89.         call    pci_write_reg
  90.         pop     ebx
  91.         ret
  92. endp
  93.  
  94. align 4
  95. proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  96.         push    ebx
  97.         xor     eax, eax
  98.         xor     ebx, ebx
  99.         mov     ah, byte [bus]
  100.         mov     al, 9
  101.         mov     bh, byte [devfn]
  102.         mov     bl, byte [reg]
  103.         mov     ecx, [val]
  104.         call    pci_write_reg
  105.         pop     ebx
  106.         ret
  107. endp
  108.  
  109. align 4
  110. proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  111.         push    ebx
  112.         xor     eax, eax
  113.         xor     ebx, ebx
  114.         mov     ah, byte [bus]
  115.         mov     al, 10
  116.         mov     bh, byte [devfn]
  117.         mov     bl, byte [reg]
  118.         mov     ecx, [val]
  119.         call    pci_write_reg
  120.         pop     ebx
  121.         ret
  122. endp
  123.  
  124. handle     equ  IOCTL.handle
  125. io_code    equ  IOCTL.io_code
  126. input      equ  IOCTL.input
  127. inp_size   equ  IOCTL.inp_size
  128. output     equ  IOCTL.output
  129. out_size   equ  IOCTL.out_size
  130.  
  131.  
  132. align 4
  133. proc srv_handler stdcall, ioctl:dword
  134.         mov     esi, [ioctl]
  135.         test    esi, esi
  136.         jz      .err
  137.  
  138.         mov     edi, [esi+handle]
  139.         cmp     [edi+SRV.magic], ' SRV'
  140.         jne     .fail
  141.  
  142.         cmp     [edi+SRV.size], sizeof.SRV
  143.         jne     .fail
  144.  
  145.         stdcall [edi+SRV.srv_proc], esi
  146.         ret
  147. .fail:
  148.         xor     eax, eax
  149.         not     eax
  150.         mov     [esi+output], eax
  151.         mov     [esi+out_size], 4
  152.         ret
  153. .err:
  154.         xor     eax, eax
  155.         not     eax
  156.         ret
  157. endp
  158.  
  159. ; param
  160. ;  ecx= io_control
  161. ;
  162. ; retval
  163. ;  eax= error code
  164.  
  165. align 4
  166. srv_handlerEx:
  167.         cmp     ecx, OS_BASE
  168.         jae     .fail
  169.  
  170.         mov     eax, [ecx+handle]
  171.         cmp     [eax+SRV.magic], ' SRV'
  172.         jne     .fail
  173.  
  174.         cmp     [eax+SRV.size], sizeof.SRV
  175.         jne     .fail
  176.  
  177.         stdcall [eax+SRV.srv_proc], ecx
  178.         ret
  179. .fail:
  180.         or      eax, -1
  181.         ret
  182.  
  183. restore  handle
  184. restore  io_code
  185. restore  input
  186. restore  inp_size
  187. restore  output
  188. restore  out_size
  189.  
  190. align 4
  191. proc get_service stdcall, sz_name:dword
  192.         mov     eax, [sz_name]
  193.         test    eax, eax
  194.         jnz     @F
  195.         ret
  196. @@:
  197.         mov     edx, [srv.fd]
  198. @@:
  199.         cmp     edx, srv.fd-SRV.fd
  200.         je      .not_load
  201.  
  202.         stdcall strncmp, edx, [sz_name], 16
  203.         test    eax, eax
  204.         je      .ok
  205.  
  206.         mov     edx, [edx+SRV.fd]
  207.         jmp     @B
  208. .not_load:
  209.         pop     ebp
  210.         jmp     load_driver
  211. .ok:
  212.         mov     eax, edx
  213.         ret
  214. endp
  215.  
  216. align 4
  217. proc reg_service stdcall, name:dword, handler:dword
  218.  
  219.         push    ebx
  220.  
  221.         xor     eax, eax
  222.  
  223.         cmp     [name], eax
  224.         je      .fail
  225.  
  226.         cmp     [handler], eax
  227.         je      .fail
  228.  
  229.         mov     eax, sizeof.SRV
  230.         call    malloc
  231.         test    eax, eax
  232.         jz      .fail
  233.  
  234.         push    esi
  235.         push    edi
  236.         mov     edi, eax
  237.         mov     esi, [name]
  238.         movsd
  239.         movsd
  240.         movsd
  241.         movsd
  242.         pop     edi
  243.         pop     esi
  244.  
  245.         mov     [eax+SRV.magic], ' SRV'
  246.         mov     [eax+SRV.size], sizeof.SRV
  247.  
  248.         mov     ebx, srv.fd-SRV.fd
  249.         mov     edx, [ebx+SRV.fd]
  250.         mov     [eax+SRV.fd], edx
  251.         mov     [eax+SRV.bk], ebx
  252.         mov     [ebx+SRV.fd], eax
  253.         mov     [edx+SRV.bk], eax
  254.  
  255.         mov     ecx, [handler]
  256.         mov     [eax+SRV.srv_proc], ecx
  257.         pop     ebx
  258.         ret
  259. .fail:
  260.         xor     eax, eax
  261.         pop     ebx
  262.         ret
  263. endp
  264.  
  265. align 4
  266. proc get_proc stdcall, exp:dword, sz_name:dword
  267.  
  268.         mov     edx, [exp]
  269. .next:
  270.         mov     eax, [edx]
  271.         test    eax, eax
  272.         jz      .end
  273.  
  274.         push    edx
  275.         stdcall strncmp, eax, [sz_name], 16
  276.         pop     edx
  277.         test    eax, eax
  278.         jz      .ok
  279.  
  280.         add     edx, 8
  281.         jmp     .next
  282. .ok:
  283.         mov     eax, [edx+4]
  284. .end:
  285.         ret
  286. endp
  287.  
  288. align 4
  289. proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
  290.  
  291. @@:
  292.         stdcall strncmp, [pSym], [sz_sym], 8
  293.         test    eax, eax
  294.         jz      .ok
  295.         add     [pSym], 18
  296.         dec     [count]
  297.         jnz     @b
  298.         xor     eax, eax
  299.         ret
  300. .ok:
  301.         mov     eax, [pSym]
  302.         mov     eax, [eax+8]
  303.         ret
  304. endp
  305.  
  306. align 4
  307. proc get_curr_task
  308.         mov     eax, [CURRENT_TASK]
  309.         shl     eax, 8
  310.         ret
  311. endp
  312.  
  313. align 4
  314. proc get_fileinfo stdcall, file_name:dword, info:dword
  315.            locals
  316.              cmd     dd ?
  317.              offset  dd ?
  318.                      dd ?
  319.              count   dd ?
  320.              buff    dd ?
  321.                      db ?
  322.              name    dd ?
  323.            endl
  324.  
  325.         xor     eax, eax
  326.         mov     ebx, [file_name]
  327.         mov     ecx, [info]
  328.  
  329.         mov     [cmd], 5
  330.         mov     [offset], eax
  331.         mov     [offset+4], eax
  332.         mov     [count], eax
  333.         mov     [buff], ecx
  334.         mov     byte [buff+4], al
  335.         mov     [name], ebx
  336.  
  337.         mov     eax, 70
  338.         lea     ebx, [cmd]
  339.         int     0x40
  340.         ret
  341. endp
  342.  
  343. align 4
  344. proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
  345.                                      bytes:dword
  346.            locals
  347.              cmd     dd ?
  348.              offset  dd ?
  349.                      dd ?
  350.              count   dd ?
  351.              buff    dd ?
  352.                      db ?
  353.              name    dd ?
  354.            endl
  355.  
  356.         xor     eax, eax
  357.         mov     ebx, [file_name]
  358.         mov     ecx, [off]
  359.         mov     edx, [bytes]
  360.         mov     esi, [buffer]
  361.  
  362.         mov     [cmd], eax
  363.         mov     [offset], ecx
  364.         mov     [offset+4], eax
  365.         mov     [count], edx
  366.         mov     [buff], esi
  367.         mov     byte [buff+4], al
  368.         mov     [name], ebx
  369.  
  370.         pushad
  371.         lea     ebx, [cmd]
  372.         call    file_system_lfn
  373.         popad
  374.         ret
  375. endp
  376.  
  377. ; description
  378. ;  allocate kernel memory and loads the specified file
  379. ;
  380. ; param
  381. ;  file_name= full path to file
  382. ;
  383. ; retval
  384. ;  eax= file image in kernel memory
  385. ;  ebx= size of file
  386. ;
  387. ; warging
  388. ;  You mast call kernel_free() to delete each file
  389. ;  loaded by the load_file() function
  390.  
  391. align 4
  392. proc load_file stdcall, file_name:dword
  393.            locals
  394.              attr       dd ?
  395.              flags      dd ?
  396.              cr_time    dd ?
  397.              cr_date    dd ?
  398.              acc_time   dd ?
  399.              acc_date   dd ?
  400.              mod_time   dd ?
  401.              mod_date   dd ?
  402.              file_size  dd ?
  403.  
  404.              file       dd ?
  405.              file2      dd ?
  406.            endl
  407.  
  408.         push    esi
  409.         push    edi
  410.  
  411.         lea     eax, [attr]
  412.         stdcall get_fileinfo, [file_name], eax
  413.         test    eax, eax
  414.         jnz     .fail
  415.  
  416.         mov     eax, [file_size]
  417.         cmp     eax, 1024*1024*16
  418.         ja      .fail
  419.  
  420.         stdcall kernel_alloc, [file_size]
  421.         mov     [file], eax
  422.         test    eax, eax
  423.         jz      .fail
  424.  
  425.         stdcall read_file, [file_name], eax, dword 0, [file_size]
  426.         cmp     ebx, [file_size]
  427.         jne     .cleanup
  428.  
  429.         mov     eax, [file]
  430.         cmp     dword [eax], 0x4B43504B
  431.         jne     .exit
  432.         mov     ebx, [eax+4]
  433.         mov     [file_size], ebx
  434.         stdcall kernel_alloc, ebx
  435.  
  436.         test    eax, eax
  437.         jz      .cleanup
  438.  
  439.         mov     [file2], eax
  440.  
  441.         push    eax
  442. .wait_lock:
  443.         cmp     [unpack_mutex], 0
  444.         je      .get_lock
  445.         call    change_task
  446.         jmp     .wait_lock
  447.  
  448. .get_lock:
  449.         mov     eax, 1
  450.         xchg    eax, [unpack_mutex]
  451.         test    eax, eax
  452.         jnz     .wait_lock
  453.         pop     eax
  454.  
  455.         stdcall unpack, [file], eax
  456.  
  457.         mov     [unpack_mutex], 0
  458.  
  459.         stdcall kernel_free, [file]
  460.         mov     eax, [file2]
  461.         mov     ebx, [file_size]
  462. .exit:
  463.         push    eax
  464.         lea     edi, [eax+ebx]    ;cleanup remain space
  465.         mov     ecx, 4096         ;from file end
  466.         and     ebx, 4095
  467.         jz      @f
  468.         sub     ecx, ebx
  469.         xor     eax, eax
  470.         cld
  471.         rep stosb
  472. @@:
  473.         mov     ebx, [file_size]
  474.         pop     eax
  475.         pop     edi
  476.         pop     esi
  477.         ret
  478. .cleanup:
  479.         stdcall kernel_free, [file]
  480. .fail:
  481.         xor     eax, eax
  482.         xor     ebx, ebx
  483.         pop     edi
  484.         pop     esi
  485.         ret
  486. endp
  487.  
  488. iglobal
  489. align 4
  490. unpack_mutex dd 0
  491. endg
  492.  
  493. align 4
  494. proc get_proc_ex stdcall, proc_name:dword, imports:dword
  495.  
  496. .look_up:
  497.         mov     edx, [imports]
  498.         test    edx, edx
  499.         jz      .end
  500.         mov     edx, [edx]
  501.         test    edx, edx
  502.         jz      .end
  503. .next:
  504.         mov     eax, [edx]
  505.         test    eax, eax
  506.         jz      .next_table
  507.  
  508.         push    edx
  509.         stdcall strncmp, eax, [proc_name], 256
  510.         pop     edx
  511.         test    eax, eax
  512.         jz      .ok
  513.  
  514.         add     edx, 8
  515.         jmp     .next
  516. .next_table:
  517.         add     [imports], 4
  518.         jmp     .look_up
  519. .ok:
  520.         mov     eax, [edx+4]
  521.         ret
  522. .end:
  523.         xor     eax, eax
  524.         ret
  525. endp
  526.  
  527. align 4
  528. proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
  529.                       sym_count:dword, strings:dword, imports:dword
  530.            locals
  531.              retval dd ?
  532.            endl
  533.  
  534.         mov     edi, [symbols]
  535.         mov     [retval], 1
  536. .fix:
  537.         movzx   ebx, [edi+COFF_SYM.SectionNumber]
  538.         test    ebx, ebx
  539.         jnz     .internal
  540.         mov     eax, dword [edi+COFF_SYM.Name]
  541.         test    eax, eax
  542.         jnz     @F
  543.  
  544.         mov     edi, [edi+4]
  545.         add     edi, [strings]
  546. @@:
  547.         push    edi
  548.         stdcall get_proc_ex, edi, [imports]
  549.         pop     edi
  550.  
  551.         xor     ebx, ebx
  552.         test    eax, eax
  553.         jnz     @F
  554.  
  555.         mov     esi, msg_unresolved
  556.         call    sys_msg_board_str
  557.         mov     esi, edi
  558.         call    sys_msg_board_str
  559.         mov     esi, msg_CR
  560.         call    sys_msg_board_str
  561.  
  562.         mov     [retval], 0
  563. @@:
  564.         mov     edi, [symbols]
  565.         mov     [edi+COFF_SYM.Value], eax
  566.         jmp     .next
  567. .internal:
  568.         cmp     bx, -1
  569.         je      .next
  570.         cmp     bx, -2
  571.         je      .next
  572.  
  573.         dec     ebx
  574.         shl     ebx, 3
  575.         lea     ebx, [ebx+ebx*4]
  576.         add     ebx, [sec]
  577.  
  578.         mov     eax, [ebx+COFF_SECTION.VirtualAddress]
  579.         add     [edi+COFF_SYM.Value], eax
  580. .next:
  581.         add     edi, sizeof.COFF_SYM
  582.         mov     [symbols], edi
  583.         dec     [sym_count]
  584.         jnz     .fix
  585.         mov     eax, [retval]
  586.         ret
  587. endp
  588.  
  589. align 4
  590. proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
  591.         delta:dword
  592.            locals
  593.              n_sec     dd ?
  594.            endl
  595.  
  596.         mov     eax, [coff]
  597.         movzx   ebx, [eax+COFF_HEADER.nSections]
  598.         mov     [n_sec], ebx
  599.         lea     esi, [eax+20]
  600. .fix_sec:
  601.         mov     edi, [esi+COFF_SECTION.PtrReloc]
  602.         add     edi, [coff]
  603.  
  604.         movzx   ecx, [esi+COFF_SECTION.NumReloc]
  605.         test    ecx, ecx
  606.         jz      .next
  607. .reloc_loop:
  608.         mov     ebx, [edi+COFF_RELOC.SymIndex]
  609.         add     ebx, ebx
  610.         lea     ebx, [ebx+ebx*8]
  611.         add     ebx, [sym]
  612.  
  613.         mov     edx, [ebx+COFF_SYM.Value]
  614.  
  615.         cmp     [edi+COFF_RELOC.Type], 6
  616.         je      .dir_32
  617.  
  618.         cmp     [edi+COFF_RELOC.Type], 20
  619.         jne     .next_reloc
  620. .rel_32:
  621.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  622.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  623.         sub     edx, eax
  624.         sub     edx, 4
  625.         jmp     .fix
  626. .dir_32:
  627.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  628.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  629. .fix:
  630.         add     eax, [delta]
  631.         add     [eax], edx
  632. .next_reloc:
  633.         add     edi, 10
  634.         dec     ecx
  635.         jnz     .reloc_loop
  636. .next:
  637.         add     esi, sizeof.COFF_SECTION
  638.         dec     [n_sec]
  639.         jnz     .fix_sec
  640. .exit:
  641.         ret
  642. endp
  643.  
  644. align 4
  645. proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
  646.         delta:dword
  647.            locals
  648.              n_sec     dd ?
  649.            endl
  650.  
  651.         mov     eax, [coff]
  652.         movzx   ebx, [eax+COFF_HEADER.nSections]
  653.         mov     [n_sec], ebx
  654.         lea     esi, [eax+20]
  655.         mov     edx, [delta]
  656. .fix_sec:
  657.         mov     edi, [esi+COFF_SECTION.PtrReloc]
  658.         add     edi, [coff]
  659.  
  660.         movzx   ecx, [esi+COFF_SECTION.NumReloc]
  661.         test    ecx, ecx
  662.         jz      .next
  663. .reloc_loop:
  664.         cmp     [edi+COFF_RELOC.Type], 6
  665.         jne     .next_reloc
  666. .dir_32:
  667.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  668.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  669.         add     [eax+edx], edx
  670. .next_reloc:
  671.         add     edi, 10
  672.         dec     ecx
  673.         jnz     .reloc_loop
  674. .next:
  675.         add     esi, sizeof.COFF_SECTION
  676.         dec     [n_sec]
  677.         jnz     .fix_sec
  678. .exit:
  679.         ret
  680. endp
  681.  
  682. align 4
  683. proc load_driver stdcall, driver_name:dword
  684.            locals
  685.              coff      dd ?
  686.              sym       dd ?
  687.              strings   dd ?
  688.              img_size  dd ?
  689.              img_base  dd ?
  690.              start     dd ?
  691.  
  692.              exports   dd ?   ;fake exports table
  693.                        dd ?
  694.              file_name rb 13+16+4+1      ; '/sys/drivers/<up-to-16-chars>.obj'
  695.            endl
  696.  
  697.         lea     edx, [file_name]
  698.         mov     dword [edx], '/sys'
  699.         mov     dword [edx+4], '/dri'
  700.         mov     dword [edx+8], 'vers'
  701.         mov     byte [edx+12], '/'
  702.         mov     esi, [driver_name]
  703. .redo:
  704.         lea     edx, [file_name]
  705.         lea     edi, [edx+13]
  706.         mov     ecx, 16
  707. @@:
  708.         lodsb
  709.         test    al, al
  710.         jz      @f
  711.         stosb
  712.         loop    @b
  713. @@:
  714.         mov     dword [edi], '.obj'
  715.         mov     byte [edi+4], 0
  716.         stdcall load_file, edx
  717.  
  718.         test    eax, eax
  719.         jz      .exit
  720.  
  721.         mov     [coff], eax
  722.  
  723.         movzx   ecx, [eax+COFF_HEADER.nSections]
  724.         xor     ebx, ebx
  725.  
  726.         lea     edx, [eax+20]
  727. @@:
  728.         add     ebx, [edx+COFF_SECTION.SizeOfRawData]
  729.         add     ebx, 15
  730.         and     ebx, not 15
  731.         add     edx, sizeof.COFF_SECTION
  732.         dec     ecx
  733.         jnz     @B
  734.         mov     [img_size], ebx
  735.  
  736.         stdcall kernel_alloc, ebx
  737.         test    eax, eax
  738.         jz      .fail
  739.         mov     [img_base], eax
  740.  
  741.         mov     edi, eax
  742.         xor     eax, eax
  743.         mov     ecx, [img_size]
  744.         add     ecx, 4095
  745.         and     ecx, not 4095
  746.         shr     ecx, 2
  747.         cld
  748.         rep stosd
  749.  
  750.         mov     edx, [coff]
  751.         movzx   ebx, [edx+COFF_HEADER.nSections]
  752.         mov     edi, [img_base]
  753.         lea     eax, [edx+20]
  754. @@:
  755.         mov     [eax+COFF_SECTION.VirtualAddress], edi
  756.         mov     esi, [eax+COFF_SECTION.PtrRawData]
  757.         test    esi, esi
  758.         jnz     .copy
  759.         add     edi, [eax+COFF_SECTION.SizeOfRawData]
  760.         jmp     .next
  761. .copy:
  762.         add     esi, edx
  763.         mov     ecx, [eax+COFF_SECTION.SizeOfRawData]
  764.         cld
  765.         rep movsb
  766. .next:
  767.         add     edi, 15
  768.         and     edi, not 15
  769.         add     eax, sizeof.COFF_SECTION
  770.         dec     ebx
  771.         jnz     @B
  772.  
  773.         mov     ebx, [edx+COFF_HEADER.pSymTable]
  774.         add     ebx, edx
  775.         mov     [sym], ebx
  776.         mov     ecx, [edx+COFF_HEADER.nSymbols]
  777.         add     ecx, ecx
  778.         lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
  779.         add     ecx, [sym]
  780.         mov     [strings], ecx
  781.  
  782.         lea     ebx, [exports]
  783.         mov     dword [ebx], kernel_export
  784.         mov     dword [ebx+4], 0
  785.         lea     eax, [edx+20]
  786.  
  787.         stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
  788.                 [strings], ebx
  789.         test    eax, eax
  790.         jz      .link_fail
  791.  
  792.         mov     ebx, [coff]
  793.         stdcall fix_coff_relocs, ebx, [sym], 0
  794.  
  795.         stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
  796.         test    eax, eax
  797.         jz      .link_fail
  798.  
  799.         mov     eax, [eax]
  800.         shr     eax, 16
  801.         cmp     eax, DRV_COMPAT
  802.         jb      .ver_fail
  803.  
  804.         cmp     eax, DRV_CURRENT
  805.         ja      .ver_fail
  806.  
  807.         mov     ebx, [coff]
  808.         stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
  809.         mov     [start], eax
  810.  
  811.         stdcall kernel_free, [coff]
  812.  
  813.         mov     ebx, [start]
  814.         stdcall ebx, DRV_ENTRY
  815.         test    eax, eax
  816.         jnz     .ok
  817.  
  818.         stdcall kernel_free, [img_base]
  819.         cmp     dword [file_name+13], 'SOUN'
  820.         jnz     @f
  821.         cmp     dword [file_name+17], 'D.ob'
  822.         jnz     @f
  823.         cmp     word [file_name+21], 'j'
  824.         jnz     @f
  825.         mov     esi, aHDA
  826.         jmp     .redo
  827. @@:
  828.         xor     eax, eax
  829.         ret
  830. .ok:
  831.         mov     ebx, [img_base]
  832.         mov     [eax+SRV.base], ebx
  833.         mov     ecx, [start]
  834.         mov     [eax+SRV.entry], ecx
  835.         ret
  836.  
  837. .ver_fail:
  838.         mov     esi, msg_CR
  839.         call    sys_msg_board_str
  840.         mov     esi, [driver_name]
  841.         call    sys_msg_board_str
  842.         mov     esi, msg_CR
  843.         call    sys_msg_board_str
  844.         mov     esi, msg_version
  845.         call    sys_msg_board_str
  846.         mov     esi, msg_www
  847.         call    sys_msg_board_str
  848.         jmp     .cleanup
  849.  
  850. .link_fail:
  851.         mov     esi, msg_module
  852.         call    sys_msg_board_str
  853.         mov     esi, [driver_name]
  854.         call    sys_msg_board_str
  855.         mov     esi, msg_CR
  856.         call    sys_msg_board_str
  857. .cleanup:
  858.         stdcall kernel_free, [img_base]
  859. .fail:
  860.         stdcall kernel_free, [coff]
  861. .exit:
  862.         xor     eax, eax
  863.         ret
  864. endp
  865.  
  866. ; in: edx -> COFF_SECTION struct
  867. ; out: eax = alignment as mask for bits to drop
  868. coff_get_align:
  869. ; Rules:
  870. ; - if alignment is not given, use default = 4K;
  871. ; - if alignment is given and is no more than 4K, use it;
  872. ; - if alignment is more than 4K, revert to 4K.
  873.         push    ecx
  874.         mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
  875.         mov     eax, 1
  876.         shr     cl, 4
  877.         dec     cl
  878.         js      .default
  879.         cmp     cl, 12
  880.         jbe     @f
  881. .default:
  882.         mov     cl, 12
  883. @@:
  884.         shl     eax, cl
  885.         pop     ecx
  886.         dec     eax
  887.         ret
  888.  
  889. align 4
  890. proc load_library stdcall, file_name:dword
  891.            locals
  892.              fullname  rb 260
  893.              fileinfo  rb 40
  894.              coff      dd ?
  895.              img_base  dd ?
  896.            endl
  897.  
  898.         cli
  899.  
  900. ; resolve file name
  901.         mov     ebx, [file_name]
  902.         lea     edi, [fullname+1]
  903.         mov     byte [edi-1], '/'
  904.         stdcall get_full_file_name, edi, 259
  905.         test    al, al
  906.         jz      .fail
  907.  
  908. ; scan for required DLL in list of already loaded for this process,
  909. ; ignore timestamp
  910.         mov     esi, [CURRENT_TASK]
  911.         shl     esi, 8
  912.         lea     edi, [fullname]
  913.         mov     ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
  914.         test    ebx, ebx
  915.         jz      .not_in_process
  916.         mov     esi, [ebx+HDLL.fd]
  917. .scan_in_process:
  918.         cmp     esi, ebx
  919.         jz      .not_in_process
  920.         mov     eax, [esi+HDLL.parent]
  921.         add     eax, DLLDESCR.name
  922.         stdcall strncmp, eax, edi, -1
  923.         test    eax, eax
  924.         jnz     .next_in_process
  925. ; simple variant: load DLL which is already loaded in this process
  926. ; just increment reference counters and return address of exports table
  927.         inc     [esi+HDLL.refcount]
  928.         mov     ecx, [esi+HDLL.parent]
  929.         inc     [ecx+DLLDESCR.refcount]
  930.         mov     eax, [ecx+DLLDESCR.exports]
  931.         sub     eax, [ecx+DLLDESCR.defaultbase]
  932.         add     eax, [esi+HDLL.base]
  933.         ret
  934. .next_in_process:
  935.         mov     esi, [esi+HDLL.fd]
  936.         jmp     .scan_in_process
  937. .not_in_process:
  938.  
  939. ; scan in full list, compare timestamp
  940.         lea     eax, [fileinfo]
  941.         stdcall get_fileinfo, edi, eax
  942.         test    eax, eax
  943.         jnz     .fail
  944.         mov     esi, [dll_list.fd]
  945. .scan_for_dlls:
  946.         cmp     esi, dll_list
  947.         jz      .load_new
  948.         lea     eax, [esi+DLLDESCR.name]
  949.         stdcall strncmp, eax, edi, -1
  950.         test    eax, eax
  951.         jnz     .continue_scan
  952. .test_prev_dll:
  953.         mov     eax, dword [fileinfo+24]; last modified time
  954.         mov     edx, dword [fileinfo+28]; last modified date
  955.         cmp     dword [esi+DLLDESCR.timestamp], eax
  956.         jnz     .continue_scan
  957.         cmp     dword [esi+DLLDESCR.timestamp+4], edx
  958.         jz      .dll_already_loaded
  959. .continue_scan:
  960.         mov     esi, [esi+DLLDESCR.fd]
  961.         jmp     .scan_for_dlls
  962.  
  963. ; new DLL
  964. .load_new:
  965. ; load file
  966.         stdcall load_file, edi
  967.         test    eax, eax
  968.         jz      .fail
  969.         mov     [coff], eax
  970.         mov     dword [fileinfo+32], ebx
  971.  
  972. ; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
  973.         mov     esi, edi
  974.         mov     ecx, -1
  975.         xor     eax, eax
  976.         repnz scasb
  977.         not     ecx
  978.         lea     eax, [ecx+sizeof.DLLDESCR]
  979.         push    ecx
  980.         call    malloc
  981.         pop     ecx
  982.         test    eax, eax
  983.         jz      .fail_and_free_coff
  984. ; save timestamp
  985.         lea     edi, [eax+DLLDESCR.name]
  986.         rep movsb
  987.         mov     esi, eax
  988.         mov     eax, dword [fileinfo+24]
  989.         mov     dword [esi+DLLDESCR.timestamp], eax
  990.         mov     eax, dword [fileinfo+28]
  991.         mov     dword [esi+DLLDESCR.timestamp+4], eax
  992. ; initialize DLLDESCR struct
  993.         and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
  994.         mov     [esi+DLLDESCR.fd], dll_list
  995.         mov     eax, [dll_list.bk]
  996.         mov     [dll_list.bk], esi
  997.         mov     [esi+DLLDESCR.bk], eax
  998.         mov     [eax+DLLDESCR.fd], esi
  999.  
  1000. ; calculate size of loaded DLL
  1001.         mov     edx, [coff]
  1002.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1003.         xor     ebx, ebx
  1004.  
  1005.         add     edx, 20
  1006. @@:
  1007.         call    coff_get_align
  1008.         add     ebx, eax
  1009.         not     eax
  1010.         and     ebx, eax
  1011.         add     ebx, [edx+COFF_SECTION.SizeOfRawData]
  1012.         add     edx, sizeof.COFF_SECTION
  1013.         dec     ecx
  1014.         jnz     @B
  1015. ; it must be nonzero and not too big
  1016.         mov     [esi+DLLDESCR.size], ebx
  1017.         test    ebx, ebx
  1018.         jz      .fail_and_free_dll
  1019.         cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
  1020.         ja      .fail_and_free_dll
  1021. ; allocate memory for kernel-side image
  1022.         stdcall kernel_alloc, ebx
  1023.         test    eax, eax
  1024.         jz      .fail_and_free_dll
  1025.         mov     [esi+DLLDESCR.data], eax
  1026. ; calculate preferred base address
  1027.         add     ebx, 0x1FFF
  1028.         and     ebx, not 0xFFF
  1029.         mov     ecx, [dll_cur_addr]
  1030.         lea     edx, [ecx+ebx]
  1031.         cmp     edx, MAX_DEFAULT_DLL_ADDR
  1032.         jb      @f
  1033.         mov     ecx, MIN_DEFAULT_DLL_ADDR
  1034.         lea     edx, [ecx+ebx]
  1035. @@:
  1036.         mov     [esi+DLLDESCR.defaultbase], ecx
  1037.         mov     [dll_cur_addr], edx
  1038.  
  1039. ; copy sections and set correct values for VirtualAddress'es in headers
  1040.         push    esi
  1041.         mov     edx, [coff]
  1042.         movzx   ebx, [edx+COFF_HEADER.nSections]
  1043.         mov     edi, eax
  1044.         add     edx, 20
  1045.         cld
  1046. @@:
  1047.         call    coff_get_align
  1048.         add     ecx, eax
  1049.         add     edi, eax
  1050.         not     eax
  1051.         and     ecx, eax
  1052.         and     edi, eax
  1053.         mov     [edx+COFF_SECTION.VirtualAddress], ecx
  1054.         add     ecx, [edx+COFF_SECTION.SizeOfRawData]
  1055.         mov     esi, [edx+COFF_SECTION.PtrRawData]
  1056.         push    ecx
  1057.         mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
  1058.         test    esi, esi
  1059.         jnz     .copy
  1060.         xor     eax, eax
  1061.         rep stosb
  1062.         jmp     .next
  1063. .copy:
  1064.         add     esi, [coff]
  1065.         rep movsb
  1066. .next:
  1067.         pop     ecx
  1068.         add     edx, sizeof.COFF_SECTION
  1069.         dec     ebx
  1070.         jnz     @B
  1071.         pop     esi
  1072.  
  1073. ; save some additional data from COFF file
  1074. ; later we will use COFF header, headers for sections and symbol table
  1075. ; and also relocations table for all sections
  1076.         mov     edx, [coff]
  1077.         mov     ebx, [edx+COFF_HEADER.pSymTable]
  1078.         mov     edi, dword [fileinfo+32]
  1079.         sub     edi, ebx
  1080.         jc      .fail_and_free_data
  1081.         mov     [esi+DLLDESCR.symbols_lim], edi
  1082.         add     ebx, edx
  1083.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1084.         lea     ecx, [ecx*5]
  1085.         lea     edi, [edi+ecx*8+20]
  1086.         add     edx, 20
  1087. @@:
  1088.         movzx   eax, [edx+COFF_SECTION.NumReloc]
  1089.         lea     eax, [eax*5]
  1090.         lea     edi, [edi+eax*2]
  1091.         add     edx, sizeof.COFF_SECTION
  1092.         sub     ecx, 5
  1093.         jnz     @b
  1094.         stdcall kernel_alloc, edi
  1095.         test    eax, eax
  1096.         jz      .fail_and_free_data
  1097.         mov     edx, [coff]
  1098.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1099.         lea     ecx, [ecx*5]
  1100.         lea     ecx, [ecx*2+5]
  1101.         mov     [esi+DLLDESCR.coff_hdr], eax
  1102.         push    esi
  1103.         mov     esi, edx
  1104.         mov     edi, eax
  1105.         rep movsd
  1106.         pop     esi
  1107.         mov     [esi+DLLDESCR.symbols_ptr], edi
  1108.         push    esi
  1109.         mov     ecx, [edx+COFF_HEADER.nSymbols]
  1110.         mov     [esi+DLLDESCR.symbols_num], ecx
  1111.         mov     ecx, [esi+DLLDESCR.symbols_lim]
  1112.         mov     esi, ebx
  1113.         rep movsb
  1114.         pop     esi
  1115.         mov     ebx, [esi+DLLDESCR.coff_hdr]
  1116.         push    esi
  1117.         movzx   eax, [edx+COFF_HEADER.nSections]
  1118.         lea     edx, [ebx+20]
  1119. @@:
  1120.         movzx   ecx, [edx+COFF_SECTION.NumReloc]
  1121.         lea     ecx, [ecx*5]
  1122.         mov     esi, [edx+COFF_SECTION.PtrReloc]
  1123.         mov     [edx+COFF_SECTION.PtrReloc], edi
  1124.         sub     [edx+COFF_SECTION.PtrReloc], ebx
  1125.         add     esi, [coff]
  1126.         shr     ecx, 1
  1127.         rep movsd
  1128.         adc     ecx, ecx
  1129.         rep movsw
  1130.         add     edx, sizeof.COFF_SECTION
  1131.         dec     eax
  1132.         jnz     @b
  1133.         pop     esi
  1134.  
  1135. ; fixup symbols
  1136.         mov     edx, ebx
  1137.         mov     eax, [ebx+COFF_HEADER.nSymbols]
  1138.         add     edx, 20
  1139.         mov     ecx, [esi+DLLDESCR.symbols_num]
  1140.         lea     ecx, [ecx*9]
  1141.         add     ecx, ecx
  1142.         add     ecx, [esi+DLLDESCR.symbols_ptr]
  1143.  
  1144.         stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
  1145.                 ecx, 0
  1146. ;          test eax, eax
  1147. ;          jnz @F
  1148. ;
  1149. ;@@:
  1150.  
  1151.         stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
  1152.         test    eax, eax
  1153.         jnz     @F
  1154.  
  1155.         stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
  1156. @@:
  1157.         mov     [esi+DLLDESCR.exports], eax
  1158.  
  1159. ; fix relocs in the hidden copy in kernel memory to default address
  1160. ; it is first fix; usually this will be enough, but second fix
  1161. ; can be necessary if real load address will not equal assumption
  1162.         mov     eax, [esi+DLLDESCR.data]
  1163.         sub     eax, [esi+DLLDESCR.defaultbase]
  1164.         stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
  1165.  
  1166.         stdcall kernel_free, [coff]
  1167.  
  1168. .dll_already_loaded:
  1169.         inc     [esi+DLLDESCR.refcount]
  1170.         push    esi
  1171.         call    init_heap
  1172.         pop     esi
  1173.  
  1174.         mov     edi, [esi+DLLDESCR.size]
  1175.         stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
  1176.         test    eax, eax
  1177.         jnz     @f
  1178.         stdcall user_alloc, edi
  1179.         test    eax, eax
  1180.         jz      .fail_and_dereference
  1181. @@:
  1182.         mov     [img_base], eax
  1183.         mov     eax, sizeof.HDLL
  1184.         call    malloc
  1185.         test    eax, eax
  1186.         jz      .fail_and_free_user
  1187.         mov     ebx, [CURRENT_TASK]
  1188.         shl     ebx, 5
  1189.         mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
  1190.         mov     [eax+HDLL.pid], edx
  1191.         push    eax
  1192.         call    init_dlls_in_thread
  1193.         pop     ebx
  1194.         test    eax, eax
  1195.         jz      .fail_and_free_user
  1196.         mov     edx, [eax+HDLL.fd]
  1197.         mov     [ebx+HDLL.fd], edx
  1198.         mov     [ebx+HDLL.bk], eax
  1199.         mov     [eax+HDLL.fd], ebx
  1200.         mov     [edx+HDLL.bk], ebx
  1201.         mov     eax, ebx
  1202.         mov     ebx, [img_base]
  1203.         mov     [eax+HDLL.base], ebx
  1204.         mov     [eax+HDLL.size], edi
  1205.         mov     [eax+HDLL.refcount], 1
  1206.         mov     [eax+HDLL.parent], esi
  1207.         mov     edx, ebx
  1208.         shr     edx, 12
  1209.         or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
  1210. ; copy entries of page table from kernel-side image to usermode
  1211. ; use copy-on-write for user-mode image, so map as readonly
  1212.         xor     edi, edi
  1213.         mov     ecx, [esi+DLLDESCR.data]
  1214.         shr     ecx, 12
  1215. .map_pages_loop:
  1216.         mov     eax, [page_tabs+ecx*4]
  1217.         and     eax, not 0xFFF
  1218.         or      al, PG_USER
  1219.         xchg    eax, [page_tabs+edx*4]
  1220.         test    al, 1
  1221.         jz      @f
  1222.         call    free_page
  1223. @@:
  1224.         invlpg  [ebx+edi]
  1225.         inc     ecx
  1226.         inc     edx
  1227.         add     edi, 0x1000
  1228.         cmp     edi, [esi+DLLDESCR.size]
  1229.         jb      .map_pages_loop
  1230.  
  1231. ; if real user-mode base is not equal to preferred base, relocate image
  1232.         sub     ebx, [esi+DLLDESCR.defaultbase]
  1233.         jz      @f
  1234.         stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
  1235. @@:
  1236.  
  1237.         mov     eax, [esi+DLLDESCR.exports]
  1238.         sub     eax, [esi+DLLDESCR.defaultbase]
  1239.         add     eax, [img_base]
  1240.         ret
  1241. .fail_and_free_data:
  1242.         stdcall kernel_free, [esi+DLLDESCR.data]
  1243. .fail_and_free_dll:
  1244.         mov     eax, esi
  1245.         call    free
  1246. .fail_and_free_coff:
  1247.         stdcall kernel_free, [coff]
  1248. .fail:
  1249.         xor     eax, eax
  1250.         ret
  1251. .fail_and_free_user:
  1252.         stdcall user_free, [img_base]
  1253. .fail_and_dereference:
  1254.         mov     eax, 1  ; delete 1 reference
  1255.         call    dereference_dll
  1256.         xor     eax, eax
  1257.         ret
  1258. endp
  1259.  
  1260. ; initialize [APPDATA.dlls_list_ptr] for given thread
  1261. ; DLL is per-process object, so APPDATA.dlls_list_ptr must be
  1262. ; kept in sync for all threads of one process.
  1263. ; out: eax = APPDATA.dlls_list_ptr if all is OK,
  1264. ; NULL if memory allocation failed
  1265. init_dlls_in_thread:
  1266.         mov     ebx, [current_slot]
  1267.         mov     eax, [ebx+APPDATA.dlls_list_ptr]
  1268.         test    eax, eax
  1269.         jnz     .ret
  1270.         push    [ebx+APPDATA.dir_table]
  1271.         mov     eax, 8
  1272.         call    malloc
  1273.         pop     edx
  1274.         test    eax, eax
  1275.         jz      .ret
  1276.         mov     [eax], eax
  1277.         mov     [eax+4], eax
  1278.         mov     ecx, [TASK_COUNT]
  1279.         mov     ebx, SLOT_BASE+256
  1280. .set:
  1281.         cmp     [ebx+APPDATA.dir_table], edx
  1282.         jnz     @f
  1283.         mov     [ebx+APPDATA.dlls_list_ptr], eax
  1284. @@:
  1285.         add     ebx, 256
  1286.         dec     ecx
  1287.         jnz     .set
  1288. .ret:
  1289.         ret
  1290.  
  1291. ; in: eax = number of references to delete, esi -> DLLDESCR struc
  1292. dereference_dll:
  1293.         sub     [esi+DLLDESCR.refcount], eax
  1294.         jnz     .ret
  1295.         mov     eax, [esi+DLLDESCR.fd]
  1296.         mov     edx, [esi+DLLDESCR.bk]
  1297.         mov     [eax+DLLDESCR.bk], edx
  1298.         mov     [edx+DLLDESCR.fd], eax
  1299.         stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
  1300.         stdcall kernel_free, [esi+DLLDESCR.data]
  1301.         mov     eax, esi
  1302.         call    free
  1303. .ret:
  1304.         ret
  1305.  
  1306. destroy_hdll:
  1307.         push    ebx ecx esi edi
  1308.         push    eax
  1309.         mov     ebx, [eax+HDLL.base]
  1310.         mov     esi, [eax+HDLL.parent]
  1311.         mov     edx, [esi+DLLDESCR.size]
  1312. ; The following actions require the context of application where HDLL is mapped.
  1313. ; However, destroy_hdll can be called in the context of OS thread when
  1314. ; cleaning up objects created by the application which is destroyed.
  1315. ; So remember current cr3 and set it to page table of target.
  1316.         mov     eax, [ecx+APPDATA.dir_table]
  1317. ; Because we cheat with cr3, disable interrupts: task switch would restore
  1318. ; page table from APPDATA of current thread.
  1319. ; Also set [current_slot] because it is used by user_free.
  1320.         pushf
  1321.         cli
  1322.         push    [current_slot]
  1323.         mov     [current_slot], ecx
  1324.         mov     ecx, cr3
  1325.         push    ecx
  1326.         mov     cr3, eax
  1327.         push    ebx     ; argument for user_free
  1328.         mov     eax, ebx
  1329.         shr     ebx, 12
  1330.         push    ebx
  1331.         mov     esi, [esi+DLLDESCR.data]
  1332.         shr     esi, 12
  1333. .unmap_loop:
  1334.         push    eax
  1335.         mov     eax, 2
  1336.         xchg    eax, [page_tabs+ebx*4]
  1337.         mov     ecx, [page_tabs+esi*4]
  1338.         and     eax, not 0xFFF
  1339.         and     ecx, not 0xFFF
  1340.         cmp     eax, ecx
  1341.         jz      @f
  1342.         call    free_page
  1343. @@:
  1344.         pop     eax
  1345.         invlpg  [eax]
  1346.         add     eax, 0x1000
  1347.         inc     ebx
  1348.         inc     esi
  1349.         sub     edx, 0x1000
  1350.         ja      .unmap_loop
  1351.         pop     ebx
  1352.         and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
  1353.         call    user_free
  1354. ; Restore context.
  1355.         pop     eax
  1356.         mov     cr3, eax
  1357.         pop     [current_slot]
  1358.         popf
  1359. ; Ok, cheating is done.
  1360.         pop     eax
  1361.         push    eax
  1362.         mov     esi, [eax+HDLL.parent]
  1363.         mov     eax, [eax+HDLL.refcount]
  1364.         call    dereference_dll
  1365.         pop     eax
  1366.         mov     edx, [eax+HDLL.bk]
  1367.         mov     ebx, [eax+HDLL.fd]
  1368.         mov     [ebx+HDLL.bk], edx
  1369.         mov     [edx+HDLL.fd], ebx
  1370.         call    free
  1371.         pop     edi esi ecx ebx
  1372.         ret
  1373.  
  1374. ; ecx -> APPDATA for slot, esi = dlls_list_ptr
  1375. destroy_all_hdlls:
  1376.         test    esi, esi
  1377.         jz      .ret
  1378. .loop:
  1379.         mov     eax, [esi+HDLL.fd]
  1380.         cmp     eax, esi
  1381.         jz      free
  1382.         call    destroy_hdll
  1383.         jmp     .loop
  1384. .ret:
  1385.         ret
  1386.  
  1387. align 4
  1388. stop_all_services:
  1389.         push    ebp
  1390.         mov     edx, [srv.fd]
  1391. .next:
  1392.         cmp     edx, srv.fd-SRV.fd
  1393.         je      .done
  1394.         cmp     [edx+SRV.magic], ' SRV'
  1395.         jne     .next
  1396.         cmp     [edx+SRV.size], sizeof.SRV
  1397.         jne     .next
  1398.  
  1399.         mov     ebx, [edx+SRV.entry]
  1400.         mov     edx, [edx+SRV.fd]
  1401.         test    ebx, ebx
  1402.         jz      .next
  1403.  
  1404.         push    edx
  1405.         mov     ebp, esp
  1406.         push    0
  1407.         push    -1
  1408.         call    ebx
  1409.         mov     esp, ebp
  1410.         pop     edx
  1411.         jmp     .next
  1412. .done:
  1413.         pop     ebp
  1414.         ret
  1415.  
  1416. ; param
  1417. ;  eax= size
  1418. ;  ebx= pid
  1419.  
  1420. align 4
  1421. create_kernel_object:
  1422.  
  1423.         push    ebx
  1424.         call    malloc
  1425.         pop     ebx
  1426.         test    eax, eax
  1427.         jz      .fail
  1428.  
  1429.         mov     ecx, [current_slot]
  1430.         add     ecx, APP_OBJ_OFFSET
  1431.  
  1432.         pushfd
  1433.         cli
  1434.         mov     edx, [ecx+APPOBJ.fd]
  1435.         mov     [eax+APPOBJ.fd], edx
  1436.         mov     [eax+APPOBJ.bk], ecx
  1437.         mov     [eax+APPOBJ.pid], ebx
  1438.  
  1439.         mov     [ecx+APPOBJ.fd], eax
  1440.         mov     [edx+APPOBJ.bk], eax
  1441.         popfd
  1442. .fail:
  1443.         ret
  1444.  
  1445. ; param
  1446. ;  eax= object
  1447.  
  1448. align 4
  1449. destroy_kernel_object:
  1450.  
  1451.         pushfd
  1452.         cli
  1453.         mov     ebx, [eax+APPOBJ.fd]
  1454.         mov     ecx, [eax+APPOBJ.bk]
  1455.         mov     [ebx+APPOBJ.bk], ecx
  1456.         mov     [ecx+APPOBJ.fd], ebx
  1457.         popfd
  1458.  
  1459.         xor     edx, edx       ;clear common header
  1460.         mov     [eax], edx
  1461.         mov     [eax+4], edx
  1462.         mov     [eax+8], edx
  1463.         mov     [eax+12], edx
  1464.         mov     [eax+16], edx
  1465.  
  1466.         call    free           ;release object memory
  1467.         ret
  1468.