Subversion Repositories Kolibri OS

Rev

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