Subversion Repositories Kolibri OS

Rev

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

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