Subversion Repositories Kolibri OS

Rev

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

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