Subversion Repositories Kolibri OS

Rev

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

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