Subversion Repositories Kolibri OS

Rev

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