Subversion Repositories Kolibri OS

Rev

Rev 3555 | Rev 4265 | 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: 3908 $
  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.  
  462.         lea     eax, [attr]
  463.         stdcall get_fileinfo, [file_name], eax   ;find file and get info
  464.         test    eax, eax
  465.         jnz     .err_1
  466.  
  467.         mov     eax, [file_size]
  468.         cmp     eax, 1024*1024*16                ;to be enough for anybody (c)
  469.         ja      .err_1
  470.                                                  ;it is very likely that the file is packed
  471.         stdcall kernel_alloc, [file_size]        ;with kpack, so allocate memory from kernel heap
  472.         mov     [km_file], eax
  473.         test    eax, eax
  474.         jz      .err_1
  475.  
  476.         stdcall read_file, [file_name], eax, dword 0, [file_size]
  477.         cmp     ebx, [file_size]
  478.  
  479.         jne     .err_2
  480.  
  481.         mov     eax, [km_file]
  482.         cmp     dword [eax], 0x4B43504B          ; check kpack signature
  483.         jne     .raw_file
  484.  
  485.         mov     ebx, [eax+4]                     ;get real size of file
  486.         mov     [file_size], ebx
  487.         stdcall user_alloc, ebx                  ;and allocate memory from user heap
  488.         mov     [um_file], eax
  489.         test    eax, eax
  490.         jz      .err_2
  491.  
  492.         pushad
  493.         mov     ecx, unpack_mutex
  494.         call    mutex_lock
  495.  
  496.         stdcall unpack, [km_file], [um_file]
  497.  
  498.         mov     ecx, unpack_mutex
  499.         call    mutex_unlock
  500.         popad
  501.  
  502.         stdcall kernel_free, [km_file]           ;we don't need packed file anymore
  503. .exit:
  504.         mov     eax, [um_file]
  505.         mov     edx, [file_size]
  506.  
  507.         pop     ebx
  508.         pop     edi
  509.         pop     esi
  510.         ret
  511.  
  512.  
  513. .raw_file:                                       ; sometimes we load unpacked file
  514.         stdcall user_alloc, ebx                  ; allocate space from user heap
  515.         mov     [um_file], eax
  516.  
  517.         test    eax, eax
  518.         jz      .err_2
  519.  
  520.         shr     eax, 10                          ; and remap pages.
  521.  
  522.         mov     ecx, [file_size]
  523.         add     ecx, 4095
  524.         shr     ecx, 12
  525.  
  526.         mov     esi, [km_file]
  527.         shr     esi, 10
  528.         add     esi, page_tabs
  529.  
  530.         lea     edi, [page_tabs+eax]
  531.  
  532.         cld
  533. @@:
  534.         lodsd
  535.         and     eax, 0xFFFFF000
  536.         or      eax, PG_USER
  537.         stosd
  538.         loop    @B
  539.  
  540.         stdcall free_kernel_space, [km_file]     ; release allocated kernel space
  541.         jmp     .exit                            ; physical pages still in use
  542.  
  543. .err_2:
  544.         stdcall kernel_free, [km_file]
  545. .err_1:
  546.         xor     eax, eax
  547.         xor     edx, edx
  548.  
  549.         pop     ebx
  550.         pop     edi
  551.         pop     esi
  552.         ret
  553. endp
  554.  
  555.  
  556. uglobal
  557. align 4
  558. unpack_mutex MUTEX
  559. endg
  560.  
  561. align 4
  562. proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
  563.         mov     ebx, [imports]
  564.         test    ebx, ebx
  565.         jz      .end
  566.         xor     esi, esi
  567. .look_up:
  568.  
  569.         mov     eax, [ebx+32]
  570.         mov     eax, [OS_BASE+eax+esi*4]
  571.         add     eax, OS_BASE
  572.         stdcall strncmp, eax, [proc_name], 256
  573.         test    eax, eax
  574.         jz      .ok
  575.  
  576.         inc     esi
  577.         cmp     esi, [ebx+24]
  578.         jb      .look_up
  579. .end:
  580.         xor     eax, eax
  581.         ret
  582. .ok:
  583.         mov     eax, [ebx+28]
  584.         mov     eax, [OS_BASE+eax+esi*4]
  585.         add     eax, OS_BASE
  586.         ret
  587. endp
  588.  
  589. align 4
  590. proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
  591.                       sym_count:dword, strings:dword, imports:dword
  592.            locals
  593.              retval dd ?
  594.            endl
  595.  
  596.         mov     edi, [symbols]
  597.         mov     [retval], 1
  598. .fix:
  599.         movzx   ebx, [edi+COFF_SYM.SectionNumber]
  600.         test    ebx, ebx
  601.         jnz     .internal
  602.         mov     eax, dword [edi+COFF_SYM.Name]
  603.         test    eax, eax
  604.         jnz     @F
  605.  
  606.         mov     edi, [edi+4]
  607.         add     edi, [strings]
  608. @@:
  609.         push    edi
  610.         stdcall get_proc_ex, edi, [imports]
  611.         pop     edi
  612.  
  613.         xor     ebx, ebx
  614.         test    eax, eax
  615.         jnz     @F
  616.  
  617.         mov     esi, msg_unresolved
  618.         call    sys_msg_board_str
  619.         mov     esi, edi
  620.         call    sys_msg_board_str
  621.         mov     esi, msg_CR
  622.         call    sys_msg_board_str
  623.  
  624.         mov     [retval], 0
  625. @@:
  626.         mov     edi, [symbols]
  627.         mov     [edi+COFF_SYM.Value], eax
  628.         jmp     .next
  629. .internal:
  630.         cmp     bx, -1
  631.         je      .next
  632.         cmp     bx, -2
  633.         je      .next
  634.  
  635.         dec     ebx
  636.         shl     ebx, 3
  637.         lea     ebx, [ebx+ebx*4]
  638.         add     ebx, [sec]
  639.  
  640.         mov     eax, [ebx+COFF_SECTION.VirtualAddress]
  641.         add     [edi+COFF_SYM.Value], eax
  642. .next:
  643.         add     edi, sizeof.COFF_SYM
  644.         mov     [symbols], edi
  645.         dec     [sym_count]
  646.         jnz     .fix
  647.         mov     eax, [retval]
  648.         ret
  649. endp
  650.  
  651. align 4
  652. proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
  653.         delta:dword
  654.            locals
  655.              n_sec     dd ?
  656.            endl
  657.  
  658.         mov     eax, [coff]
  659.         movzx   ebx, [eax+COFF_HEADER.nSections]
  660.         mov     [n_sec], ebx
  661.         lea     esi, [eax+20]
  662. .fix_sec:
  663.         mov     edi, [esi+COFF_SECTION.PtrReloc]
  664.         add     edi, [coff]
  665.  
  666.         movzx   ecx, [esi+COFF_SECTION.NumReloc]
  667.         test    ecx, ecx
  668.         jz      .next
  669. .reloc_loop:
  670.         mov     ebx, [edi+COFF_RELOC.SymIndex]
  671.         add     ebx, ebx
  672.         lea     ebx, [ebx+ebx*8]
  673.         add     ebx, [sym]
  674.  
  675.         mov     edx, [ebx+COFF_SYM.Value]
  676.  
  677.         cmp     [edi+COFF_RELOC.Type], 6
  678.         je      .dir_32
  679.  
  680.         cmp     [edi+COFF_RELOC.Type], 20
  681.         jne     .next_reloc
  682. .rel_32:
  683.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  684.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  685.         sub     edx, eax
  686.         sub     edx, 4
  687.         jmp     .fix
  688. .dir_32:
  689.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  690.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  691. .fix:
  692.         add     eax, [delta]
  693.         add     [eax], edx
  694. .next_reloc:
  695.         add     edi, 10
  696.         dec     ecx
  697.         jnz     .reloc_loop
  698. .next:
  699.         add     esi, sizeof.COFF_SECTION
  700.         dec     [n_sec]
  701.         jnz     .fix_sec
  702. .exit:
  703.         ret
  704. endp
  705.  
  706. align 4
  707. proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
  708.         delta:dword
  709.            locals
  710.              n_sec     dd ?
  711.            endl
  712.  
  713.         mov     eax, [coff]
  714.         movzx   ebx, [eax+COFF_HEADER.nSections]
  715.         mov     [n_sec], ebx
  716.         lea     esi, [eax+20]
  717.         mov     edx, [delta]
  718. .fix_sec:
  719.         mov     edi, [esi+COFF_SECTION.PtrReloc]
  720.         add     edi, [coff]
  721.  
  722.         movzx   ecx, [esi+COFF_SECTION.NumReloc]
  723.         test    ecx, ecx
  724.         jz      .next
  725. .reloc_loop:
  726.         cmp     [edi+COFF_RELOC.Type], 6
  727.         jne     .next_reloc
  728. .dir_32:
  729.         mov     eax, [edi+COFF_RELOC.VirtualAddress]
  730.         add     eax, [esi+COFF_SECTION.VirtualAddress]
  731.         add     [eax+edx], edx
  732. .next_reloc:
  733.         add     edi, 10
  734.         dec     ecx
  735.         jnz     .reloc_loop
  736. .next:
  737.         add     esi, sizeof.COFF_SECTION
  738.         dec     [n_sec]
  739.         jnz     .fix_sec
  740. .exit:
  741.         ret
  742. endp
  743.  
  744. align 4
  745. proc load_driver stdcall, driver_name:dword
  746.            locals
  747.              coff      dd ?
  748.              sym       dd ?
  749.              strings   dd ?
  750.              img_size  dd ?
  751.              img_base  dd ?
  752.              start     dd ?
  753.  
  754.              file_name rb 13+16+4+1      ; '/sys/drivers/<up-to-16-chars>.obj'
  755.            endl
  756.  
  757.         lea     edx, [file_name]
  758.         mov     dword [edx], '/sys'
  759.         mov     dword [edx+4], '/dri'
  760.         mov     dword [edx+8], 'vers'
  761.         mov     byte [edx+12], '/'
  762.         mov     esi, [driver_name]
  763. .redo:
  764.         lea     edx, [file_name]
  765.         lea     edi, [edx+13]
  766.         mov     ecx, 16
  767. @@:
  768.         lodsb
  769.         test    al, al
  770.         jz      @f
  771.         stosb
  772.         loop    @b
  773. @@:
  774.         mov     dword [edi], '.obj'
  775.         mov     byte [edi+4], 0
  776.         stdcall load_file, edx
  777.  
  778.         test    eax, eax
  779.         jz      .exit
  780.  
  781.         mov     [coff], eax
  782.  
  783.         movzx   ecx, [eax+COFF_HEADER.nSections]
  784.         xor     ebx, ebx
  785.  
  786.         lea     edx, [eax+20]
  787. @@:
  788.         add     ebx, [edx+COFF_SECTION.SizeOfRawData]
  789.         add     ebx, 15
  790.         and     ebx, not 15
  791.         add     edx, sizeof.COFF_SECTION
  792.         dec     ecx
  793.         jnz     @B
  794.         mov     [img_size], ebx
  795.  
  796.         stdcall kernel_alloc, ebx
  797.         test    eax, eax
  798.         jz      .fail
  799.         mov     [img_base], eax
  800.  
  801.         mov     edi, eax
  802.         xor     eax, eax
  803.         mov     ecx, [img_size]
  804.         add     ecx, 4095
  805.         and     ecx, not 4095
  806.         shr     ecx, 2
  807.         cld
  808.         rep stosd
  809.  
  810.         mov     edx, [coff]
  811.         movzx   ebx, [edx+COFF_HEADER.nSections]
  812.         mov     edi, [img_base]
  813.         lea     eax, [edx+20]
  814. @@:
  815.         mov     [eax+COFF_SECTION.VirtualAddress], edi
  816.         mov     esi, [eax+COFF_SECTION.PtrRawData]
  817.         test    esi, esi
  818.         jnz     .copy
  819.         add     edi, [eax+COFF_SECTION.SizeOfRawData]
  820.         jmp     .next
  821. .copy:
  822.         add     esi, edx
  823.         mov     ecx, [eax+COFF_SECTION.SizeOfRawData]
  824.         cld
  825.         rep movsb
  826. .next:
  827.         add     edi, 15
  828.         and     edi, not 15
  829.         add     eax, sizeof.COFF_SECTION
  830.         dec     ebx
  831.         jnz     @B
  832.  
  833.         mov     ebx, [edx+COFF_HEADER.pSymTable]
  834.         add     ebx, edx
  835.         mov     [sym], ebx
  836.         mov     ecx, [edx+COFF_HEADER.nSymbols]
  837.         add     ecx, ecx
  838.         lea     ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE
  839.         add     ecx, [sym]
  840.         mov     [strings], ecx
  841.  
  842.         lea     eax, [edx+20]
  843.  
  844.         stdcall fix_coff_symbols, eax, [sym], [edx+COFF_HEADER.nSymbols], \
  845.                 [strings], __exports
  846.         test    eax, eax
  847.         jz      .link_fail
  848.  
  849.         mov     ebx, [coff]
  850.         stdcall fix_coff_relocs, ebx, [sym], 0
  851.  
  852.         stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szVersion
  853.         test    eax, eax
  854.         jz      .link_fail
  855.  
  856.         mov     eax, [eax]
  857.         shr     eax, 16
  858.         cmp     eax, DRV_COMPAT
  859.         jb      .ver_fail
  860.  
  861.         cmp     eax, DRV_CURRENT
  862.         ja      .ver_fail
  863.  
  864.         mov     ebx, [coff]
  865.         stdcall get_coff_sym, [sym], [ebx+COFF_HEADER.nSymbols], szSTART
  866.         mov     [start], eax
  867.  
  868.         stdcall kernel_free, [coff]
  869.  
  870.         mov     ebx, [start]
  871.         stdcall ebx, DRV_ENTRY
  872.         test    eax, eax
  873.         jnz     .ok
  874.  
  875.         stdcall kernel_free, [img_base]
  876.  
  877.         xor     eax, eax
  878.         ret
  879. .ok:
  880.         mov     ebx, [img_base]
  881.         mov     [eax+SRV.base], ebx
  882.         mov     ecx, [start]
  883.         mov     [eax+SRV.entry], ecx
  884.         ret
  885.  
  886. .ver_fail:
  887.         mov     esi, msg_CR
  888.         call    sys_msg_board_str
  889.         mov     esi, [driver_name]
  890.         call    sys_msg_board_str
  891.         mov     esi, msg_CR
  892.         call    sys_msg_board_str
  893.         mov     esi, msg_version
  894.         call    sys_msg_board_str
  895.         mov     esi, msg_www
  896.         call    sys_msg_board_str
  897.         jmp     .cleanup
  898.  
  899. .link_fail:
  900.         mov     esi, msg_module
  901.         call    sys_msg_board_str
  902.         mov     esi, [driver_name]
  903.         call    sys_msg_board_str
  904.         mov     esi, msg_CR
  905.         call    sys_msg_board_str
  906. .cleanup:
  907.         stdcall kernel_free, [img_base]
  908. .fail:
  909.         stdcall kernel_free, [coff]
  910. .exit:
  911.         xor     eax, eax
  912.         ret
  913. endp
  914.  
  915. ; in: edx -> COFF_SECTION struct
  916. ; out: eax = alignment as mask for bits to drop
  917. coff_get_align:
  918. ; Rules:
  919. ; - if alignment is not given, use default = 4K;
  920. ; - if alignment is given and is no more than 4K, use it;
  921. ; - if alignment is more than 4K, revert to 4K.
  922.         push    ecx
  923.         mov     cl, byte [edx+COFF_SECTION.Characteristics+2]
  924.         mov     eax, 1
  925.         shr     cl, 4
  926.         dec     cl
  927.         js      .default
  928.         cmp     cl, 12
  929.         jbe     @f
  930. .default:
  931.         mov     cl, 12
  932. @@:
  933.         shl     eax, cl
  934.         pop     ecx
  935.         dec     eax
  936.         ret
  937.  
  938. align 4
  939. proc load_library stdcall, file_name:dword
  940.            locals
  941.              fullname  rb 260
  942.              fileinfo  rb 40
  943.              coff      dd ?
  944.              img_base  dd ?
  945.            endl
  946.  
  947. ; resolve file name
  948.         mov     ebx, [file_name]
  949.         lea     edi, [fullname+1]
  950.         mov     byte [edi-1], '/'
  951.         stdcall get_full_file_name, edi, 259
  952.         test    al, al
  953.         jz      .fail
  954.  
  955. ; scan for required DLL in list of already loaded for this process,
  956. ; ignore timestamp
  957.         cli
  958.  
  959.         mov     esi, [CURRENT_TASK]
  960.         shl     esi, 8
  961.         lea     edi, [fullname]
  962.         mov     ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
  963.         test    ebx, ebx
  964.         jz      .not_in_process
  965.         mov     esi, [ebx+HDLL.fd]
  966. .scan_in_process:
  967.         cmp     esi, ebx
  968.         jz      .not_in_process
  969.         mov     eax, [esi+HDLL.parent]
  970.         add     eax, DLLDESCR.name
  971.         stdcall strncmp, eax, edi, -1
  972.         test    eax, eax
  973.         jnz     .next_in_process
  974. ; simple variant: load DLL which is already loaded in this process
  975. ; just increment reference counters and return address of exports table
  976.         inc     [esi+HDLL.refcount]
  977.         mov     ecx, [esi+HDLL.parent]
  978.         inc     [ecx+DLLDESCR.refcount]
  979.         mov     eax, [ecx+DLLDESCR.exports]
  980.         sub     eax, [ecx+DLLDESCR.defaultbase]
  981.         add     eax, [esi+HDLL.base]
  982.         sti
  983.         ret
  984. .next_in_process:
  985.         mov     esi, [esi+HDLL.fd]
  986.         jmp     .scan_in_process
  987. .not_in_process:
  988.  
  989. ; scan in full list, compare timestamp
  990.         sti
  991.         lea     eax, [fileinfo]
  992.         stdcall get_fileinfo, edi, eax
  993.         test    eax, eax
  994.         jnz     .fail
  995.         cli
  996.         mov     esi, [dll_list.fd]
  997. .scan_for_dlls:
  998.         cmp     esi, dll_list
  999.         jz      .load_new
  1000.         lea     eax, [esi+DLLDESCR.name]
  1001.         stdcall strncmp, eax, edi, -1
  1002.         test    eax, eax
  1003.         jnz     .continue_scan
  1004. .test_prev_dll:
  1005.         mov     eax, dword [fileinfo+24]; last modified time
  1006.         mov     edx, dword [fileinfo+28]; last modified date
  1007.         cmp     dword [esi+DLLDESCR.timestamp], eax
  1008.         jnz     .continue_scan
  1009.         cmp     dword [esi+DLLDESCR.timestamp+4], edx
  1010.         jz      .dll_already_loaded
  1011. .continue_scan:
  1012.         mov     esi, [esi+DLLDESCR.fd]
  1013.         jmp     .scan_for_dlls
  1014.  
  1015. ; new DLL
  1016. .load_new:
  1017.         sti
  1018. ; load file
  1019.         stdcall load_file, edi
  1020.         test    eax, eax
  1021.         jz      .fail
  1022.         mov     [coff], eax
  1023.         mov     dword [fileinfo+32], ebx
  1024.  
  1025. ; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
  1026.         mov     esi, edi
  1027.         mov     ecx, -1
  1028.         xor     eax, eax
  1029.         repnz scasb
  1030.         not     ecx
  1031.         lea     eax, [ecx+sizeof.DLLDESCR]
  1032.         push    ecx
  1033.         call    malloc
  1034.         pop     ecx
  1035.         test    eax, eax
  1036.         jz      .fail_and_free_coff
  1037. ; save timestamp
  1038.         lea     edi, [eax+DLLDESCR.name]
  1039.         rep movsb
  1040.         mov     esi, eax
  1041.         mov     eax, dword [fileinfo+24]
  1042.         mov     dword [esi+DLLDESCR.timestamp], eax
  1043.         mov     eax, dword [fileinfo+28]
  1044.         mov     dword [esi+DLLDESCR.timestamp+4], eax
  1045.  
  1046. ; calculate size of loaded DLL
  1047.         mov     edx, [coff]
  1048.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1049.         xor     ebx, ebx
  1050.  
  1051.         add     edx, 20
  1052. @@:
  1053.         call    coff_get_align
  1054.         add     ebx, eax
  1055.         not     eax
  1056.         and     ebx, eax
  1057.         add     ebx, [edx+COFF_SECTION.SizeOfRawData]
  1058.         add     edx, sizeof.COFF_SECTION
  1059.         dec     ecx
  1060.         jnz     @B
  1061. ; it must be nonzero and not too big
  1062.         mov     [esi+DLLDESCR.size], ebx
  1063.         test    ebx, ebx
  1064.         jz      .fail_and_free_dll
  1065.         cmp     ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
  1066.         ja      .fail_and_free_dll
  1067. ; allocate memory for kernel-side image
  1068.         stdcall kernel_alloc, ebx
  1069.         test    eax, eax
  1070.         jz      .fail_and_free_dll
  1071.         mov     [esi+DLLDESCR.data], eax
  1072. ; calculate preferred base address
  1073.         add     ebx, 0x1FFF
  1074.         and     ebx, not 0xFFF
  1075.         mov     ecx, [dll_cur_addr]
  1076.         lea     edx, [ecx+ebx]
  1077.         cmp     edx, MAX_DEFAULT_DLL_ADDR
  1078.         jb      @f
  1079.         mov     ecx, MIN_DEFAULT_DLL_ADDR
  1080.         lea     edx, [ecx+ebx]
  1081. @@:
  1082.         mov     [esi+DLLDESCR.defaultbase], ecx
  1083.         mov     [dll_cur_addr], edx
  1084.  
  1085. ; copy sections and set correct values for VirtualAddress'es in headers
  1086.         push    esi
  1087.         mov     edx, [coff]
  1088.         movzx   ebx, [edx+COFF_HEADER.nSections]
  1089.         mov     edi, eax
  1090.         add     edx, 20
  1091.         cld
  1092. @@:
  1093.         call    coff_get_align
  1094.         add     ecx, eax
  1095.         add     edi, eax
  1096.         not     eax
  1097.         and     ecx, eax
  1098.         and     edi, eax
  1099.         mov     [edx+COFF_SECTION.VirtualAddress], ecx
  1100.         add     ecx, [edx+COFF_SECTION.SizeOfRawData]
  1101.         mov     esi, [edx+COFF_SECTION.PtrRawData]
  1102.         push    ecx
  1103.         mov     ecx, [edx+COFF_SECTION.SizeOfRawData]
  1104.         test    esi, esi
  1105.         jnz     .copy
  1106.         xor     eax, eax
  1107.         rep stosb
  1108.         jmp     .next
  1109. .copy:
  1110.         add     esi, [coff]
  1111.         rep movsb
  1112. .next:
  1113.         pop     ecx
  1114.         add     edx, sizeof.COFF_SECTION
  1115.         dec     ebx
  1116.         jnz     @B
  1117.         pop     esi
  1118.  
  1119. ; save some additional data from COFF file
  1120. ; later we will use COFF header, headers for sections and symbol table
  1121. ; and also relocations table for all sections
  1122.         mov     edx, [coff]
  1123.         mov     ebx, [edx+COFF_HEADER.pSymTable]
  1124.         mov     edi, dword [fileinfo+32]
  1125.         sub     edi, ebx
  1126.         jc      .fail_and_free_data
  1127.         mov     [esi+DLLDESCR.symbols_lim], edi
  1128.         add     ebx, edx
  1129.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1130.         lea     ecx, [ecx*5]
  1131.         lea     edi, [edi+ecx*8+20]
  1132.         add     edx, 20
  1133. @@:
  1134.         movzx   eax, [edx+COFF_SECTION.NumReloc]
  1135.         lea     eax, [eax*5]
  1136.         lea     edi, [edi+eax*2]
  1137.         add     edx, sizeof.COFF_SECTION
  1138.         sub     ecx, 5
  1139.         jnz     @b
  1140.         stdcall kernel_alloc, edi
  1141.         test    eax, eax
  1142.         jz      .fail_and_free_data
  1143.         mov     edx, [coff]
  1144.         movzx   ecx, [edx+COFF_HEADER.nSections]
  1145.         lea     ecx, [ecx*5]
  1146.         lea     ecx, [ecx*2+5]
  1147.         mov     [esi+DLLDESCR.coff_hdr], eax
  1148.         push    esi
  1149.         mov     esi, edx
  1150.         mov     edi, eax
  1151.         rep movsd
  1152.         pop     esi
  1153.         mov     [esi+DLLDESCR.symbols_ptr], edi
  1154.         push    esi
  1155.         mov     ecx, [edx+COFF_HEADER.nSymbols]
  1156.         mov     [esi+DLLDESCR.symbols_num], ecx
  1157.         mov     ecx, [esi+DLLDESCR.symbols_lim]
  1158.         mov     esi, ebx
  1159.         rep movsb
  1160.         pop     esi
  1161.         mov     ebx, [esi+DLLDESCR.coff_hdr]
  1162.         push    esi
  1163.         movzx   eax, [edx+COFF_HEADER.nSections]
  1164.         lea     edx, [ebx+20]
  1165. @@:
  1166.         movzx   ecx, [edx+COFF_SECTION.NumReloc]
  1167.         lea     ecx, [ecx*5]
  1168.         mov     esi, [edx+COFF_SECTION.PtrReloc]
  1169.         mov     [edx+COFF_SECTION.PtrReloc], edi
  1170.         sub     [edx+COFF_SECTION.PtrReloc], ebx
  1171.         add     esi, [coff]
  1172.         shr     ecx, 1
  1173.         rep movsd
  1174.         adc     ecx, ecx
  1175.         rep movsw
  1176.         add     edx, sizeof.COFF_SECTION
  1177.         dec     eax
  1178.         jnz     @b
  1179.         pop     esi
  1180.  
  1181. ; fixup symbols
  1182.         mov     edx, ebx
  1183.         mov     eax, [ebx+COFF_HEADER.nSymbols]
  1184.         add     edx, 20
  1185.         mov     ecx, [esi+DLLDESCR.symbols_num]
  1186.         lea     ecx, [ecx*9]
  1187.         add     ecx, ecx
  1188.         add     ecx, [esi+DLLDESCR.symbols_ptr]
  1189.  
  1190.         stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \
  1191.                 ecx, 0
  1192. ;          test eax, eax
  1193. ;          jnz @F
  1194. ;
  1195. ;@@:
  1196.  
  1197.         stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
  1198.         test    eax, eax
  1199.         jnz     @F
  1200.  
  1201.         stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
  1202. @@:
  1203.         mov     [esi+DLLDESCR.exports], eax
  1204.  
  1205. ; fix relocs in the hidden copy in kernel memory to default address
  1206. ; it is first fix; usually this will be enough, but second fix
  1207. ; can be necessary if real load address will not equal assumption
  1208.         mov     eax, [esi+DLLDESCR.data]
  1209.         sub     eax, [esi+DLLDESCR.defaultbase]
  1210.         stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
  1211.  
  1212.         stdcall kernel_free, [coff]
  1213.  
  1214.         cli
  1215. ; initialize DLLDESCR struct
  1216.         and     dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented
  1217.         mov     [esi+DLLDESCR.fd], dll_list
  1218.         mov     eax, [dll_list.bk]
  1219.         mov     [dll_list.bk], esi
  1220.         mov     [esi+DLLDESCR.bk], eax
  1221.         mov     [eax+DLLDESCR.fd], esi
  1222. .dll_already_loaded:
  1223.         inc     [esi+DLLDESCR.refcount]
  1224.         push    esi
  1225.         call    init_heap
  1226.         pop     esi
  1227.  
  1228.         mov     edi, [esi+DLLDESCR.size]
  1229.         stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
  1230.         test    eax, eax
  1231.         jnz     @f
  1232.         stdcall user_alloc, edi
  1233.         test    eax, eax
  1234.         jz      .fail_and_dereference
  1235. @@:
  1236.         mov     [img_base], eax
  1237.         mov     eax, sizeof.HDLL
  1238.         call    malloc
  1239.         test    eax, eax
  1240.         jz      .fail_and_free_user
  1241.         mov     ebx, [CURRENT_TASK]
  1242.         shl     ebx, 5
  1243.         mov     edx, [CURRENT_TASK+ebx+TASKDATA.pid]
  1244.         mov     [eax+HDLL.pid], edx
  1245.         push    eax
  1246.         call    init_dlls_in_thread
  1247.         pop     ebx
  1248.         test    eax, eax
  1249.         jz      .fail_and_free_user
  1250.         mov     edx, [eax+HDLL.fd]
  1251.         mov     [ebx+HDLL.fd], edx
  1252.         mov     [ebx+HDLL.bk], eax
  1253.         mov     [eax+HDLL.fd], ebx
  1254.         mov     [edx+HDLL.bk], ebx
  1255.         mov     eax, ebx
  1256.         mov     ebx, [img_base]
  1257.         mov     [eax+HDLL.base], ebx
  1258.         mov     [eax+HDLL.size], edi
  1259.         mov     [eax+HDLL.refcount], 1
  1260.         mov     [eax+HDLL.parent], esi
  1261.         mov     edx, ebx
  1262.         shr     edx, 12
  1263.         or      dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
  1264. ; copy entries of page table from kernel-side image to usermode
  1265. ; use copy-on-write for user-mode image, so map as readonly
  1266.         xor     edi, edi
  1267.         mov     ecx, [esi+DLLDESCR.data]
  1268.         shr     ecx, 12
  1269. .map_pages_loop:
  1270.         mov     eax, [page_tabs+ecx*4]
  1271.         and     eax, not 0xFFF
  1272.         or      al, PG_USER
  1273.         xchg    eax, [page_tabs+edx*4]
  1274.         test    al, 1
  1275.         jz      @f
  1276.         call    free_page
  1277. @@:
  1278.         invlpg  [ebx+edi]
  1279.         inc     ecx
  1280.         inc     edx
  1281.         add     edi, 0x1000
  1282.         cmp     edi, [esi+DLLDESCR.size]
  1283.         jb      .map_pages_loop
  1284.  
  1285. ; if real user-mode base is not equal to preferred base, relocate image
  1286.         sub     ebx, [esi+DLLDESCR.defaultbase]
  1287.         jz      @f
  1288.         stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
  1289. @@:
  1290.  
  1291.         mov     eax, [esi+DLLDESCR.exports]
  1292.         sub     eax, [esi+DLLDESCR.defaultbase]
  1293.         add     eax, [img_base]
  1294.         sti
  1295.         ret
  1296. .fail_and_free_data:
  1297.         stdcall kernel_free, [esi+DLLDESCR.data]
  1298. .fail_and_free_dll:
  1299.         mov     eax, esi
  1300.         call    free
  1301. .fail_and_free_coff:
  1302.         stdcall kernel_free, [coff]
  1303. .fail:
  1304.         xor     eax, eax
  1305.         ret
  1306. .fail_and_free_user:
  1307.         stdcall user_free, [img_base]
  1308. .fail_and_dereference:
  1309.         mov     eax, 1  ; delete 1 reference
  1310.         call    dereference_dll
  1311.         sti
  1312.         xor     eax, eax
  1313.         ret
  1314. endp
  1315.  
  1316. ; initialize [APPDATA.dlls_list_ptr] for given thread
  1317. ; DLL is per-process object, so APPDATA.dlls_list_ptr must be
  1318. ; kept in sync for all threads of one process.
  1319. ; out: eax = APPDATA.dlls_list_ptr if all is OK,
  1320. ; NULL if memory allocation failed
  1321. init_dlls_in_thread:
  1322.         mov     ebx, [current_slot]
  1323.         mov     eax, [ebx+APPDATA.dlls_list_ptr]
  1324.         test    eax, eax
  1325.         jnz     .ret
  1326.         push    [ebx+APPDATA.dir_table]
  1327.         mov     eax, 8
  1328.         call    malloc
  1329.         pop     edx
  1330.         test    eax, eax
  1331.         jz      .ret
  1332.         mov     [eax], eax
  1333.         mov     [eax+4], eax
  1334.         mov     ecx, [TASK_COUNT]
  1335.         mov     ebx, SLOT_BASE+256
  1336. .set:
  1337.         cmp     [ebx+APPDATA.dir_table], edx
  1338.         jnz     @f
  1339.         mov     [ebx+APPDATA.dlls_list_ptr], eax
  1340. @@:
  1341.         add     ebx, 256
  1342.         dec     ecx
  1343.         jnz     .set
  1344. .ret:
  1345.         ret
  1346.  
  1347. ; in: eax = number of references to delete, esi -> DLLDESCR struc
  1348. dereference_dll:
  1349.         sub     [esi+DLLDESCR.refcount], eax
  1350.         jnz     .ret
  1351.         mov     eax, [esi+DLLDESCR.fd]
  1352.         mov     edx, [esi+DLLDESCR.bk]
  1353.         mov     [eax+DLLDESCR.bk], edx
  1354.         mov     [edx+DLLDESCR.fd], eax
  1355.         stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
  1356.         stdcall kernel_free, [esi+DLLDESCR.data]
  1357.         mov     eax, esi
  1358.         call    free
  1359. .ret:
  1360.         ret
  1361.  
  1362. destroy_hdll:
  1363.         push    ebx ecx esi edi
  1364.         push    eax
  1365.         mov     ebx, [eax+HDLL.base]
  1366.         mov     esi, [eax+HDLL.parent]
  1367.         mov     edx, [esi+DLLDESCR.size]
  1368. ; The following actions require the context of application where HDLL is mapped.
  1369. ; However, destroy_hdll can be called in the context of OS thread when
  1370. ; cleaning up objects created by the application which is destroyed.
  1371. ; So remember current cr3 and set it to page table of target.
  1372.         mov     eax, [ecx+APPDATA.dir_table]
  1373. ; Because we cheat with cr3, disable interrupts: task switch would restore
  1374. ; page table from APPDATA of current thread.
  1375. ; Also set [current_slot] because it is used by user_free.
  1376.         pushf
  1377.         cli
  1378.         push    [current_slot]
  1379.         mov     [current_slot], ecx
  1380.         mov     ecx, cr3
  1381.         push    ecx
  1382.         mov     cr3, eax
  1383.         push    ebx     ; argument for user_free
  1384.         mov     eax, ebx
  1385.         shr     ebx, 12
  1386.         push    ebx
  1387.         mov     esi, [esi+DLLDESCR.data]
  1388.         shr     esi, 12
  1389. .unmap_loop:
  1390.         push    eax
  1391.         mov     eax, 2
  1392.         xchg    eax, [page_tabs+ebx*4]
  1393.         mov     ecx, [page_tabs+esi*4]
  1394.         and     eax, not 0xFFF
  1395.         and     ecx, not 0xFFF
  1396.         cmp     eax, ecx
  1397.         jz      @f
  1398.         call    free_page
  1399. @@:
  1400.         pop     eax
  1401.         invlpg  [eax]
  1402.         add     eax, 0x1000
  1403.         inc     ebx
  1404.         inc     esi
  1405.         sub     edx, 0x1000
  1406.         ja      .unmap_loop
  1407.         pop     ebx
  1408.         and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
  1409.         call    user_free
  1410. ; Restore context.
  1411.         pop     eax
  1412.         mov     cr3, eax
  1413.         pop     [current_slot]
  1414.         popf
  1415. ; Ok, cheating is done.
  1416.         pop     eax
  1417.         push    eax
  1418.         mov     esi, [eax+HDLL.parent]
  1419.         mov     eax, [eax+HDLL.refcount]
  1420.         call    dereference_dll
  1421.         pop     eax
  1422.         mov     edx, [eax+HDLL.bk]
  1423.         mov     ebx, [eax+HDLL.fd]
  1424.         mov     [ebx+HDLL.bk], edx
  1425.         mov     [edx+HDLL.fd], ebx
  1426.         call    free
  1427.         pop     edi esi ecx ebx
  1428.         ret
  1429.  
  1430. ; ecx -> APPDATA for slot, esi = dlls_list_ptr
  1431. destroy_all_hdlls:
  1432.         test    esi, esi
  1433.         jz      .ret
  1434. .loop:
  1435.         mov     eax, [esi+HDLL.fd]
  1436.         cmp     eax, esi
  1437.         jz      free
  1438.         call    destroy_hdll
  1439.         jmp     .loop
  1440. .ret:
  1441.         ret
  1442.  
  1443. align 4
  1444. stop_all_services:
  1445.         push    ebp
  1446.         mov     edx, [srv.fd]
  1447. .next:
  1448.         cmp     edx, srv.fd-SRV.fd
  1449.         je      .done
  1450.         cmp     [edx+SRV.magic], ' SRV'
  1451.         jne     .next
  1452.         cmp     [edx+SRV.size], sizeof.SRV
  1453.         jne     .next
  1454.  
  1455.         mov     ebx, [edx+SRV.entry]
  1456.         mov     edx, [edx+SRV.fd]
  1457.         test    ebx, ebx
  1458.         jz      .next
  1459.  
  1460.         push    edx
  1461.         mov     ebp, esp
  1462.         push    0
  1463.         push    -1
  1464.         call    ebx
  1465.         mov     esp, ebp
  1466.         pop     edx
  1467.         jmp     .next
  1468. .done:
  1469.         pop     ebp
  1470.         ret
  1471.  
  1472. ; param
  1473. ;  eax= size
  1474. ;  ebx= pid
  1475.  
  1476. align 4
  1477. create_kernel_object:
  1478.  
  1479.         push    ebx
  1480.         call    malloc
  1481.         pop     ebx
  1482.         test    eax, eax
  1483.         jz      .fail
  1484.  
  1485.         mov     ecx, [current_slot]
  1486.         add     ecx, APP_OBJ_OFFSET
  1487.  
  1488.         pushfd
  1489.         cli
  1490.         mov     edx, [ecx+APPOBJ.fd]
  1491.         mov     [eax+APPOBJ.fd], edx
  1492.         mov     [eax+APPOBJ.bk], ecx
  1493.         mov     [eax+APPOBJ.pid], ebx
  1494.  
  1495.         mov     [ecx+APPOBJ.fd], eax
  1496.         mov     [edx+APPOBJ.bk], eax
  1497.         popfd
  1498. .fail:
  1499.         ret
  1500.  
  1501. ; param
  1502. ;  eax= object
  1503.  
  1504. align 4
  1505. destroy_kernel_object:
  1506.  
  1507.         pushfd
  1508.         cli
  1509.         mov     ebx, [eax+APPOBJ.fd]
  1510.         mov     ecx, [eax+APPOBJ.bk]
  1511.         mov     [ebx+APPOBJ.bk], ecx
  1512.         mov     [ecx+APPOBJ.fd], ebx
  1513.         popfd
  1514.  
  1515.         xor     edx, edx       ;clear common header
  1516.         mov     [eax], edx
  1517.         mov     [eax+4], edx
  1518.         mov     [eax+8], edx
  1519.         mov     [eax+12], edx
  1520.         mov     [eax+16], edx
  1521.  
  1522.         call    free           ;release object memory
  1523.         ret
  1524.