kolibrios/kernel/branches/kolibrios-pe-clevermouse/core/dll.inc
Magomed Kostoev (mkostoevr) eccd8f2198 [CLEVERMOUSE_PE_KERNEL] Apply CleverMouse PE patch
git-svn-id: svn://kolibrios.org@9048 a494cfbc-eb01-0410-851d-a64ba20cac60
2021-07-09 19:26:55 +00:00

1217 lines
27 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
DRV_COMPAT = 5 ;minimal required drivers version
DRV_CURRENT = 6 ;current drivers model version
DRV_VERSION = (DRV_COMPAT shl 16) or DRV_CURRENT
PID_KERNEL = 1 ;os_idle thread
align 4
proc get_notify stdcall, p_ev:dword
.wait:
mov ebx, [current_slot]
test dword [ebx+APPDATA.event_mask], EVENT_NOTIFY
jz @f
and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
mov edi, [p_ev]
mov dword [edi], EV_INTR
mov eax, [ebx+APPDATA.event]
mov dword [edi+4], eax
ret
@@:
call change_task
jmp .wait
endp
align 4
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 6
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 5
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 4
mov bh, byte [devfn]
mov bl, byte [reg]
call pci_read_reg
pop ebx
ret
endp
align 4
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 8
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
align 4
proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 9
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
align 4
proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
push ebx
xor eax, eax
xor ebx, ebx
mov ah, byte [bus]
mov al, 10
mov bh, byte [devfn]
mov bl, byte [reg]
mov ecx, [val]
call pci_write_reg
pop ebx
ret
endp
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
align 4
proc srv_handler stdcall, ioctl:dword
mov esi, [ioctl]
test esi, esi
jz .err
mov edi, [esi+handle]
cmp [edi+SRV.magic], ' SRV'
jne .fail
cmp [edi+SRV.size], sizeof.SRV
jne .fail
; stdcall [edi+SRV.srv_proc], esi
mov eax, [edi+SRV.srv_proc]
test eax, eax
jz .fail
stdcall eax, esi
ret
.fail:
xor eax, eax
not eax
mov [esi+output], eax
mov [esi+out_size], 4
ret
.err:
xor eax, eax
not eax
ret
endp
; param
; ecx= io_control
;
; retval
; eax= error code
align 4
srv_handlerEx:
cmp ecx, OS_BASE
jae .fail
mov eax, [ecx+handle]
cmp [eax+SRV.magic], ' SRV'
jne .fail
cmp [eax+SRV.size], sizeof.SRV
jne .fail
; stdcall [eax+SRV.srv_proc], ecx
mov eax, [eax+SRV.srv_proc]
test eax, eax
jz .fail
stdcall eax, ecx
ret
.fail:
or eax, -1
ret
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
align 4
proc get_service stdcall, sz_name:dword
mov eax, [sz_name]
test eax, eax
jnz @F
ret
@@:
mov edx, [srv.fd]
@@:
cmp edx, srv.fd-SRV.fd
je .not_load
stdcall strncmp, edx, [sz_name], 16
test eax, eax
mov eax, edx
je .nothing
mov edx, [edx+SRV.fd]
jmp @B
.not_load:
mov eax, [sz_name]
push edi
sub esp, 36
mov edi, esp
mov dword [edi], '/sys'
mov dword [edi+4], '/dri'
mov dword [edi+8], 'vers'
mov byte [edi+12], '/'
@@:
mov dl, [eax]
mov [edi+13], dl
inc eax
inc edi
test dl, dl
jnz @b
mov dword [edi+12], '.sys'
mov byte [edi+16], 0
mov edi, esp
stdcall load_pe_driver, edi, 0
add esp, 36
pop edi
.nothing:
ret
endp
reg_service:
xor eax, eax
mov ecx, [esp+8]
jecxz .nothing
push sizeof.SRV
push ecx
pushd [esp+12]
call reg_service_ex
.nothing:
ret 8
reg_usb_driver:
push sizeof.USBSRV
pushd [esp+12]
pushd [esp+12]
call reg_service_ex
test eax, eax
jz .nothing
mov ecx, [esp+12]
mov [eax+USBSRV.usb_func], ecx
.nothing:
ret 12
proc reg_service_ex stdcall, name:dword, handler:dword, srvsize:dword
push ebx
xor eax, eax
cmp [name], eax
je .fail
; cmp [handler], eax
; je .fail
mov eax, [srvsize]
call malloc
test eax, eax
jz .fail
push esi
push edi
mov edi, eax
mov esi, [name]
movsd
movsd
movsd
movsd
pop edi
pop esi
mov [eax+SRV.magic], ' SRV'
mov [eax+SRV.size], sizeof.SRV
mov ebx, srv.fd-SRV.fd
mov edx, [ebx+SRV.fd]
mov [eax+SRV.fd], edx
mov [eax+SRV.bk], ebx
mov [ebx+SRV.fd], eax
mov [edx+SRV.bk], eax
mov ecx, [handler]
mov [eax+SRV.srv_proc], ecx
pop ebx
ret
.fail:
xor eax, eax
pop ebx
ret
endp
align 4
proc get_proc stdcall, exp:dword, sz_name:dword
mov edx, [exp]
.next:
mov eax, [edx]
test eax, eax
jz .end
push edx
stdcall strncmp, eax, [sz_name], 16
pop edx
test eax, eax
jz .ok
add edx, 8
jmp .next
.ok:
mov eax, [edx+4]
.end:
ret
endp
align 4
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
@@:
stdcall strncmp, [pSym], [sz_sym], 8
test eax, eax
jz .ok
add [pSym], 18
dec [count]
jnz @b
xor eax, eax
ret
.ok:
mov eax, [pSym]
mov eax, [eax+8]
ret
endp
align 4
proc get_curr_task
mov eax, [current_slot_idx]
shl eax, 8
ret
endp
align 4
proc get_fileinfo stdcall, file_name:dword, info:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
xor eax, eax
mov ebx, [file_name]
mov ecx, [info]
mov [cmd], 5
mov [offset], eax
mov [offset+4], eax
mov [count], eax
mov [buff], ecx
mov byte [buff+4], al
mov [name], ebx
mov eax, 70
lea ebx, [cmd]
pushad
cld
call protect_from_terminate
call file_system_lfn
call unprotect_from_terminate
popad
ret
endp
align 4
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
bytes:dword
locals
cmd dd ?
offset dd ?
dd ?
count dd ?
buff dd ?
db ?
name dd ?
endl
xor eax, eax
mov ebx, [file_name]
mov ecx, [off]
mov edx, [bytes]
mov esi, [buffer]
mov [cmd], eax
mov [offset], ecx
mov [offset+4], eax
mov [count], edx
mov [buff], esi
mov byte [buff+4], al
mov [name], ebx
pushad
lea ebx, [cmd]
call file_system_lfn_protected
popad
ret
endp
align 4
; @brief Allocate kernel memory and loads the specified file
;
; @param file_name Path to file
;
; @returns File image in kernel memory in `eax` and size of file in `ebx`
;
; @warning You must call kernel_free() to delete each file loaded by the
; load_file() function
proc load_file stdcall, file_name:dword
locals
attr dd ?
flags dd ?
cr_time dd ?
cr_date dd ?
acc_time dd ?
acc_date dd ?
mod_time dd ?
mod_date dd ?
file_size dd ?
file dd ?
file2 dd ?
endl
push esi
push edi
lea eax, [attr]
stdcall get_fileinfo, [file_name], eax
test eax, eax
jnz .fail
mov eax, [file_size]
cmp eax, 1024*1024*16
ja .fail
stdcall kernel_alloc, [file_size]
mov [file], eax
test eax, eax
jz .fail
stdcall read_file, [file_name], eax, dword 0, [file_size]
cmp ebx, [file_size]
jne .cleanup
mov eax, [file]
cmp dword [eax], 'KPCK'
jne .exit
mov ebx, [eax+4]
mov [file_size], ebx
stdcall kernel_alloc, ebx
test eax, eax
jz .cleanup
mov [file2], eax
pushad
mov ecx, unpack_mutex
call mutex_lock
popad
stdcall unpack, [file], eax
pushad
mov ecx, unpack_mutex
call mutex_unlock
popad
stdcall kernel_free, [file]
mov eax, [file2]
mov ebx, [file_size]
.exit:
push eax
lea edi, [eax+ebx] ;cleanup remain space
mov ecx, 4096 ;from file end
and ebx, 4095
jz @f
sub ecx, ebx
xor eax, eax
cld
rep stosb
@@:
mov ebx, [file_size]
pop eax
pop edi
pop esi
ret
.cleanup:
stdcall kernel_free, [file]
.fail:
xor eax, eax
xor ebx, ebx
pop edi
pop esi
ret
endp
; description
; allocate user memory and loads the specified file
;
; param
; file_name= path to file
;
; retval
; eax= file image in user memory
; ebx= size of file
;
; warging
; You mast call kernel_free() to delete each file
; loaded by the load_file() function
align 4
proc load_file_umode stdcall, file_name:dword
locals
attr dd ?
flags dd ?
cr_time dd ?
cr_date dd ?
acc_time dd ?
acc_date dd ?
mod_time dd ?
mod_date dd ?
file_size dd ?
km_file dd ?
um_file dd ?
endl
push esi
push edi
push ebx
lea eax, [attr]
stdcall get_fileinfo, [file_name], eax ;find file and get info
test eax, eax
jnz .err_1
mov eax, [file_size]
cmp eax, 1024*1024*16 ;to be enough for anybody (c)
ja .err_1
;it is very likely that the file is packed
stdcall kernel_alloc, [file_size] ;with kpack, so allocate memory from kernel heap
mov [km_file], eax
test eax, eax
jz .err_1
stdcall read_file, [file_name], eax, dword 0, [file_size]
cmp ebx, [file_size]
jne .err_2
mov eax, [km_file]
cmp dword [eax], 'KPCK' ; check kpack signature
jne .raw_file
mov ebx, [eax+4] ;get real size of file
mov [file_size], ebx
stdcall user_alloc, ebx ;and allocate space from user heap
mov [um_file], eax
test eax, eax
jz .err_2
mov edx, [file_size] ;preallocate page memory
shr eax, 10
lea edi, [page_tabs+eax]
add edx, 4095
shr edx, 12
@@:
call alloc_page
test eax, eax
jz .err_3
or eax, PG_UWR
stosd
dec edx
jnz @B
pushad
mov ecx, unpack_mutex
call mutex_lock
stdcall unpack, [km_file], [um_file]
mov ecx, unpack_mutex
call mutex_unlock
popad
stdcall kernel_free, [km_file] ;we don't need packed file anymore
.exit:
mov edi, [um_file]
mov esi, [um_file]
mov eax, [file_size]
mov edx, eax
add edi, eax ;cleanup remain space
mov ecx, 4096 ;from file end
and eax, 4095
jz @f
sub ecx, eax
xor eax, eax
cld
rep stosb
@@:
mov eax, [um_file]
pop ebx
pop edi
pop esi
ret
.raw_file: ; sometimes we load unpacked file
stdcall user_alloc, ebx ; allocate space from user heap
mov [um_file], eax
test eax, eax
jz .err_2
shr eax, 10 ; and remap pages.
mov ecx, [file_size]
add ecx, 4095
shr ecx, 12
mov esi, [km_file]
shr esi, 10
add esi, page_tabs
lea edi, [page_tabs+eax]
cld
@@:
lodsd
and eax, 0xFFFFF000
or eax, PG_UWR
stosd
loop @B
stdcall free_kernel_space, [km_file] ; release allocated kernel space
jmp .exit ; physical pages still in use
.err_3:
stdcall user_free, [um_file]
.err_2:
stdcall kernel_free, [km_file]
.err_1:
xor eax, eax
xor edx, edx
pop ebx
pop edi
pop esi
ret
endp
uglobal
align 4
unpack_mutex MUTEX
endg
align 4
proc get_proc_ex stdcall uses ebx esi, proc_name:dword, imports:dword
mov ebx, [imports]
test ebx, ebx
jz .end
xor esi, esi
.look_up:
mov eax, [ebx+32]
mov eax, [OS_BASE+eax+esi*4]
add eax, OS_BASE
stdcall strncmp, eax, [proc_name], 256
test eax, eax
jz .ok
inc esi
cmp esi, [ebx+24]
jb .look_up
.end:
xor eax, eax
ret
.ok:
mov eax, [ebx+28]
mov eax, [OS_BASE+eax+esi*4]
add eax, OS_BASE
ret
endp
align 4
proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
sym_count:dword, strings:dword, imports:dword
locals
retval dd ?
endl
mov edi, [symbols]
mov [retval], 1
.fix:
movzx ebx, [edi+COFF_SYM.SectionNumber]
test ebx, ebx
jnz .internal
mov eax, dword [edi+COFF_SYM.Name]
test eax, eax
jnz @F
mov edi, [edi+4]
add edi, [strings]
@@:
push edi
stdcall get_proc_ex, edi, [imports]
pop edi
xor ebx, ebx
test eax, eax
jnz @F
; disable debug msg
;mov esi, msg_unresolved
;call sys_msg_board_str
;mov esi, edi
;call sys_msg_board_str
;mov esi, msg_CR
;call sys_msg_board_str
mov [retval], 0
@@:
mov edi, [symbols]
mov [edi+COFF_SYM.Value], eax
jmp .next
.internal:
cmp bx, -1
je .next
cmp bx, -2
je .next
dec ebx
shl ebx, 3
lea ebx, [ebx+ebx*4]
add ebx, [sec]
mov eax, [ebx+COFF_SECTION.VirtualAddress]
add [edi+COFF_SYM.Value], eax
.next:
add edi, sizeof.COFF_SYM
mov [symbols], edi
dec [sym_count]
jnz .fix
mov eax, [retval]
ret
endp
align 4
proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals
n_sec dd ?
endl
mov eax, [coff]
movzx ebx, [eax+COFF_HEADER.nSections]
mov [n_sec], ebx
lea esi, [eax+20]
.fix_sec:
mov edi, [esi+COFF_SECTION.PtrReloc]
add edi, [coff]
movzx ecx, [esi+COFF_SECTION.NumReloc]
test ecx, ecx
jz .next
.reloc_loop:
mov ebx, [edi+COFF_RELOC.SymIndex]
add ebx, ebx
lea ebx, [ebx+ebx*8]
add ebx, [sym]
mov edx, [ebx+COFF_SYM.Value]
cmp [edi+COFF_RELOC.Type], 6
je .dir_32
cmp [edi+COFF_RELOC.Type], 20
jne .next_reloc
.rel_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
sub edx, eax
sub edx, 4
jmp .fix
.dir_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
.fix:
add eax, [delta]
add [eax], edx
.next_reloc:
add edi, 10
dec ecx
jnz .reloc_loop
.next:
add esi, sizeof.COFF_SECTION
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
align 4
proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
delta:dword
locals
n_sec dd ?
endl
mov eax, [coff]
movzx ebx, [eax+COFF_HEADER.nSections]
mov [n_sec], ebx
lea esi, [eax+20]
mov edx, [delta]
.fix_sec:
mov edi, [esi+COFF_SECTION.PtrReloc]
add edi, [coff]
movzx ecx, [esi+COFF_SECTION.NumReloc]
test ecx, ecx
jz .next
.reloc_loop:
cmp [edi+COFF_RELOC.Type], 6
jne .next_reloc
.dir_32:
mov eax, [edi+COFF_RELOC.VirtualAddress]
add eax, [esi+COFF_SECTION.VirtualAddress]
add [eax+edx], edx
.next_reloc:
add edi, 10
dec ecx
jnz .reloc_loop
.next:
add esi, sizeof.COFF_SECTION
dec [n_sec]
jnz .fix_sec
.exit:
ret
endp
; in: edx -> COFF_SECTION struct
; out: eax = alignment as mask for bits to drop
coff_get_align:
; Rules:
; - if alignment is not given, use default = 4K;
; - if alignment is given and is no more than 4K, use it;
; - if alignment is more than 4K, revert to 4K.
push ecx
mov cl, byte [edx+COFF_SECTION.Characteristics+2]
mov eax, 1
shr cl, 4
dec cl
js .default
cmp cl, 12
jbe @f
.default:
mov cl, 12
@@:
shl eax, cl
pop ecx
dec eax
ret
align 4
proc load_library stdcall, file_name:dword, encoding:dword
locals
fullname dd ?
filesize dd ?
coff dd ?
img_base dd ?
img_size dd ?
symbols_ptr dd ?
symbols_lim dd ?
exports dd ?
endl
; resolve file name
stdcall kernel_alloc, maxPathLength
mov [fullname], eax
mov edi, eax
mov esi, [file_name]
mov eax, [encoding]
push ebp
call getFullPath
pop ebp
test eax, eax
jz .fail
; load file
stdcall load_file, [fullname]
test eax, eax
jz .fail
mov [coff], eax
mov [filesize], ebx
; calculate size of loaded DLL
movzx ecx, [eax+COFF_HEADER.nSections]
xor ebx, ebx
lea edx, [eax+20]
@@:
call coff_get_align
add ebx, eax
not eax
and ebx, eax
add ebx, [edx+COFF_SECTION.SizeOfRawData]
add edx, sizeof.COFF_SECTION
dec ecx
jnz @B
; it must be nonzero and not too big
mov [img_size], ebx
test ebx, ebx
jz .fail_and_free_coff
cmp ebx, 0x10000000
ja .fail_and_free_coff
; allocate memory
call init_heap
stdcall user_alloc, [img_size]
test eax, eax
jz .fail_and_free_coff
mov [img_base], eax
; copy sections and set correct values for VirtualAddress'es in headers
mov edx, [coff]
movzx ebx, [edx+COFF_HEADER.nSections]
mov edi, eax
add edx, 20
cld
@@:
call coff_get_align
add edi, eax
not eax
and edi, eax
mov [edx+COFF_SECTION.VirtualAddress], edi
mov esi, [edx+COFF_SECTION.PtrRawData]
mov ecx, [edx+COFF_SECTION.SizeOfRawData]
test esi, esi
jnz .copy
xor eax, eax
rep stosb
jmp .next
.copy:
add esi, [coff]
rep movsb
.next:
add edx, sizeof.COFF_SECTION
dec ebx
jnz @B
mov edx, [coff]
mov ebx, [edx+COFF_HEADER.pSymTable]
mov edi, [filesize]
sub edi, ebx
jc .fail_and_free_data
mov [symbols_lim], edi
add ebx, edx
; coff_hdr = coff
; symbols_num = coff.nSymbols
mov [symbols_ptr], ebx
mov ebx, edx
; fixup symbols
mov eax, [edx+COFF_HEADER.nSymbols]
add edx, 20
lea ecx, [eax*9]
add ecx, ecx
add ecx, [symbols_ptr]
stdcall fix_coff_symbols, edx, [symbols_ptr], eax, \
ecx, 0
; test eax, eax
; jnz @F
;
;@@:
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], szEXPORTS
test eax, eax
jnz @F
stdcall get_coff_sym, [symbols_ptr], [ebx+COFF_HEADER.nSymbols], sz_EXPORTS
@@:
mov [exports], eax
stdcall fix_coff_relocs, ebx, [symbols_ptr], 0
stdcall kernel_free, [coff]
stdcall kernel_free, [fullname]
mov eax, [exports]
ret
.fail_and_free_data:
stdcall user_free, [img_base]
.fail_and_free_coff:
stdcall kernel_free, [coff]
.fail:
stdcall kernel_free, [fullname]
xor eax, eax
ret
endp
; in: esi -> PEDESCR struct
proc dereference_pe
mov ecx, pe_list_mutex
call mutex_lock
dec [esi+PEDESCR.refcount]
jnz mutex_unlock
mov eax, [esi+PEDESCR.fd]
mov edx, [esi+PEDESCR.bk]
mov [eax+PEDESCR.bk], edx
mov [edx+PEDESCR.fd], eax
call mutex_unlock
mov eax, esi
call free
ret
endp
align 4
stop_all_services:
push ebp
mov edx, [srv.fd]
.next:
cmp edx, srv.fd-SRV.fd
je .done
cmp [edx+SRV.magic], ' SRV'
jne .next
cmp [edx+SRV.size], sizeof.SRV
jne .next
mov ebx, [edx+SRV.entry]
mov edx, [edx+SRV.fd]
test ebx, ebx
jz .next
push edx
mov ebp, esp
push 0
push -1
call ebx
mov esp, ebp
pop edx
jmp .next
.done:
pop ebp
ret
; param
; eax= size
; ebx= pid
align 4
create_kernel_object:
push ebx
call malloc
pop ebx
test eax, eax
jz .fail
mov ecx, [current_slot]
add ecx, APP_OBJ_OFFSET
pushfd
cli
mov edx, [ecx+APPOBJ.fd]
mov [eax+APPOBJ.fd], edx
mov [eax+APPOBJ.bk], ecx
mov [eax+APPOBJ.pid], ebx
mov [ecx+APPOBJ.fd], eax
mov [edx+APPOBJ.bk], eax
popfd
.fail:
ret
; param
; eax= object
align 4
destroy_kernel_object:
pushfd
cli
mov ebx, [eax+APPOBJ.fd]
mov ecx, [eax+APPOBJ.bk]
mov [ebx+APPOBJ.bk], ecx
mov [ecx+APPOBJ.fd], ebx
popfd
xor edx, edx ;clear common header
mov [eax], edx
mov [eax+4], edx
mov [eax+8], edx
mov [eax+12], edx
mov [eax+16], edx
call free ;release object memory
ret
;void* __fastcall create_object(size_t size)
; param
; ecx= size
align 4
create_object:
push esi
push edi
pushfd
cli
mov esi, [current_process]
mov eax, [esi+PROC.ht_free]
mov edi, [esi+PROC.ht_next]
dec eax
js .err0
mov [esi+PROC.ht_free], eax
mov eax, [esi+PROC.htab+edi*4]
mov [esi+PROC.ht_next], eax
popfd
mov eax, ecx
call malloc
test eax, eax
jz .err1
mov [eax+FUTEX.handle], edi
mov [esi+PROC.htab+edi*4], eax
pop edi
pop esi
ret
.err1:
pushfd
cli
mov eax, [esi+PROC.ht_next]
mov [esi+PROC.htab+edi*4], eax
mov [esi+PROC.ht_next], edi
inc [esi+PROC.ht_free]
.err0:
popfd
pop edi
pop esi
xor eax, eax
ret
;int __fastcall destroy_object(struct object *obj)
align 4
destroy_object:
push esi
mov esi, [current_process]
mov edx, [ecx+FUTEX.handle]
pushfd
cli
mov eax, [esi+PROC.ht_next]
mov [esi+PROC.htab+edx*4], eax
mov [esi+PROC.ht_next], edx
inc [esi+PROC.ht_free]
popfd
pop esi
mov eax, ecx
call free
xor eax, eax
ret
.fail:
popfd
pop esi
mov eax, -1
ret