Subversion Repositories Kolibri OS

Rev

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