Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 2291 → Rev 2292

/programs/emulator/KlbrInWin/I40EMUL.INC
0,0 → 1,7834
; Cb-n#%li.-# @l$i Lkbnbe
convert_color:
bswap eax
shr eax, 8
ret
 
draw_window_base:
mov al, byte [ebp+tls.color_main+3]
and eax, 0xF
dec eax
js .type1
jz .nodraw
dec eax
jz .type2
; window with skin
push 1
call draw_border
call draw_caption_skinned
movzx eax, [ebp+tls.y_size]
cmp eax, 21+5
jle @f
test byte [ebp+tls.color_main+3], 40h
jnz @f
push 1
push [ebp+tls.color_main]
movzx ecx, [ebp+tls.y_size]
sub ecx, 5
push ecx
movzx ecx, [ebp+tls.x_size]
sub ecx, 5
push ecx
push [_skinh]
push 5
call rectangle_gradient
@@:
; close button
mov edx, 40000001h ; id=1, no draw
xor ebx, ebx
cmp [skin_btn_close.left], ebx
jge @f
mov ebx, dword [ebp+tls.x_size]
@@:
add ebx, [skin_btn_close.left]
shl ebx, 16
mov bx, word [skin_btn_close.width]
dec ebx
mov ecx, [skin_btn_close.top]
shl ecx, 16
mov cx, word [skin_btn_close.height]
dec ecx
call add_button
; minimize button
mov edx, 4000FFFFh ; id=65535, no draw
xor ebx, ebx
cmp [skin_btn_minimize.left], ebx
jge @f
mov ebx, dword [ebp+tls.x_size]
@@:
add ebx, [skin_btn_minimize.left]
shl ebx, 16
mov bx, word [skin_btn_minimize.width]
dec ebx
mov ecx, [skin_btn_minimize.top]
shl ecx, 16
mov cx, word [skin_btn_minimize.height]
dec ecx
call add_button
jmp .nodraw
.type1:
; border
mov eax, [ebp+tls.color_border]
call create_select_pen
push eax
xor esi, esi
call rect_wnd
call select_delete
; caption
call draw_caption_type1
; work area
test byte [ebp+tls.color_main+3], 40h
jnz .nodraw
push 1
push [ebp+tls.color_main]
movzx eax, [ebp+tls.y_size]
dec eax
push eax
movzx eax, [ebp+tls.x_size]
dec eax
push eax
push 21
push 1
call rectangle_gradient
jmp .nodraw
.type2:
; border
push eax
call draw_border
; caption
call draw_caption_type2
; work area
test byte [ebp+tls.color_main+3], 40h
jnz .nodraw
push 1
push [ebp+tls.color_main]
movzx eax, [ebp+tls.y_size]
sub eax, 5
push eax
movzx eax, [ebp+tls.x_size]
sub eax, 5
push eax
push 20
push 5
call rectangle_gradient
.nodraw:
; caption string
call draw_caption_string
; draw buttons
pushad
mov esi, [ebp+tls.buttons]
@@:
test esi, esi
jz @f
push [esi+button_desc.next]
mov ebx, dword [esi+button_desc.xsize]
mov ecx, dword [esi+button_desc.ysize]
test byte [esi+button_desc.id+3], 0x40
mov esi, [esi+button_desc.color]
jnz .sk
call draw_button
.sk:
pop esi
jmp @b
@@:
popad
ret
 
draw_caption_type1:
push 040404h
push [ebp+tls.color_capt]
movzx eax, [ebp+tls.y_size]
dec eax
cmp eax, 21
jb @f
mov eax, 21
@@:
push eax
movzx eax, [ebp+tls.x_size]
dec eax
push eax
push 1
push 1
call rectangle_gradient
ret
 
draw_caption_type2:
mov eax, [ebp+tls.color_capt]
mov ecx, 0x040404
test eax, 0x40000000
jz @f
or ecx, 0x80000000
xor eax, 0xC0000000
@@:
push ecx
push eax
movzx eax, [ebp+tls.y_size]
sub eax, 4
cmp eax, 20
jb @f
mov eax, 20
@@: push eax
movzx eax, [ebp+tls.x_size]
sub eax, 4
push eax
push 4
push 4
call rectangle_gradient
ret
 
draw_caption_skinned:
xor ebx, ebx
mov eax, [left_bmp]
cmp [ebp+tls.bActive], bl
jnz @f
mov eax, [left1_bmp]
@@:
xor ecx, ecx
call putbmp
movzx esi, [ebp+tls.x_size]
mov ecx, [eax+4]
sub esi, ecx
mov eax, [oper_bmp]
cmp [ebp+tls.bActive], bl
jnz @f
mov eax, [oper1_bmp]
@@:
sub esi, [eax+4]
mov eax, [base_bmp]
cmp [ebp+tls.bActive], bl
jnz @f
mov eax, [base1_bmp]
@@:
cmp esi, [eax+4]
jle .nobase
@@:
call putbmp
add ecx, [eax+4]
sub esi, [eax+4]
jg @b
.nobase:
movzx ecx, [ebp+tls.x_size]
mov eax, [oper_bmp]
cmp [ebp+tls.bActive], bl
jnz @f
mov eax, [oper1_bmp]
@@:
sub ecx, [eax+4]
 
putbmp:
; in: eax=bmpinfo,ecx=y*65536+x,edi=hDC
push eax ecx
lea edx, [eax+40]
push ebx ; fuColorUse = DIB_RGB_COLORS
push eax ; lpbmi
push edx ; lpBits
push dword [eax+8] ; cScanLines
push ebx ; uStartScan
push ebx ; YSrc
push ebx ; XSrc
push dword [eax+8] ; dwHeight
push dword [eax+4] ; dwWidth
movzx eax, cx
shr ecx, 10h
push ecx ; YDest
push eax ; XDest
push edi ; hDC
call [SetDIBitsToDevice]
pop ecx eax
ret
 
draw_caption_string:
test byte [ebp+tls.color_main+3], 0x10
jnz @f
.ret:
.nodraw:
ret
@@:
mov esi, [ebp+tls.caption]
test esi, esi
jz .ret
add esi, [base]
mov al, byte [ebp+tls.color_main+3]
and eax, 0xF
dec eax
js .type1
jz .nodraw
dec eax
jz .type2
; caption for skinned windows
; determine maximum caption length
mov ax, [ebp+tls.x_size]
sub ax, [margins+2]
sub ax, [margins]
js .ret
cwd
push 6
pop ebx
div bx
mov ecx, eax
; determine coordinates
mov ebx, dword [margins]
mov bx, word [_skinh]
sub bx, [margins+6]
sub bx, [margins+4]
sar bx, 1
adc bx, 0
add bx, [margins+6]
add bx, -3
.common:
mov edx, esi
@@:
lodsb
test al, al
loopnz @b
jnz @f
dec esi
@@: sub esi, edx
mov ecx, dword [common_colors+16]
jmp i40_writetext_l2
.type1:
.type2:
; caption for windows without skin
movzx eax, [ebp+tls.x_size]
sub eax, 16
js .ret
cdq
push 6
pop ebx
div ebx
mov ecx, eax
mov ebx, 0x00080007
jmp .common
 
i40_draw_window:
mov [ebp+tls.color_main], edx
mov [ebp+tls.color_capt], esi
mov [ebp+tls.color_border], edi
mov [ebp+tls.curdraw], 0
cmp [ebp+tls.showwnd], 0
jnz .wasshown
; real size is 1 pixel more
inc ebx
mov dword [ebp+tls.x_size], ebx
inc ecx
mov dword [ebp+tls.y_size], ecx
test edx, 0x10000000
jz @f
mov [ebp+tls.caption], edi
@@:
push 0
movzx eax, cx
push eax
movzx eax, bx
push eax
shr ecx, 10h
push ecx
shr ebx, 10h
push ebx
push [ebp+tls.hWnd]
call [MoveWindow]
push 5 ; SW_SHOW
push [ebp+tls.hWnd]
call [ShowWindow]
mov [ebp+tls.showwnd], 1
cmp [ebp+tls.lpShapeData], 0
jz @f
call set_window_shape
@@:
.wasshown:
; define client box
test byte [ebp+tls.color_main+3], 0x20
jnz .client_relative
and [ebp+tls.client_left], 0
and [ebp+tls.client_top], 0
movzx eax, [ebp+tls.x_size]
mov [ebp+tls.client_width], eax
movzx eax, [ebp+tls.y_size]
mov [ebp+tls.client_height], eax
jmp .client_set
.client_relative:
mov eax, [_skinh]
mov [window_topleft+8*3+4], eax
mov [window_topleft+8*4+4], eax
mov al, byte [ebp+tls.color_main+3]
and eax, 0xF
mov edx, [eax*8+window_topleft]
mov [ebp+tls.client_left], edx
neg edx
movzx ecx, [ebp+tls.x_size]
lea ecx, [ecx+edx*2]
mov [ebp+tls.client_width], ecx
mov eax, [eax*8+window_topleft+4]
mov [ebp+tls.client_top], eax
movzx ecx, [ebp+tls.y_size]
sub ecx, eax
add ecx, edx
mov [ebp+tls.client_height], ecx
.client_set:
push 0
push [ebp+tls.hWnd]
call [ValidateRect]
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
call draw_window_base
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
ret
 
i40_put_pixel:
test edx, 1000000h
jnz .negate
mov eax, edx
call convert_color
push eax
add ebx, [ebp+tls.client_left]
add ecx, [ebp+tls.client_top]
push ecx
push ebx
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
.1:
push edi
call [SetPixel]
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
ret
.negate:
push ecx
push ecx
push ebx
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
push edi
call [GetPixel]
pop ecx
not eax
push eax
push ecx
push ebx
jmp .1
 
i40_getkey:
movzx ecx, [ebp+tls.keybuflen]
jecxz .empty
lea esi, [ebp+tls.keybuffer]
mov edi, esi
lodsb
shl eax, 8
mov [esp+20h], ax
dec ecx
mov [ebp+tls.keybuflen], cl
rep movsb
ret
.empty:
mov byte [esp+20h], 1
ret
 
i40_get_sys_time:
sub esp, 10h
push esp
call [GetLocalTime]
movzx eax, word [esp+12]
aam
shl ax, 4
shr ah, 4
shl eax, 16-4
mov ax, [esp+10]
aam
shl ax, 4
shr ah, 4
shr ax, 4
mov bl, al
mov ax, [esp+8]
aam
shl ax, 4
shr ah, 4
shr ax, 4
mov ah, bl
add esp, 10h
mov [esp+20h], eax
ret
 
i40_writetext:
add edx, [base]
i40_writetext_l1:
add bx, word [ebp+tls.client_top]
ror ebx, 16
add bx, word [ebp+tls.client_left]
ror ebx, 16
i40_writetext_l2:
push edi
push ecx
push edx
push [ebp+tls.hWnd]
call [GetDC]
mov ecx, esi
pop esi
pop edi
push eax
; ecx=length, esi=pointer, ebx=x*65536+y, edi=font&color
.loop:
xor eax, eax
lodsb
test edi, edi
js .test_asciiz
dec ecx
js .done
jmp @f
.test_asciiz:
test eax, eax
jz .done
@@:
push esi
push ecx
mov esi, [char_mt]
lea esi, [esi + eax*8]
add esi, eax
mov ecx, 6
test edi, 10000000h
jz @f
sub esi, [char_mt]
add esi, [char2_mt]
add esi, eax
lodsb
mov ecx, eax
@@:
mov edx, 9
.intloop:
lodsb
push ebx
push ecx
.intintloop:
shr al, 1
pushad
jnc .nopix
mov eax, edi
@@:
call convert_color
push eax
movzx eax, bx
push eax
shr ebx, 16
push ebx
push dword [esp+3Ch] ; hDC
call [SetPixel]
jmp @f
.nopix:
mov eax, [esp+34h]
test edi, 0x40000000
jnz @b
@@:
popad
add ebx, 10000h
loop .intintloop
pop ecx
pop ebx
inc ebx
dec edx
jnz .intloop
sub ebx, 9
shl ecx, 16
add ebx, ecx
pop ecx
pop esi
jmp .loop
.done:
push [ebp+tls.hWnd]
call [ReleaseDC]
pop edi
ret
 
i40_delay:
imul ebx, ebx, 10
push ebx
call [Sleep]
ret
 
ramdisk2win32:
push edi
add ebx, [base]
mov esi, ramdisk_path
push esi
call [lstrlenA]
xchg eax, ecx
rep movsb
push edi
push edi
mov ecx, 8
@@:
mov al, [ebx]
inc ebx
cmp al, '.'
jz @f
stosb
loop @b
@@:
dec edi
cmp byte [edi], ' '
jz @b
inc edi
mov al, '.'
stosb
cmp [ebx], al
jnz @f
inc ebx
@@:
mov ecx, 3
@@:
mov al, [ebx]
inc ebx
stosb
loop @b
@@:
dec edi
cmp byte [edi], ' '
jz @b
inc edi
xor eax, eax
stosb
call [OemToCharA]
xor eax, eax
pop edi
ret
 
i40_read_floppy_file:
sub esp, 512
mov edi, esp
push esi
call ramdisk2win32
pop ebx
push eax
push eax
push 3
push eax
push 1
push 80000000h
push edi
call [CreateFileA]
add esp, 512
inc eax
jz .err_ret
dec eax
xchg eax, esi
push 0
push esi
call [GetFileSize]
xchg eax, edi
push eax
mov ecx, esp
push 0
push ecx
push edi
add ebx, [base]
push ebx
push esi
call [ReadFile]
pop eax
push esi
call [CloseHandle]
mov [esp+20h], edi
ret
.err_ret:
or dword [esp+20h], -1
ret
 
pad_bmp:
pushad
movzx eax, cx
shr ecx, 10h
lea ecx, [ecx+ecx*2]
add ecx, 3
and ecx, not 3
mul ecx
push eax
call malloc
mov [esp+1Ch], eax
popad
push eax
mov edi, eax
push ecx
mov esi, ebx
.extloop:
push ecx
shr ecx, 10h
lea ecx, [ecx+ecx*2]
mov eax, ecx
shr ecx, 2
rep movsd
mov ecx, eax
and ecx, 3
rep movsb
mov al, 0
@@: test edi, 3
jz @f
stosb
jmp @b
@@: pop ecx
dec cx
jnz .extloop
pop ecx
pop edi
jmp pad_cont
 
i40_putimage:
add ebx, [base]
; Windows requires that all scanlines are DWORD-padded
mov edi, ebx
test ecx, 30000h
jnz pad_bmp
pad_cont:
xor esi, esi
; BITMAPINFO
push esi ; biClrImportant
push esi ; biClrUsed
push esi ; biYPelsPerMeter
push esi ; biXPelsPerMeter
push esi ; biSizeImage
push esi ; biCompression
push 180001h ; biPlanes, biBitCount
movzx eax, cx
neg eax
push eax ; biHeight
neg eax
shr ecx, 10h
push ecx ; biWidth
push 40 ; biSize
push ebx
lea ebx, [esp+4]
; SetDIBitsToDevice
push esi ; fuColorUse = DIB_RGB_COLORS
push ebx ; lpbmi
push edi ; lpvBits
push eax ; cScanLines
dec eax
push eax ; uStartScan
push eax ; YSrc
inc eax
push esi ; XSrc
push eax ; dwHeight
push ecx ; dwWidth
movzx ecx, dx
add ecx, [ebp+tls.client_top]
push ecx ; YDest
shr edx, 10h
add edx, [ebp+tls.client_left]
push edx ; XDest
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, ebx
push ebx ; hdc
call [SetDIBitsToDevice]
xchg eax, ebx
pop ebx
add esp, 40
push eax
push [ebp+tls.hWnd]
call [ReleaseDC]
cmp edi, ebx
jz @f
push edi
call free
@@:
ret
 
draw_button:
push ebx
push ecx
push ebp
mov ebp, esp
; word [ebp+4]=y_size, word [ebp+6]=y_start, word [ebp+8]=x_size, word [ebp+10]=x_start
; button body
push esi
cmp [buttontype], 0
jz .flatbtn
or esi, 80000000h
push esi
mov edx, 2
.l2:
cmp byte [esp+edx], 0xEB
jbe @f
mov byte [esp+edx], 0xEB
@@: add byte [esp+edx], 0x14
dec edx
jns .l2
pop esi
mov eax, 010101h
cmp cx, 20
ja @f
mov eax, 020202h
@@:
sub esi, eax
.flatbtn:
push eax
push esi
movzx eax, word [ebp+6]
add ax, cx
push eax
movzx eax, word [ebp+10]
add ax, bx
push eax
shr ecx, 16
push ecx
shr ebx, 16
push ebx
call rectangle_gradient
; button frames
pop eax
push eax
push eax
xor ecx, ecx
.l1:
cmp byte [esp+ecx], 0xDF
jbe @f
mov byte [esp+ecx], 0xDF
@@:
inc ecx
cmp ecx, 3
jb .l1
pop eax
add eax, 202020h
call create_select_pen
push eax
push 0
movzx eax, word [ebp+6]
add ax, [ebp+4]
push eax
push ebx
push edi
call [MoveToEx]
movzx eax, word [ebp+6]
push eax
push ebx
push edi
call [LineTo]
movzx eax, word [ebp+6]
push eax
movzx eax, word [ebp+8]
add ax, bx
push eax
push edi
call [LineTo]
call select_delete
cmp byte [ebp-4], 20h
jae @f
mov byte [ebp-4], 20h
@@:
cmp byte [ebp-3], 20h
jae @f
mov byte [ebp-3], 20h
@@:
cmp byte [ebp-2], 20h
jae @f
mov byte [ebp-2], 20h
@@:
mov eax, [ebp-4]
sub eax, 202020h
call create_select_pen
push eax
movzx eax, word [ebp+4]
add ax, [ebp+6]
push eax
movzx eax, word [ebp+8]
add ax, bx
push eax
push edi
call [LineTo]
movzx eax, word [ebp+4]
add ax, [ebp+6]
push eax
push ebx
push edi
call [LineTo]
call select_delete
pop eax
pop ebp
pop ecx
pop ebx
ret
 
add_button:
push esi
lea esi, [ebp+tls.buttons]
@@:
mov eax, [esi]
test eax, eax
jz .end
xchg esi, eax
jmp @b
.end:
push ecx
push edx
push button_desc.size
call malloc
mov [esi], eax
mov [eax+button_desc.next], 0
pop [eax+button_desc.id]
mov dword [eax+button_desc.xsize], ebx
pop dword [eax+button_desc.ysize]
pop [eax+button_desc.color]
ret
 
i40_define_button:
test edx, 0x80000000
jnz .delete
rol ebx, 16
add bx, word [ebp+tls.client_left]
rol ebx, 16
rol ecx, 16
add cx, word [ebp+tls.client_top]
rol ecx, 16
test edx, 0x40000000
jnz .nodraw
push ecx
push edx
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
pop edx
pop ecx
pushad
call draw_button
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
popad
.nodraw:
call add_button
.ret:
ret
.delete:
and edx, not 0x80000000
lea esi, [ebp+tls.buttons]
@@:
mov eax, [esi]
test eax, eax
jz @f
; The kernel checks only low word of button ID!
cmp word [eax+button_desc.id], dx
jz .found
xchg eax, esi
jmp @b
@@:
ret
.found:
; if active button is deleting, there is no more active button
cmp eax, [ebp+tls.active_button]
jnz @f
and [ebp+tls.active_button], 0
@@:
push [eax+button_desc.next]
push eax
call free
pop [esi+button_desc.next]
ret
 
invalid_slot_msg db 'Emulated program has requested information on non-existent slot'
db ' and will be terminated',0
invalid_slot:
call release_shared
push 0
push 0
push invalid_slot_msg
push 0
call [MessageBoxA]
jmp i40_terminate
 
get_os_process_info:
pushad
mov ebx, 5
call i40_sys_service
popad
stosd ; .cpu_usage
xor eax, eax
inc eax
stosw ; .window_stack_position
stosw ; .window_stack_value
dec eax
stosw ; .not_used1
mov eax, 'OS/I'
stosd
mov eax, 'DLE '
stosd
mov eax, ' '
stosd
xor eax, eax
stosd ; .memory_start
mov eax, 0x01000000-1
stosd ; .used_memory
xor eax, eax
inc eax
stosd ; .PID
dec eax
stosd
stosd
stosd
stosd
stosw ; .slot_state
scasw
stosd
stosd
stosd
stosd
stosb
jmp got_process_info
 
i40_get_process_info:
cmp ecx, -1
jnz @f
mov ecx, [ebp+tls.cur_slot]
inc ecx
@@:
add ebx, [base]
mov edx, [shared_data]
; cmp ecx, [edx+shared_data_struc.alloc_threads] ; too many programs will fail
cmp ecx, 256
ja invalid_slot
dec ecx
call acquire_shared
mov eax, ecx
call get_slot_ptr
mov esi, edi
mov edi, ebx
jecxz get_os_process_info
xor eax, eax
stosd ; .cpu_usage
mov eax, [edx+shared_data_struc.alloc_threads]
stosw ; .window_stack_position
stosw ; .window_stack_value
xor eax, eax
stosw ; .not_used1
push esi
add esi, 28
movsd
movsd
movsd
pop esi
stosd ; .memory_start
mov eax, [esi+24]
stosd ; .used_memory
mov eax, [esi]
stosd ; .PID
push ecx
xor eax, eax
push eax
push eax
push eax
push eax
push esp
push dword [esi+20]
call [GetWindowRect]
pop eax
stosd
pop eax
stosd
pop eax
sub eax, [edi-8]
sub eax, 1
adc eax, 0
stosd
pop eax
sub eax, [edi-8]
sub eax, 1
adc eax, 0
stosd
pop ecx
and word [edi], 0 ; .slot_state
cmp dword [esi], 0
jnz @f
mov byte [edi], 9
@@:
scasd
; client area coordinates
push esi
; for my window, return true coordinates from tls
cmp ecx, [ebp+tls.cur_slot]
jnz .notmy
lea esi, [ebp+tls.client_left]
movsd
movsd
lodsd
dec eax
stosd
lodsd
dec eax
stosd
jmp @f
.notmy:
; for other windows, return copy of window coordinates
add esi, 0x22
movsd
movsd
movsd
movsd
@@:
pop esi
; window state
sub esp, 40
push 44
push esp
push dword [esi+20]
call [GetWindowPlacement]
test eax, eax
jnz @f
add esp, 44
jmp .normal
@@:
mov eax, [esp+8] ; showCmd
add esp, 44
cmp eax, 3
jz .maximized
cmp eax, 2
jz .minimized
test eax, eax
jz .minimized
push dword [esi+20]
call [IsWindowVisible]
test eax, eax
jz .minimized
.normal:
xor eax, eax
jmp @f
.minimized:
mov al, 2
jmp @f
.maximized:
mov al, 1
@@:
stosb
got_process_info:
mov eax, [shared_data]
mov eax, [eax+shared_data_struc.alloc_threads]
mov dword [esp+20h], eax ; number of processes
call release_shared
ret
 
test_button_mouse:
cmp al, 86h
jnz @f
mov al, 6
test [ebp+tls.message_mask], 4
jz @f
mov [ebp+tls.translated_msg_code], al ; mouse
mov al, 3 ; button
@@: ret
 
event_test_redraw:
; if function 0 has not been called, then redraw message is present
; cmp [ebp+tls.showwnd], 0
; jnz @f
cmp [ebp+tls.curdraw], 0
jz @f
test [ebp+tls.message_mask], 1
jz @f
pop eax
mov dword [esp+20h], 1
@@:
ret
 
i40_wait_event:
call event_test_redraw
sub esp, 20h
xor eax, eax
xchg al, [ebp+tls.translated_msg_code]
test eax, eax
jnz @f
mov al, 2
test byte [ebp+tls.message_mask], al
jz .nokey
cmp [ebp+tls.keybuflen], ah
jnz @f
.nokey:
inc eax
test [ebp+tls.message_mask], 4
jz .nobut
cmp [ebp+tls.butbuflen], ah
jnz @f
.nobut:
mov ebx, esp
push 0
push 0
push 0
push ebx
call [GetMessageA]
test eax, eax
jz i40_terminate
push ebx
call [TranslateMessage]
push ebx
call [DispatchMessageA]
add esp, 20h
jmp i40_wait_event
@@:
add esp, 20h
cmp al, 6
jnz @f
test [ebp+tls.message_mask], 20h
jz i40_wait_event
@@:
call test_button_mouse
mov [esp+20h], eax
ret
 
i40_check_event:
call event_test_redraw
sub esp, 20h
xor eax, eax
xchg al, [ebp+tls.translated_msg_code]
or eax, eax
jnz .event
mov al, 2
test byte [ebp+tls.message_mask], al
jz .nokey
cmp [ebp+tls.keybuflen], ah
jnz .event
.nokey:
inc eax
test [ebp+tls.message_mask], 4
jz .nobut
cmp [ebp+tls.butbuflen], ah
jnz .event
.nobut:
@@:
mov ebx, esp
push 1
push 0
push 0
push 0
push ebx
call [PeekMessageA]
test eax, eax
jz .noevent
cmp dword [ebx+4], 0x12 ; WM_QUIT
jz i40_terminate
push ebx
call [TranslateMessage]
push ebx
call [DispatchMessageA]
xor eax, eax
cmp [ebp+tls.curdraw], al
jnz .redraw
xchg al, [ebp+tls.translated_msg_code]
or eax, eax
jz @b
.event:
add esp, 20h
cmp al, 6
jnz @f
test [ebp+tls.message_mask], 20h
jz i40_check_event
@@:
call test_button_mouse
mov [esp+20h], eax
ret
.redraw:
inc eax
add esp, 20h
test [ebp+tls.message_mask], eax
jz i40_check_event
mov [esp+20h], eax
ret
.noevent:
add esp, 20h
and dword [esp+20h], 0
ret
 
i40_redraw_status:
dec ebx
jz .fn1
dec ebx
jnz not_supported_i40_fn
ret
.fn1:
; delete all defined buttons
xor ebx, ebx
mov [ebp+tls.active_button], ebx ; no more active buttons
xchg ebx, [ebp+tls.buttons]
@@:
test ebx, ebx
jz .done
push ebx
mov ebx, [ebx]
call free
jmp @b
.done:
ret
 
i40_drawrect:
push ecx
push edx
push [ebp+tls.hWnd]
call [GetDC]
pop edx
pop ecx
xchg eax, edi
push 1
push edx
movzx eax, cx
shr ecx, 16
add ecx, [ebp+tls.client_top]
add eax, ecx
push eax
movzx eax, bx
shr ebx, 16
add ebx, [ebp+tls.client_left]
add eax, ebx
push eax
push ecx
push ebx
call rectangle_gradient
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
ret
 
get_screen_size:
call [GetDesktopWindow]
push eax
push eax
call [GetDC]
xchg eax, esi
push 8 ; HORZRES
push esi
call [GetDeviceCaps]
dec eax
xchg ebx, eax
shl ebx, 16
push 10 ; VERTRES
push esi
call [GetDeviceCaps]
dec eax
or ebx, eax
pop eax
push esi
push eax
call [ReleaseDC]
ret
 
i40_get_screen_size:
call get_screen_size
mov [esp+20h], ebx
ret
 
i40_set_background:
pushad
push 1
call init_background
popad
mov eax, [bgr_section]
test eax, eax
jnz @f
ret
@@:
dec ebx
jz .setsize
dec ebx
jz .setpixel
dec ebx
jz .redraw
dec ebx
jz .method
dec ebx
jz .setblock
dec ebx
jz .map
dec ebx
jnz not_supported_i40_fn
.unmap:
push ecx
mov esi, ecx
add esi, [base]
lea edi, [eax+10h]
mov ecx, [eax]
imul ecx, [eax+4]
lea ecx, [ecx*3]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
mov byte [eax+12], 1
mov byte [eax+13], 0
pop ecx
jmp i40_sys_services.free_heap
.map:
mov cl, 1
xchg cl, [eax+13]
test cl, cl
jz @f
push eax ecx edx
push 100
call [Sleep]
pop edx ecx eax
jmp .map
@@:
lea esi, [eax+10h]
mov ecx, [eax]
imul ecx, [eax+4]
lea ecx, [ecx*3]
pushad
call i40_sys_services.allocate_heap
popad
mov [esp+20h], eax
test eax, eax
jnz @f
mov byte [esi-10h+13], 0
ret
@@:
mov edi, eax
add edi, [base]
mov edx, ecx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
ret
.setblock:
xchg esi, ecx
add esi, [base]
lea edi, [eax+edx+10h]
rep movsb
mov byte [eax+12], 1
ret
.setsize:
push ecx
@@:
mov cl, 1
xchg cl, [eax+13]
test cl, cl
jz @f
push eax ecx edx
push 100
call [Sleep]
pop edx ecx eax
jmp @b
@@:
pop ecx
mov [eax], ecx
mov [eax+4], edx
mov byte [eax+12], 1
mov byte [eax+13], 0
ret
.method:
mov [eax+8], ecx
mov byte [eax+12], 1
ret
.setpixel:
and edx, 0x00FFFFFF
and dword [eax+ecx+10h], 0xFF000000
or [eax+ecx+10h], edx
mov byte [eax+12], 1
@@: ret
.redraw:
cmp byte [eax+12], 0
jz @b
.redraw_force:
mov byte [eax+12], 0
mov ebx, 2
mov eax, [shared_data]
cmp [eax+shared_data_struc.vk], 0
jnz .settmp
mov eax, [SetBgrQuestion]
dec eax
js .ask
jz .permanent
dec eax
jz .settmp
; don't set
ret
.ask:
push 123h
push aConfirm
push BgrQuestionText
push 0
call [MessageBoxA]
cmp al, 6
jz .permanent
cmp al, 7
jz .settmp
ret
.permanent:
inc ebx
.settmp:
push eax
push esp
push 3 ; KEY_QUERY_VALUE | KEY_SET_VALUE
push 0
push bgrkeyname
push 80000001h
call [RegOpenKeyExA]
test eax, eax
pop esi
jnz .nopos
; save old reg values
push '0'
push '0'
push 2
mov eax, esp
push eax ; lpcbData
add eax, 4
push eax ; lpData
push 0 ; lpType
push 0 ; lpReserved
push bgrstylevalue ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
mov eax, esp
mov dword [eax], 2
push eax ; lpcbData
add eax, 8
push eax ; lpData
push 0 ; lpType
push 0 ; lpReserved
push bgrtilevalue ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
pop eax
mov ecx, '0'
mov eax, [bgr_section]
cmp byte [eax+8], 1
jz @f
mov cl, '2'
@@:
push ecx
mov eax, esp
push 2
push eax
push 1
push 0
push bgrstylevalue
push esi
call [RegSetValueExA]
pop ecx
cmp cl, '0'
jnz .stretch
push '1' ; tile
jmp @f
.stretch:
push '0'
@@:
mov eax, esp
push 2
push eax
push 1
push 0
push bgrtilevalue
push esi
call [RegSetValueExA]
pop ecx
push esi
call [RegCloseKey]
.nopos:
mov edi, win32_path
push startcurdir
push edi
call [lstrcpyA]
push bgrfilename
test bl, 1
jnz @f
mov dword [esp], bgrtempfilename
@@:
push edi
call [lstrcatA]
push 0
push 80h
push 2
push 0
push 0
push 40000000h
push edi
call [CreateFileA]
inc eax
jnz @f
push 10h
push 0
push BgrFileErrorMsg
push 0
call [MessageBoxA]
pop ecx
pop ecx
ret
@@:
dec eax
xchg eax, esi
; bmp header
mov ecx, [bgr_section]
mov eax, [ecx+4]
mov [bgr_bmp_header+16h], eax
mov eax, [ecx]
mov [bgr_bmp_header+12h], eax
add eax, eax
add eax, [ecx]
add eax, 3
and al, not 3
mul dword [ecx+4]
; eax=size of image
mov [bgr_bmp_header+22h], eax
add eax, 36h
mov [bgr_bmp_header+2], eax
push eax
mov eax, esp
push 0
push eax
push 36h
push bgr_bmp_header
push esi
call [WriteFile]
pop eax
; bmp data
mov eax, [bgr_section]
mov ecx, [eax+4]
lea edi, [eax+10h]
mov eax, [eax]
mul ecx
imul eax, 3
add edi, eax
.putline:
push ecx
mov ecx, [bgr_section]
mov eax, [ecx]
add eax, eax
add eax, [ecx]
sub edi, eax
push eax
push eax
mov ecx, esp
push 0
push ecx
push eax
push edi
push esi
call [WriteFile]
pop eax
pop ecx
and ecx, 3
jz .nopad
.padloop:
push ecx
push 0
push eax
mov eax, esp
push 0
push eax
add eax, 4
push 1
push eax
push esi
call [WriteFile]
pop eax
pop eax
pop ecx
loop .padloop
.nopad:
pop ecx
loop .putline
push esi
call [CloseHandle]
mov eax, [shared_data]
mov [eax+shared_data_struc.dwNewBgrTime], -1
;or [dwNewBgrTime], -1
push ebx
push win32_path
push 0
push 14h
call [SystemParametersInfoA]
cmp bl, 2
jnz @f
push eax
push esp
push 500
push 0
push 0
push 0
push 0x1A
push 0xFFFF
call [SendMessageTimeoutA]
pop eax
; restore key values
push eax
push esp
push 2 ; KEY_SET_VALUE
push 0
push bgrkeyname
push 80000001h
call [RegOpenKeyExA]
test eax, eax
pop esi
jnz @f
mov eax, esp
push 2
push eax
push 1
push 0
push bgrstylevalue
push esi
call [RegSetValueExA]
lea eax, [esp+4]
push 2
push eax
push 1
push 0
push bgrtilevalue
push esi
call [RegSetValueExA]
push esi
call [RegCloseKey]
@@:
mov esi, [shared_data]
call [GetTickCount]
add eax, 3000
;mov [dwNewBgrTime], eax
mov [esi+shared_data_struc.dwNewBgrTime], eax
pop ecx
pop ecx
ret
 
i40_getbutton:
movzx ecx, [ebp+tls.butbuflen]
jecxz .empty
lea edi, [ebp+tls.butbuffer]
mov eax, [edi]
and al, not 1
mov [esp+20h], eax
lea esi, [edi+4]
dec ecx
mov [ebp+tls.butbuflen], cl
rep movsd
ret
.empty:
mov byte [esp+20h], 1
ret
 
i40_sys_service:
cmp ebx, 1
jz .19
cmp ebx, 2
jz .kill
cmp ebx, 18
jnz .not2
.kill:
call acquire_shared
xchg eax, ecx
cmp eax, 1
jbe release_shared ; invalid PID/slot - ignore
mov esi, [shared_data]
mov edi, esi
mov ecx, [esi]
add esi, shared_data_struc.threads
cmp ebx, 2
jz .slot
@@:
cmp [esi], eax
jz .found
add esi, 64
loop @b
jmp release_shared ; no such PID - ignore
.slot:
dec eax
cmp eax, ecx
jae release_shared
shl eax, 6
add esi, eax
cmp dword [esi], 0
jz release_shared
.found:
; terminate self?
call get_cur_slot_ptr
cmp esi, edi
jnz @f
call release_shared
jmp i40_terminate
@@:
; get thread and process handles
mov eax, [esi+shared_data_struc.win32_hThread-shared_data_struc.threads]
call server_convert
mov edi, eax
call release_shared
; target thread is suspended? if so, do not wait
push edi
call [SuspendThread]
test eax, eax
jnz .suspended
push edi
call [ResumeThread]
; send WM_CLOSE to thread window
push 0
push 0
push 0x10 ; WM_CLOSE
push [esi+shared_data_struc.hWnd-shared_data_struc.threads]
call [PostMessageA]
; wait no more than 1 second
push 1000
push edi
call [WaitForSingleObject]
cmp eax, 258 ; WAIT_TIMEOUT
jnz .ret_close
; let target thread to terminate itself
push edi
call [SuspendThread]
.suspended:
mov ebx, [esi+shared_data_struc.win32_stack-shared_data_struc.threads]
sub esp, 0xB2*4
push 1000Fh
mov esi, esp
push esp
push edi
call [GetThreadContext]
mov ax, ss
cmp [esi+0xC8], ax
jz @f
mov [esi+0xC8], ss
mov [esi+0xC4], ebx
@@:
mov [esi+0xBC], cs
mov [esi+0x98], ds
mov [esi+0x94], es
mov [esi+0xB8], dword i40_terminate
push esi
push edi
call [SetThreadContext]
add esp, 0xB3*4
@@:
push edi
call [ResumeThread]
cmp eax, 1
ja @b
.ret_close:
push edi
call [CloseHandle]
ret
.not2:
cmp ebx, 3
jnz .not3
cmp ecx, 2
jb .noactivate_ret
call acquire_shared
mov eax, [shared_data]
cmp ecx, [eax+shared_data_struc.alloc_threads]
ja .noactivate_release
lea eax, [ecx-1]
call get_slot_ptr
cmp dword [edi], 0
jz .noactivate_release
mov esi, [edi+shared_data_struc.hWnd-shared_data_struc.threads]
call release_shared
.restore_given_window:
sub esp, 40
push 44
push esp
push esi
call [GetWindowPlacement]
mov eax, [esp+8]
add esp, 44
mov ecx, 5 ; SW_SHOW
cmp al, 2 ; SW_SHOWMINIMIZED
jnz @f
mov cl, 9 ; SW_RESTORE
@@:
push ecx
push esi
call [ShowWindow]
; push esi
; call [BringWindowToTop]
push esi
call [SetForegroundWindow]
ret
.noactivate_release:
call release_shared
.noactivate_ret:
ret
.not3:
cmp ebx, 4
jnz .not4
; get idle time - current implementation on NT simply returns cpuspeed
cmp [bIs9x], 0
jz .5
idletime_via_ring0 = 1
if ~idletime_via_ring0
mov eax, [shared_data]
cmp [eax+shared_data_struc.b9xPerfInited], 0
jnz .perfinited
call acquire_shared
cmp [eax+shared_data_struc.b9xPerfInited], 0
jnz @f
push eax
push esp ; phkResult
push 1 ; samDesired = KEY_QUERY_VALUE
push 0 ; ulOptions
push perfstart ; lpSubKey
push 80000006h ; hKey = HKEY_DYN_DATA
call [RegOpenKeyExA]
pop esi
test eax, eax
jnz .perfinitfail
push eax
mov eax, esp
push 4
push esp ; lpcbData
push eax ; lpData
push 0 ; lpType
push 0 ; lpReserved
push perfval ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
pop ecx
pop ecx
push eax
push esi
call [RegCloseKey]
pop eax
test eax, eax
jnz .perfinitfail
push 200
call [Sleep] ; give chance to collect data
@@:
mov eax, [shared_data]
mov [eax+shared_data_struc.b9xPerfInited], 1
call release_shared
.perfinited:
push 100
pop ebx
push eax
push esp ; phkResult
push 1 ; samDesired = KEY_QUERY_VALUE
push 0 ; ulOptions
push perfget ; lpSubKey
push 80000006h ; hKey = HKEY_DYN_DATA
call [RegOpenKeyExA]
pop esi
test eax, eax
jnz @f
push ebx
mov eax, esp
push 4
push esp ; lpcbData
push eax ; lpData
push 0 ; lpType
push 0 ; lpReserved
push perfval ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
pop ecx
pop ebx
push esi
call [RegCloseKey]
@@:
pushad
call .5
popad
push 100
pop ecx
sub ebx, ecx
neg ebx
mul ebx
div ecx
mov [esp+20h], eax
ret
.perfinitfail:
call release_shared
push 40h
push 0
push aPerfInitFailed
push 0
call [MessageBoxA]
jmp .5
else
mov eax, [shared_data]
cmp [eax+shared_data_struc.b9xPerfInited], 0
jnz @f
.idlecount_init:
div edx
@@:
mov ebx, [eax+shared_data_struc.idlecount]
pushad
call .5
popad
mul ebx
mov ecx, 1000
div ecx
mov [esp+20h], eax
ret
end if
.not4:
cmp ebx, 5
jnz .not5
.5:
mov eax, [shared_data]
mov ebx, [eax+shared_data_struc.cpuspeed]
test ebx, ebx
jnz @f
; determine cpu speed
; 1) check for value in registry
push eax
push esp
push 1 ; KEY_QUERY_VALUE
push 0
push keycpu
push 80000002h
call [RegOpenKeyExA]
test eax, eax
pop eax
jnz .nokey
xchg eax, esi
push eax
push 4
push esp
lea eax, [esp+8]
push eax
push 0
push 0
push keymhz
push esi
call [RegQueryValueExA]
push eax
push esi
call [RegCloseKey]
pop eax
test eax, eax
pop eax
pop eax
jnz .nokey
imul eax, 1000000
jmp .speed_found
.nokey:
; 2) sleep for 1/4 sec and read TSC
rdtsc
push eax edx
push 250
call [Sleep]
rdtsc
pop ecx ebx
sub eax, ebx
sbb edx, ecx
shl eax, 2
.speed_found:
xchg ebx, eax
mov eax, [shared_data]
mov [eax+shared_data_struc.cpuspeed], ebx
@@:
mov [esp+20h], ebx
ret
.not5:
cmp ebx, 7
jnz .not7
mov eax, [shared_data]
mov eax, [eax+shared_data_struc.active_process]
mov [esp+20h], eax
ret
.not7:
cmp ebx, 8
jnz .not8
dec ecx
jnz @f
mov eax, [shared_data]
movzx eax, [eax+shared_data_struc.sound_flag]
mov [esp+20h], eax
ret
@@:
dec ecx
jnz not_supported_i40_fn
mov eax, [shared_data]
lock xor [eax+shared_data_struc.sound_flag], 1
ret
.not8:
cmp ebx, 9
jnz .not9
.19:
mov eax, [shared_data]
cmp [eax+shared_data_struc.vk], 0
jz not_supported_i40_fn
.server_terminate:
div edx
ret
.not9:
cmp ebx, 10
; jnz .not10
; call minimize_window
; ret
jz minimize_window
.not10:
cmp ebx, 11
jnz .not11
dec ecx
jnz not_supported_i40_fn
xor eax, eax
mov edi, edx
add edi, [base]
; floppy is not supported yet => return "no floppy installed"
stosb
; IDEx configuration
; CD is not supported yet. On IDEx there may be only HD (or nothing)
xor edx, edx
mov esi, hd_partitions_num
push esi
.idex:
lodsd
shl edx, 2
test eax, eax
jz @f
inc edx
@@:
cmp esi, hd_partitions_num+4*4
jc .idex
mov [edi], dl
inc edi
; number of partitions
pop esi
mov cl, 4
@@:
lodsd
stosb
loop @b
; reserved bytes
and dword [edi], 0
ret
.not11:
cmp ebx, 12
jnz .not12
.return0:
and dword [esp+20h], 0
ret
.not12:
cmp ebx, 13
jnz .not13
mov edi, ecx
add edi, [base]
mov esi, version_inf
mov ecx, version_end - version_inf
rep movsb
ret
.not13:
cmp ebx, 14
jz .return0
cmp ebx, 15
jnz .not15
call get_screen_size
movzx eax, bx
inc eax
shr eax, 1
push eax
shr ebx, 16
inc ebx
shr ebx, 1
push ebx
call [SetCursorPos]
ret
.not15:
cmp ebx, 16
jnz .not16
sub esp, 20h
push esp
call [GlobalMemoryStatus]
mov eax, [esp+12]
add esp, 20h
shr eax, 10
mov [esp+20h], eax
ret
.not16:
cmp ebx, 17
jnz .not17
sub esp, 20h
push esp
call [GlobalMemoryStatus]
mov eax, [esp+8]
add esp, 20h
shr eax, 10
mov [esp+20h], eax
ret
.not17:
cmp ebx, 19
jnz .not19
jecxz .19_0
dec ecx
jz .19_1
dec ecx
jz .19_2
dec ecx
jz .19_3
dec ecx
jnz not_supported_i40_fn
movzx eax, dx
push eax
shr edx, 16
push edx
call [SetCursorPos]
ret
.19_0:
mov eax, [shared_data]
movzx eax, [eax+shared_data_struc.mouse_speed_factor]
mov [esp+20h], eax
ret
.19_1:
mov eax, [shared_data]
mov [eax+shared_data_struc.mouse_speed_factor], dx
ret
.19_2:
mov eax, [shared_data]
mov eax, [eax+shared_data_struc.mouse_delay]
mov [esp+20h], eax
ret
.19_3:
mov eax, [shared_data]
mov [eax+shared_data_struc.mouse_delay], edx
ret
.not19:
cmp ebx, 21
jnz .not21
xchg eax, ecx
call get_slot_num
mov [esp+20h], edx
ret
.not21:
cmp ebx, 22
jnz not_supported_i40_fn
cmp ecx, 4
jae not_supported_i40_fn
shr ecx, 1
jnc @f
xchg eax, edx
call get_slot_num
@@:
dec edx
jz .22err
mov esi, [shared_data]
cmp edx, [esi]
jae .22err
shl edx, 6
mov esi, [esi+edx+shared_data_struc.hWnd]
and dword [esp+20h], 0
dec ecx
js minimize_given_window
jmp .restore_given_window
.22err:
or dword [esp+20h], -1
ret
 
get_slot_num:
push ecx
mov esi, [shared_data]
mov ecx, [esi]
add esi, shared_data_struc.threads
xor edx, edx
@@:
inc edx
cmp [esi], eax
jz @f
add esi, 64
loop @b
xor edx, edx
@@:
pop ecx
ret
 
minimize_window:
mov esi, [ebp+tls.hWnd]
minimize_given_window:
mov [ebp+tls.butbuflen], 0
xor eax, eax ; SW_HIDE
mov ecx, [shared_data]
cmp [ecx+shared_data_struc.vk], 0
jnz @f
mov al, 6 ; SW_MINIMIZE
@@:
push eax
push esi
call [ShowWindow]
ret
 
server_convert:
div edx
ret
 
i40_sys_setup:
mov eax, [shared_data]
and dword [esp+20h], 0
dec ebx
jnz .nomidi
cmp ecx, 100h
jb .nomidi
cmp ecx, 0xFFFF
ja .nomidi
mov [eax+shared_data_struc.midi_base], cx
ret
.nomidi:
dec ebx
jnz .not2
mov edi, keymap
dec ecx
jz .settable
mov edi, keymap_shift
dec ecx
jz .settable
mov edi, keymap_alt
dec ecx
jnz .nosettable
.settable:
add edx, [base]
mov esi, edx
mov ecx, 80h/4
rep movsd
ret
.nosettable:
cmp ecx, 9-3
jnz .nosetkeyboard
mov [eax+shared_data_struc.keyboard], dx
ret
.nosetkeyboard:
inc dword [esp+20h]
ret
.not2:
dec ebx
jnz .not3
mov [eax+shared_data_struc.cd_base], cl
ret
.not3:
dec ebx
jnz .not4
cmp ecx, 0x100
jb .not4
cmp ecx, 0xFFFF
ja .not4
mov word [eax+shared_data_struc.sb16], cx
ret
.not4:
dec ebx
jnz .not5
mov [eax+shared_data_struc.syslang], ecx
ret
.not5:
dec ebx
jnz .not6
cmp ecx, 0x100
jb .not6
mov [eax+shared_data_struc.wss], ecx
ret
.not6:
dec ebx
jnz .not7
mov [eax+shared_data_struc.hd_base], cl
ret
.not7:
dec ebx
jnz .not8
mov [eax+shared_data_struc.fat32part], ecx
ret
.not8:
dec ebx
dec ebx
jnz .not10
mov [eax+shared_data_struc.sound_dma], ecx
ret
.not10:
dec ebx
jnz .not11
and ecx, 1
mov [eax+shared_data_struc.lba_read_enabled], ecx
ret
.not11:
dec ebx
jnz .not12
and ecx, 1
jz .okcheck11
cmp [eax+shared_data_struc.bAllowReadPCI], 0
jnz .okcheck11
; be silent, because in loading process (of VirtualKolibri) SETUP will try this anyway
; push 40h
; push 0
; push aPciDisabled
; push 0
; call [MessageBoxA]
ret
.okcheck11:
mov [eax+shared_data_struc.pci_access_enabled], ecx
ret
.not12:
mov byte [esp+20h], 21 ; restore eax
jmp not_supported_i40_fn
 
i40_wait_event_timeout:
; call event_test_redraw
; imul ebx, ebx, 10
sub esp, 20h
mov esi, esp
jmp .M
.L:
push 2
pop eax
test byte [ebp+tls.message_mask], al
jz .nokey
cmp [ebp+tls.keybuflen], ah
jnz .event
.nokey:
inc eax
test [ebp+tls.message_mask], 4
jz .nobut
cmp [ebp+tls.butbuflen], ah
jnz .event
.nobut:
push 1 ; PM_REMOVE
push 0
push 0
push 0
push esi
call [PeekMessageA]
test eax, eax
jz .notfound
cmp dword [esi+4], 0x12 ; WM_QUIT
jz i40_terminate
push esi
call [TranslateMessage]
push esi
call [DispatchMessageA]
.M:
xor eax, eax
cmp [ebp+tls.curdraw], al
jz @f
test [ebp+tls.message_mask], 1
jz @f
inc eax
add esp, 20h
mov dword [esp+20h], eax
ret
@@:
xchg al, [ebp+tls.translated_msg_code]
test eax, eax
jz .L
cmp al, 6
jnz .event
test [ebp+tls.message_mask], 20h
jz .L
.event:
add esp, 20h
call test_button_mouse
mov [esp+20h], eax
ret
.notfound:
push 10
call [Sleep]
dec ebx
jnz .L
.timeout:
add esp, 20h
and dword [esp+20h], 0
ret
 
i40_getsetup:
mov eax, [shared_data]
dec ebx
jnz .not_midi_base
movzx eax, [eax+shared_data_struc.midi_base]
mov [esp+20h], eax
ret
.not_midi_base:
dec ebx
jnz .not_keyboard
mov esi, keymap
dec ecx
jz .getmap
mov esi, keymap_shift
dec ecx
jz .getmap
mov esi, keymap_alt
dec ecx
jnz .nobase
.getmap:
mov ecx, 128/4
mov edi, edx
add edi, [base]
rep movsd
ret
.nobase:
cmp ecx, 9-3
jnz not_supported_i40_fn
movzx eax, [eax+shared_data_struc.keyboard]
mov [esp+20h], eax
ret
.not_keyboard:
dec ebx
jnz .not_cd_base
movzx eax, [eax+shared_data_struc.cd_base]
mov [esp+20h], eax
ret
.not_cd_base:
dec ebx
jnz .not_sb16
mov eax, [eax+shared_data_struc.sb16]
mov [esp+20h], eax
ret
.not_sb16:
dec ebx
jnz .not_lang
mov eax, [eax+shared_data_struc.syslang]
mov [esp+20h], eax
ret
.not_lang:
dec ebx
jnz .not_wss
mov eax, [eax+shared_data_struc.wss]
mov [esp+20h], eax
ret
.not_wss:
dec ebx
jnz .not_hdbase
movzx eax, [eax+shared_data_struc.hd_base]
mov [esp+20h], eax
ret
.not_hdbase:
dec ebx
jnz .not_fat32part
mov eax, [eax+shared_data_struc.fat32part]
mov [esp+20h], eax
ret
.not_fat32part:
dec ebx
jnz .not_timer_ticks
call [GetTickCount]
push 10
pop ecx
xor edx, edx
div ecx
mov [esp+20h], eax
ret
.not_timer_ticks:
dec ebx
jnz .not_sound_dma
mov eax, [eax+shared_data_struc.sound_dma]
mov [esp+20h], eax
ret
.not_sound_dma:
dec ebx
jnz .not_lba_enabled
mov eax, [eax+shared_data_struc.lba_read_enabled]
mov [esp+20h], eax
ret
.not_lba_enabled:
dec ebx
jnz .not_pci_enabled
mov eax, [eax+shared_data_struc.pci_access_enabled]
mov [esp+20h], eax
ret
.not_pci_enabled:
mov dword [esp+20h], 1 ; this is kernel rule, not my
ret
 
i40_get_sys_date:
sub esp, 10h
push esp
call [GetLocalTime]
movzx eax, word [esp+6]
aam
shl ax, 4
shr ah, 4
shl eax, 16-4
mov ax, [esp+2]
aam
shl ax, 4
shr ah, 4
shr ax, 4
mov bl, al
mov ax, [esp]
sub ax, 2000
aam
shl ax, 4
shr ah, 4
shr ax, 4
mov ah, bl
add esp, 10h
mov [esp+20h], eax
ret
 
i40_current_folder:
add ecx, [base]
dec ebx
jz .set
dec ebx
jnz not_supported_i40_fn
mov edi, ecx
mov esi, [ebp+tls.cur_dir]
push edx
push esi
call [lstrlenA]
pop ecx
inc eax
cmp ecx, eax
jb @f
mov ecx, eax
@@:
rep movsb
mov byte [edi-1], 0
mov [esp+20h], eax
ret
.set:
mov esi, ecx
cmp byte [ecx], '/'
jnz .relative
push [ebp+tls.cur_dir]
call free
push esi
call [lstrlenA]
inc eax ; (for terminating zero)
inc eax ; '/sys' -> '/rd/1' requires one additional byte
push eax
push eax
call malloc
mov [ebp+tls.cur_dir], eax
mov edi, eax
pop ecx
mov eax, [esi]
or eax, ' '
cmp eax, '/sys'
jnz @f
mov eax, '/rd/'
stosd
mov al, '1'
stosb
sub ecx, 4
add esi, 4
@@:
rep movsb
ret
.relative:
push [ebp+tls.cur_dir]
call [lstrlenA]
push eax
push esi
call [lstrlenA]
mov edi, eax
inc eax
add [esp], eax
push [ebp+tls.cur_dir]
push 0
push [hHeap]
call [HeapReAlloc]
mov [ebp+tls.cur_dir], eax
add edi, eax
.l1:
cmp word [esi], '.'
jz .ret
cmp word [esi], './'
jnz @f
inc esi
inc esi
jmp .l1
@@:
cmp word [esi], '..'
jnz .copy
cmp byte [esi+2], 0
jz @f
cmp byte [esi+2], '/'
jnz .copy
@@:
dec edi
cmp edi, [ebp+tls.cur_dir]
jbe @f
cmp byte [edi], '/'
jnz @b
@@:
inc esi
inc esi
cmp byte [esi], 0
jz .ret
inc esi
jmp .l1
.copy:
lodsb
stosb
test al, al
jnz .copy
ret
.ret:
mov byte [edi], 0
ret
 
i40_delete_ramdisk_file:
sub esp, 512
mov edi, esp
call ramdisk2win32
push edi
call [DeleteFileA]
add esp, 512
ret
 
i40_write_ramdisk_file:
test esi, esi
jnz not_supported_i40_fn
sub esp, 512
mov edi, esp
push ecx edx
call ramdisk2win32
push 0
push 80h
push 2
push 0
push 0
push 40000000h
push edi
call [CreateFileA]
inc eax
jz .ret
dec eax
xchg eax, esi
pop edx ecx
add ecx, [base]
push eax
mov eax, esp
push 0
push eax
push edx
push ecx
push esi
call [WriteFile]
pop eax
push esi
call [CloseHandle]
.ret:
add esp, 512
and dword [esp+20h], 0
ret
 
i40_screen_getpixel:
push 0
call [GetDC]
xchg eax, esi
push 8
push esi
call [GetDeviceCaps]
xchg eax, ebx
xor edx, edx
div ebx
push eax
push edx
push esi
call [GetPixel]
push eax
push esi
push 0
call [ReleaseDC]
pop eax
call convert_color
mov [esp+20h], eax
ret
 
i40_screen_getarea:
add ebx, [base]
push ecx ebx edx
mov edi, ecx
movsx ebx, cx
sar edi, 16
cmp ebx, 0
jle .nodata
cmp edi, 0
jg .okdata
.nodata:
pop edx ebx ecx
ret
.okdata:
xor eax, eax
push eax
call [GetDC]
push eax
push eax
call [CreateCompatibleDC]
xchg eax, esi
push ebx
push edi
push dword [esp+8]
call [CreateCompatibleBitmap]
push eax
push esi
call [SelectObject]
push eax
movzx eax, word [esp+8]
movzx ecx, word [esp+8+2]
push 0xCC0020
push eax
push ecx
push dword [esp+16]
push ebx
push edi
push 0
push 0
push esi
call [BitBlt]
push esi
call [SelectObject]
push ebp
xchg eax, ebp
; esi=hDC, ebp=hBitmap, ebx=height, edi=width
xor eax, eax
push eax ; biClrImportant
push eax ; biClrUsed
push eax ; biYPelsPerMeter
push eax ; biXPelsPerMeter
push eax ; biSizeImage
push eax ; biCompression
push 180001h ; biBitCount, biPlanes
push ebx ; biHeight
neg dword [esp]
push edi ; biWidth
push 40 ; biSize
mov ecx, esp
push eax ; uUsage
push ecx ; lpbi
mov eax, [ecx+52]
test edi, 3
jz .width_aligned_1
lea eax, [3*edi+3]
and al, not 3
mul ebx
call malloc_big
.width_aligned_1:
push eax ; lpvBits
push ebx ; cScanLines
push 0 ; uStartScan
push ebp ; hbmp
push esi ; hdc
xchg eax, edi
call [GetDIBits]
add esp, 40
push ebp
call [DeleteObject]
pop ebp
push esi
call [DeleteDC]
push 0
call [ReleaseDC]
pop edx eax edx
cmp eax, edi
jz .ret
; edi -> bits from Windows [dword-aligned scanlines], eax -> bits for Kolibri [no spaces],
shr edx, 16
; ebx = height, edx = width
push 8000h
push 0
push edi
xchg eax, edi
lea edx, [edx*3]
xchg eax, esi
@@:
mov ecx, edx
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
add esi, 3
and esi, not 3
sub ebx, 1
jnz @b
call [VirtualFree]
.ret:
ret
 
i40_read_mouse_pos:
dec ebx
js .get_coord
jz .get_coord
dec ebx
jnz .ifcursor
cmp [bIs9x], 0
jnz read_9x_mouse_buttons
xor ebx, ebx
push 6 ; VK_XBUTTON2
call .aks
push 5 ; VK_XBUTTON1
call .aks
push 4 ; VK_MBUTTON
call .aks
push 2 ; VK_RBUTTON
call .aks
push 1 ; VK_LBUTTON
call .aks
mov [esp+20h], ebx
ret
.get_coord:
push eax
push eax
push esp
call [GetCursorPos]
pop eax ; x
pop ecx ; y
test ebx, ebx
js @f
sub ax, [ebp+tls.x_start]
sub ax, word [ebp+tls.client_left]
sub cx, [ebp+tls.y_start]
sub cx, word [ebp+tls.client_top]
@@:
shl eax, 16
add eax, ecx
mov [esp+20h], eax
ret
.ifcursor:
dec ebx
dec ebx
jz .load_cursor
dec ebx
jz .set_cursor
dec ebx
jnz .not_cursor
.delete_cursor:
jecxz .delete_invalid
call acquire_shared
mov eax, ecx
mov ecx, num_cursors
mov edi, [shared_data]
add edi, shared_data_struc.cursors
@@:
add edi, 8
cmp [edi-8], eax
loopnz @b
jnz .delete_invalid_release
mov ecx, [ebp+tls.cur_slot]
cmp [edi-4], ecx
jnz .delete_invalid_release
and dword [edi-8], 0
and dword [edi-4], 0
call release_shared
push eax
call [DestroyCursor]
; the current kernel implementation returns garbage !
mov dword [esp+20h], 0xBAADF00D ; is it garbage? :-)
ret
.delete_invalid_release:
call release_shared
.delete_invalid:
push 10h
push 0
push aInvalidCursor
push 0
call [MessageBoxA]
; the current kernel implementation returns 6 !?
mov dword [esp+20h], 6
ret
.set_cursor:
; set_cursor for invalid handle reverts to standard arrow
call acquire_shared
mov eax, ecx
jecxz .setarrow
mov ecx, num_cursors
mov edi, [shared_data]
add edi, shared_data_struc.cursors
@@:
add edi, 8
cmp [edi-8], eax
loopnz @b
jz @f
.setarrow:
mov eax, [hArrow]
@@:
; N.B. I don't check process field, because the kernel allows to set
; cursors, loaded by another process
call release_shared
mov [ebp+tls.hCursor], eax
push eax
call [SetCursor]
mov [esp+20h], eax
ret
.load_cursor:
test dx, dx
jz .fromfile
dec dx
jz .frommem
dec dx
jz .indirect
jmp not_supported_i40_fn
.fromfile:
mov esi, ecx
add esi, [base]
sub esp, 204h
mov edi, esp
call i40_file_system_lfn.parse
test eax, eax
jz @f
add esp, 204h
and dword [esp+20h], 0
ret
@@:
push 10h ; LR_LOADFROMFILE
push 32
push 32
push 2 ; IMAGE_CURSOR
push edi
push 0
call [LoadImageA]
add esp, 204h
test eax, eax
jnz .addcursor
push 10h
push 0
push aCursorFailed
jmp .mberr
.addcursor:
call acquire_shared
mov ecx, num_cursors
mov edi, [shared_data]
add edi, shared_data_struc.cursors
@@:
add edi, 8
cmp dword [edi-8], 0
loopnz @b
jz @f
call release_shared
push 10h
push 0
push aCursorLimitExceeded
jmp .mberr
@@:
mov [edi-8], eax
mov edx, [ebp+tls.cur_slot]
mov [edi-4], edx
call release_shared
mov [esp+20h], eax
ret
.frommem:
add ecx, [base]
cmp dword [ecx], 0x020000
jz @f
push 10h
push 0
push aInvCursorData
.mberr:
push 0
call [MessageBoxA]
.reterr:
and dword [esp+20h], 0
ret
@@:
cmp word [ecx+4], 1
jz @f
push 10h
push 0
push aOnlyOneCursor
jmp .mberr
@@:
cmp word [ecx+6], 0x2020
jz @f
push 10h
push 0
push aInvCursorDim
jmp .mberr
@@:
mov eax, [ecx+0Ah]
add ecx, [ecx+12h]
sub ecx, 4
push dword [ecx]
mov [ecx], eax
push ecx
push 0
push 32
push 32
push 0x00030000
push 0
push 0x2E8+4
push ecx
call [CreateIconFromResourceEx]
pop ecx
pop dword [ecx]
test eax, eax
jnz .addcursor
.gen_failed:
push 10h
push 0
push aCursorFailed
jmp .mberr
.indirect:
mov ebx, edx
shr ebx, 16 ; bl = y, bh = x
mov esi, ecx
add esi, [base]
push 32*32*4
call malloc
mov edi, eax
mov ecx, 32*32
push esi edi
@@:
lodsd
and eax, 0xFFFFFF
stosd
loop @b
pop edi esi
push edi ; lpvBits
push 32 ; cBitsPerPel
push 1 ; cPlanes
push 32 ; nHeight
push 32 ; nWidth
call [CreateBitmap]
test eax, eax
jnz @f
.free_edi:
push edi
call free
jmp .gen_failed
@@:
push eax ; ICONINFO.hbmColor
mov ecx, 32*4
push esi edi
.1:
push ecx
mov cl, 8
xor edx, edx
@@:
lodsd
shr eax, 24
setz al
lea edx, [edx*2+eax]
loop @b
mov al, dl
stosb
pop ecx
loop .1
pop edi esi
push edi ; lpvBits
push 1 ; cBitsPerPel
push 1 ; cPlanes
push 32 ; nHeight
push 32 ; nWidth
call [CreateBitmap]
test eax, eax
jnz @f
call [DeleteObject]
jmp .free_edi
@@:
push eax ; ICONINFO.hbmMask
movzx eax, bl
push eax ; ICONINFO.yHotSpot
movzx eax, bh
push eax ; ICONINFO.xHotSpot
push 0 ; ICONINFO.fIcon
push esp
call [CreateIconIndirect]
mov ebx, eax
add esp, 12
call [DeleteObject]
call [DeleteObject]
test ebx, ebx
jz .free_edi
push edi
call free
mov eax, ebx
jmp .addcursor
 
.not_cursor:
dec ebx
jnz not_supported_i40_fn
mov eax, [ebp+tls.scroll]
cdq
mov ecx, 120 ; WHEEL_DELTA
idiv ecx
mov [ebp+tls.scroll], edx
movzx eax, ax
mov [esp+20h], eax
ret
 
.aks:
push dword [esp+4]
call [GetAsyncKeyState]
cmp ah, 80h
cmc
adc ebx, ebx
ret 4
 
read_9x_mouse_buttons:
call [jmp_temp_int33]
movzx eax, bl
mov [esp+20h], eax
ret
 
use16
temp_code:
mov eax, esp
mov ss, [temp_ss]
mov sp, temp_stack_size
push eax
 
mov ax, 3
int 33h
 
pop eax
push ds
pop ss
mov esp, eax
db 66h
retf
 
temp_code_int1A:
mov esi, esp
mov ss, [temp_ss]
mov sp, temp_stack_size
push esi
 
int 1Ah
 
pop esi
push ds
pop ss
mov esp, esi
db 66h
retf
 
temp_code_size = $ - temp_code
use32
 
i40_draw_line:
push edx
mov esi, ecx
mov eax, edx
call convert_color
push eax
push eax
push 1
push 0
call [CreatePen]
push eax
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
push edi
call [SelectObject]
push eax
push 0
test byte [esp+12+3], 0x01
jz @f
push 6 ; R2_NOT
push edi
call [SetROP2]
mov [esp], eax
@@:
push 0
mov eax, esi
shr eax, 16
add eax, [ebp+tls.client_top]
push eax
mov eax, ebx
shr eax, 16
add eax, [ebp+tls.client_left]
push eax
push edi
call [MoveToEx]
movzx esi, si
add esi, [ebp+tls.client_top]
push esi
movzx ebx, bx
add ebx, [ebp+tls.client_left]
push ebx
push edi
call [LineTo]
pop eax
test byte [esp+8+3], 0x01
jz @f
push eax
push edi
call [SetROP2]
push esi
push ebx
push edi
call [GetPixel]
xor eax, 0xFFFFFF
mov [esp+4], eax
@@:
pop eax
pop ecx
push eax
push ecx
push esi
push ebx
push edi
call [SetPixel]
push edi
call [SelectObject]
push eax
call [DeleteObject]
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
pop edx
ret
 
i40_get_background:
pushad
push 0
call init_background
popad
mov eax, [bgr_section]
dec ebx
jz .1
dec ebx
jz .2
dec ebx
dec ebx
jnz not_supported_i40_fn
test eax, eax
mov ecx, 2
jz @f
mov ecx, [eax+8]
@@:
mov [esp+20h], ecx
ret
.1:
test eax, eax
jz @f
mov ecx, [eax]
shl ecx, 16
mov cx, [eax+4]
jmp @b
@@:
call get_screen_size
add ebx, 10001h
@@:
mov [esp+20h], ebx
.ret:
ret
.2:
; cmp ecx, 0x160000-16
; jae .ret
xor ebx, ebx
test eax, eax
jz @b
mov ebx, [eax+ecx+10h]
and ebx, 0x00FFFFFF
jmp @b
 
i40_set_event_mask:
test ebx, not 1F7h
jnz not_supported_i40_fn
mov [ebp+tls.message_mask], ebx
ret
 
i40_reserve_free_ports:
cmp ebx, 1
ja not_supported_i40_fn
cmp edx, 0xFFFF
ja .inv_range
cmp ecx, edx
jbe .range_ok
.inv_range:
push 30h
push aWarning
push PortsRangeErr
push 0
call [MessageBoxA]
mov dword [esp+20h], 1
ret
.range_ok:
call acquire_shared
mov esi, [shared_data]
mov eax, ecx
test ebx, ebx
jnz .free
; reserve ports
@@:
mov edi, PortsNotEnabledErr
bt dword [esi+shared_data_struc.DisabledPorts], eax
jc .err_release
mov edi, PortsUsedErr
bt dword [esi+shared_data_struc.UsedIoMap], eax
jnc .err_release
inc eax
cmp eax, edx
jbe @b
mov eax, ecx
@@:
btr dword [esi+shared_data_struc.UsedIoMap], eax
inc eax
cmp eax, edx
jbe @b
jmp .update_iomap
.free:
mov edi, PortsNotUsedErr
bt dword [esi+shared_data_struc.UsedIoMap], eax
jc .err_release
inc eax
cmp eax, edx
jbe .free
mov eax, ecx
@@:
bts dword [esi+shared_data_struc.UsedIoMap], eax
inc eax
cmp eax, edx
jbe @b
.update_iomap:
cmp [bIs9x], 0
jz .nt
call release_shared
and dword [esp+20h], 0
ret
.nt:
mov eax, [shared_data]
push 0
push 0
add eax, shared_data_struc.UsedIoMap
push 2000h
push eax
push 0x22203C
call send_driver_request
mov edi, DrvOpenErr
jnz @f
.err_release:
call release_shared
push 30h
push aWarning
push edi
push 0
call [MessageBoxA]
mov dword [esp+20h], 1
ret
@@:
call release_shared
; push 0
; call [Sleep] ; force task switch
and dword [esp+20h], 0
ret
 
i40_display_number:
cmp bl, 1
ja not_supported_i40_fn
push ebx esi
and ebx, not 0xC0000000
xor esi, esi
cmp bl, 1
jb .noptr
mov eax, [base]
test byte [esp+7], 0x40
jz @f
mov esi, [eax+ecx+4]
@@:
mov ecx, [eax+ecx]
.noptr:
mov eax, 10
cmp bh, 1
jb @f
mov eax, 16
jz @f
mov eax, 2
@@:
shr ebx, 16
cmp ebx, 64
jbe @f
pop esi ebx
jmp not_supported_i40_fn
@@:
push edi
mov edi, esp
sub esp, 64
dec edi
std
push edx
push ebx
xchg eax, ecx
test ebx, ebx
jz .done
.digit:
xor edx, edx
test esi, esi
jz .dig0
push eax
mov eax, esi
div ecx
pop esi
xchg eax, esi
.dig0:
div ecx
xchg eax, edx
cmp al, 10
sbb al, 69h
das
stosb
xchg eax, edx
dec ebx
jnz .digit
.done:
cld
mov edx, edi
inc edx
pop esi
pop ebx
lea edi, [esp+40h]
test byte [esp+48h+3], 80h
jz .okleadzero
@@:
cmp byte [edx], '0'
jnz .okleadzero
inc edx
dec esi
cmp edx, edi
jb @b
dec edx
inc esi
mov byte [edx], '0'
.okleadzero:
mov ecx, [edi+4]
and ecx, not 0x80000000
mov edi, [edi]
call i40_writetext_l1
add esp, 4Ch
ret
 
i40_display_settings:
dec ebx
jnz @f
set_button_style:
div edx
ret
@@:
dec ebx
jnz @f
add ecx, [base]
set_wnd_colors:
div edx
ret
@@:
dec ebx
jnz @f
add ecx, [base]
get_wnd_colors:
div edx
ret
@@:
dec ebx
jnz @f
mov eax, [_skinh]
mov [esp+20h], eax
ret
@@:
dec ebx
jnz @f
call acquire_shared
mov eax, [shared_data]
mov ecx, [eax+shared_data_struc.workarea_right]
mov [esp+20h], ecx
mov ecx, [eax+shared_data_struc.workarea_left]
mov [esp+22h], cx
mov ecx, [eax+shared_data_struc.workarea_bottom]
mov [esp+14h], ecx
mov ecx, [eax+shared_data_struc.workarea_top]
mov [esp+16h], cx
call release_shared
ret
@@:
dec ebx
jnz @f
call acquire_shared
mov eax, [shared_data]
mov bx, cx
mov [eax+shared_data_struc.workarea_right], ebx
shr ecx, 10h
mov [eax+shared_data_struc.workarea_left], ecx
mov bx, dx
mov [eax+shared_data_struc.workarea_bottom], ebx
shr edx, 10h
mov [eax+shared_data_struc.workarea_top], edx
call release_shared
ret
@@:
dec ebx
jnz not_supported_i40_fn
mov eax, dword [margins]
mov [esp+20h], eax
mov eax, dword [margins+4]
mov [esp+14h], eax
ret
 
i40_set_window_shape:
test ebx, ebx
jnz @f
mov [ebp+tls.lpShapeData], ecx
jmp .common
@@: dec ebx
jnz not_supported_i40_fn
inc ebx
shl ebx, cl
mov [ebp+tls.scale], ebx
.common:
cmp [ebp+tls.showwnd], 0
jz .done
call set_window_shape
.done: ret
 
set_window_shape:
mov esi, [ebp+tls.lpShapeData]
add esi, [base]
movzx ebx, [ebp+tls.y_size]
mov eax, ebx
inc eax
inc eax
shl eax, 4
push eax
call malloc
push eax
xchg eax, edi
push 20h
pop eax
stosd ; RGNDATAHEADER.dwSize
push 1
pop eax
stosd ; .iType
xor eax, eax
stosd ; .nCount
stosd ; .nRgnSize
stosd ; RGNDATAHEADER.rcBound.left
stosd ; .top
movzx eax, [ebp+tls.x_size]
stosd ; .right
movzx eax, [ebp+tls.y_size]
stosd ; .bottom
xor edx, edx ; edx=number of rects, ebp=allocated number of rects
xor ecx, ecx
.yloop:
push ecx
xor ecx, ecx
.1:
lodsb
cmp al, 0
jnz .2
add ecx, [ebp+tls.scale]
cmp cx, [ebp+tls.x_size]
jae .3
jmp .1
.2:
inc edx
cmp edx, ebx
ja .realloc_rects
.realloc_cont:
mov [edi], ecx
pop eax
mov [edi+4], eax
push eax
add eax, [ebp+tls.scale]
mov [edi+12], eax
add ecx, [ebp+tls.scale]
.4:
lodsb
cmp al, 0
jz .5
add ecx, [ebp+tls.scale]
cmp cx, [ebp+tls.x_size]
jb .4
.5:
mov [edi+8], ecx
add edi, 10h
add ecx, [ebp+tls.scale]
cmp cx, [ebp+tls.x_size]
jb .1
.3:
pop ecx
add ecx, [ebp+tls.scale]
cmp cx, [ebp+tls.y_size]
jb .yloop
pop edi
mov [edi+8], edx
push edi
inc edx
inc edx
shl edx, 4
push edx
push 0
call [ExtCreateRegion]
push 1
push eax
push [ebp+tls.hWnd]
call [SetWindowRgn]
push edi
call free
ret
 
.realloc_rects:
push ecx
push edx
add ebx, ebx ; multiply size by 2
mov eax, ebx
inc eax
inc eax
shl eax, 4
push eax
push dword [esp+10h]
push 0
push [hHeap]
call [HeapReAlloc]
sub edi, [esp+0xC]
add edi, eax
mov [esp+0xC], eax
pop edx
pop ecx
jmp .realloc_cont
 
i40_create_thread:
dec ebx
jnz not_supported_i40_fn
push ecx
push edx
push 16
call malloc
xchg eax, ebx
pop dword [ebx+4] ; esp
pop dword [ebx] ; eip
push 0
push 0
push 0
push 0
call [CreateEventA]
mov [ebx+8], eax
mov eax, [ebp+tls.cur_dir]
mov [ebx+12], eax
push eax
push esp
push 0
push ebx
push KolibriThreadProc
push 10000h
push 0
call [CreateThread]
pop ecx
test eax, eax
jnz @f
or dword [esp+20h], -1
ret
@@:
push eax
call [CloseHandle]
push -1
push dword [ebx+8]
call [WaitForSingleObject]
push dword [ebx+8]
call [CloseHandle]
mov esi, [ebx]
push ebx
call free
; esi = slot; get PID
call acquire_shared
xchg eax, esi
call get_slot_ptr
mov eax, [edi]
mov dword [esp+20h], eax
push edi
call get_cur_slot_ptr
lea esi, [edi+24]
pop edi
add edi, 24
movsd
movsd
movsd
movsd
call release_shared
ret
 
KolibriThreadProc:
mov ebp, [tls_index]
mov eax, [fs:2Ch]
mov ebp, [eax+ebp*4]
mov ebx, [esp+4]
mov ecx, [ebx]
mov edx, [ebx+4]
mov [ebp+tls._cs], cs
mov [ebp+tls._ds], ds
mov [ebp+tls._fs], fs
mov [ebp+tls._esp], edx
mov [ebp+tls._eip], ecx
mov esi, [ebx+12]
push esi
call [lstrlenA]
inc eax
push eax
push eax
call malloc
pop ecx
mov [ebp+tls.cur_dir], eax
mov edi, eax
rep movsb
lock inc [NumThreads]
call acquire_shared
server_new_thread:
div edx
call release_shared
mov [ebp+tls.cur_slot], ecx
mov [ebx], ecx
push dword [ebx+8]
call [SetEvent]
xor ebx, ebx
push ebx
push 400000h
push ebx
push ebx
mov eax, 80000000h
push eax
push eax
push eax
push eax
push eax
push [process_name]
push classname
push ebx
call [CreateWindowExA]
mov [ebp+tls.hWnd], eax
mov [ebp+tls.bActive], 1
mov [ebp+tls.bFirstMouseMove], 1
call acquire_shared
call get_cur_slot_ptr
mov [edi+shared_data_struc.hWnd-shared_data_struc.threads], eax
call release_shared
xor eax, eax
xor ecx, ecx
xor edx, edx
xor esi, esi
xor edi, edi
push 202h
pushad
and dword [esp+8], 0
jmp i40_done
 
; initialize_winsock:
; push ecx edx
; cmp [WinSockDLL], -1
; jz .failed_ret
; cmp [WinSockDLL], 0
; jnz .ok
; push winsock_name
; call [LoadLibraryA]
; mov [WinSockDLL], eax
; test eax, eax
; jz .failed
; push esi
; mov esi, winsock_imports
; .import:
; lodsd
; test eax, eax
; jz .importok
; push eax
; push [WinSockDLL]
; call [GetProcAddress]
; mov [esi-4], eax
; test eax, eax
; jnz .import
; pop esi
; jmp .failed
; .importok:
; sub esp, 190h
; push esp
; push 101h
; call [WSAStartup]
; add esp, 190h
; test eax, eax
; jz .ok
; .failed:
; or [WinSockDLL], -1
; push 10h
; push 0
; push aWinsockInitErr
; push 0
; call [MessageBoxA]
; .failed_ret:
; stc
; .ok:
; pop edx ecx
; ret
 
; i40_socket:
; call initialize_winsock
; jnc @f
; or dword [esp+20h], -1
; ret
; @@:
; cmp ebx, 9
; jnz not_supported_i40_fn
; .is_localport_unused:
; mov esi, ecx
; ; destroy old tcp socket
; mov eax, [ebp+tls.cursocket]
; test eax, eax
; jz @f
; dec eax
; push eax
; call [closesocket]
; @@:
; xor ebx, ebx
; mov [ebp+tls.curport], bx
; ; create new tcp socket
; push ebx ; protocol - unspecified
; push 1 ; SOCK_STREAM aka TCP
; push 2 ; AF_INET
; call [socket]
; inc eax
; mov [ebp+tls.cursocket], eax
; jnz @f
; push 10h
; push ebx
; push aSocketErr
; push ebx
; call [MessageBoxA]
; mov dword [esp+20h], ebx
; ret
; @@:
; push ebx
; push ebx ; sockaddr_in.sin_zero
; push 0x0100007F ; sockaddr_in.sin_addr = 127.0.0.1
; shl esi, 16
; inc esi
; inc esi ; sockaddr_in.sin_family = 2 = AF_INET
; push esi ; sockaddr_in.sin_port
; mov ecx, esp
; push 10h ; namelen
; push ecx ; name
; dec eax
; push eax ; s
; call [bind]
 
i40_sound_interface:
cmp ebx, 55
jnz not_supported_i40_fn
mov eax, [shared_data]
cmp [eax+shared_data_struc.sound_flag], 0
jz @f
ret
@@:
; prepare wave-block
push 800h
call malloc
push eax
lea ebx, [eax+800h]
xchg eax, edi
push esi
mov esi, wave_block_begin
mov ecx, wbb_size/4
rep movsd
stosd
pop esi
add esi, [base]
.mainloop:
lodsb
test al, al
jz .done
cmp al, 81h
jae .note
movzx edx, al
xor eax, eax
lodsw
jmp .doit
.note:
sub al, 81h
movzx edx, al
lodsb
cmp al, 0xFF
jz .pause
mov cl, al
and eax, 0xF
movzx eax, word [kontrOctave+eax+eax]
shr cl, 4
shr eax, cl
.doit:
; eax=divider (freq=1193180/divider), edx=time (in 1/100 sec)
mov ecx, edx
mul [wave_r]
div [_1193180]
push eax
mov eax, ecx
mul [wave_r]
div [_100]
mov ecx, eax
pop edx
.doit2:
; ecx=number of bytes required for this note
lea eax, [edi+ecx]
cmp eax, ebx
ja .realloc
; mov al, 0xFF
; cmp edx, ecx
; jbe @f
; mov al, 0 ; this is for pause
;@@:
mov al, 80h
; if edx is zero, make it 1
cmp edx, 1
adc edx, 0
.writeloop:
push ecx
cmp ecx, edx
jb @f
mov ecx, edx
@@: rep stosb
pop ecx
xor al, [sound_vol]
sub ecx, edx
ja .writeloop
jmp .mainloop
.pause:
mov eax, edx
mul [wave_r]
div [_100]
mov ecx, eax
mov edx, eax
inc edx
jmp .doit2
.realloc:
pop eax
sub ebx, eax
add ebx, ebx ; ebx=new size
sub edi, eax ; edi=delta
push ecx edx
push ebx
push eax
push 0
push [hHeap]
call [HeapReAlloc]
pop edx ecx
push eax
add ebx, eax
add edi, eax
jmp .doit2
.done:
pop ebx
sub edi, ebx
sub edi, 8
mov [ebx+4], edi
sub edi, 24h
mov [ebx+28h], edi
; because we use asynchronous call of PlaySoundA, we can not free used memory,
; but we can free previous wave-block
push 0
push 0
push 0
call [PlaySoundA] ; force previous sound terminate
push 5 ; SND_ASYNC|SND_MEMORY
push 0
push ebx
call [PlaySoundA]
xchg ebx, [ebp+tls.prev_snd_block]
test ebx, ebx
jz @f
push ebx
call free
@@:
and dword [esp+20h], 0
ret
 
i40_file_system:
add ebx, [base]
lea esi, [ebx+0x14]
cmp dword [ebx], 0
jnz not_supported_i40_fn
emul_read_file:
; read 0 bytes - OK
cmp dword [ebx+8], 0
jnz @f
and dword [esp+20h], 0
ret
@@:
; check for root dir
cmp byte [esi], 0
jz .root
cmp byte [esi+1], 0
jnz .noroot
.root:
mov esi, dir0
mov edi, [ebx+12]
add edi, [base]
mov ecx, 12
push ecx
rep movsb
add edi, 32-12
pop ecx
rep movsb
and dword [esp+20h], 0 ; eax=0: read ok
mov dword [esp+14h], 64 ; ebx=size
ret
.noroot:
sub esp, 200h
call convert_path
jc emul_path_err
dec eax
jz .ramdisk
sub al, 3
jae .harddisk
add esp, 200h
jmp not_supported_i40_fn
.ramdisk:
lodsb
cmp al, 0
jz .give_dir1
; must be {/RD | /RAMDISK}{/1 | /FIRST}/...
lodsw
cmp ax, '1\'
jz .ramdisk_ok
cmp ax, '1'
jz .ramdisk_readdir
cmp ax, 'FI'
jnz emul_path_err
lodsd
cmp eax, 'RST\'
jz .ramdisk_ok
cmp eax, 'RST'
jnz emul_path_err
.ramdisk_readdir:
add esp, 200h
mov esi, ramdisk_path
push 0 ; read /rd/1
call read_directory
mov [esp+20h], eax
mov [esp+14h], ebx
ret
.ramdisk_ok:
; now esi points to filename, relative from ramdisk
sub esp, 200h
mov edi, esp
push ramdisk_path
.doit1:
push edi
call [lstrcpyA]
cmp byte [esi], 0
setz al
push eax
push esi
push edi
call [lstrcatA]
pop eax
lea esi, [esp+200h]
xchg esi, edi
mov ecx, 200h/4
rep movsd
add esp, 200h
mov esi, esp
; now esi contains full Win32 name of requested file
push eax
push esi
call [GetFileAttributesA]
inc eax
pop ecx
jz emul_filenotfound
dec eax
test al, 10h ; FILE_ATTRIBUTE_DIRECTORY
jnz .read_dir
push 0
push 0
push 3
push 0
push 1
push 80000000h
push esi
call [CreateFileA]
inc eax
jz emul_filenotfound
dec eax
xchg eax, esi
mov eax, [ebx+4]
xor edx, edx
shld edx, eax, 9
shl eax, 9
push edx
mov edi, esp
push 0
push edi
push eax
push esi
call [SetFilePointer]
push 0
push edi
mov eax, [ebx+8]
shl eax, 9
; check limits
mov ecx, [limit]
inc ecx
sub ecx, [ebx+0xC]
cmp eax, ecx
jbe @f
mov eax, ecx
@@: push eax
mov eax, [ebx+0xC]
add eax, [base]
push eax
push esi
call [ReadFile]
pop eax
push 0
push esi
call [GetFileSize]
add esp, 200h
mov [esp+14h], eax
push esi
call [CloseHandle]
and dword [esp+20h], 0
ret
.read_dir:
inc ecx
push ecx ; 2 for exclude '..', 1 for all
call read_directory
add esp, 200h
mov [esp+20h], eax
mov [esp+14h], ebx
ret
.harddisk:
movzx edx, al
lodsb
test al, al
jnz @f
add esp, 200h
mov dword [esp+20h], 10 ; access denied
ret
@@:
xor ecx, ecx ; partition
@@:
lodsb
cmp al, '\'
jz @f
cmp al, 0
jz @f
sub al, '0'
cmp al, 9
ja emul_path_err
imul ecx, 10
add cl, al
jmp @b
@@:
test al, al
jnz @f
dec esi
@@:
test ecx, ecx
jz emul_path_err
cmp ecx, [hd_partitions_num+edx*4]
jbe @f
add esp, 200h
mov dword [esp+20h], 4 ; partition not defined
ret
@@:
sub esp, 200h
mov edi, esp
mov eax, [hd_partitions_array+edx*4]
dec ecx
shl ecx, 9
add eax, ecx
push eax
jmp .doit1
.give_dir1:
add esp, 200h
mov esi, dir1
mov edi, [ebx+12]
add edi, [base]
mov ecx, 12
push ecx
rep movsb
and dword [esp+20h], 0 ; eax=0: read ok
mov dword [esp+14h], 32 ; ebx=size
ret
 
emul_path_err:
push 0
push aWarning
push aPathIsInvalid
push 0
call [MessageBoxA]
emul_filenotfound:
add esp, 200h
mov dword [esp+20h], 5 ; file not found
cmp dword [ebx], 10h
jnz @f
neg dword [esp+20h]
@@: ret
 
aWarning db 'Warning',0
aPathIsInvalid db 'Requested path is invalid',0
 
convert_path:
lea edi, [esp+4]
push ebx
lea ebx, [edi + 511]
.1:
lodsb
cmp al, '/'
jz .1
dec esi
mov ecx, 11
sub ebx, ecx
cmp edi, ebx
ja .5
mov edx, edi
mov al, ' '
add ebx, ecx
rep stosb
mov edi, edx
.2:
lodsb
cmp al, '/'
jz .3
cmp al, '.'
jz .4
cmp al, 0
jz .3
cmp edi, ebx
jae .5
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, ' '
@@: stosb
jmp .2
.4:
lea edi, [edx+8]
jmp .2
.3:
lea edi, [edx+7]
mov ecx, 8
std
mov al, ' '
repz scasb
cld
jz .5
mov ecx, [edx+8]
mov [edi+3], ecx
mov byte [edi+2], '.'
add edi, 5
mov ecx, 3
std
repz scasb
cld
jz @f
inc edi
inc edi
@@:
mov al, '\'
stosb
cmp byte [esi-1], 0
jnz .1
mov byte [edi-1], 0
mov esi, path_begin
xor eax, eax
xor ecx, ecx
.6:
add esi, ecx
lodsb
test al, al
jz .5
xchg eax, ecx
lodsb
xchg ecx, eax
lea edi, [esp+8]
repz cmpsb
jnz .6
cmp byte [edi], 0
jz .7
cmp byte [edi], '\'
jnz .6
.7:
mov esi, edi
pop ebx
push eax
push esi
push esi
call [OemToCharA]
pop eax
; convert /hd to /hdx
cmp al, 3
jnz @f
mov eax, [shared_data]
movzx eax, [eax+shared_data_struc.hd_base]
add eax, 3
@@:
clc
ret
.5:
stc
pop ebx
ret
 
read_directory:
; in: ebx->fileinfo block, esi->mask
; byte [esp+4] = 0 for /rd/1, 1 for normal call, 2 for exclude '..'
; out: eax,ebx according to kernel fn58 read /rd/1
 
; note that all returned values have been taken from kernel code
 
mov ecx, [ebx+8] ; number of blocks
mov edi, [ebx+12] ; output memory
add edi, [base]
mov ebx, [ebx+4] ; start block
; /rd/1 = 14 clusters
cmp byte [esp+4], 0
jnz .ok2
cmp ebx, 14 ; 14 clusters = root dir
jae .err1
cmp ecx, 14
jbe .ok1
.err1:
mov eax, 5 ; out of range
or ebx, -1
ret 4
.ok1:
lea edx, [ebx+ecx]
cmp edx, 14
pushfd
jbe @f
sub edx, 14
sub ecx, edx
jz .doret2
@@:
popfd
.ok2:
pushfd
shl ebx, 9
shl ecx, 9
xor edx, edx
sub esp, 200h
pushad
lea edi, [esp+20h]
push esi
call [lstrlenA]
mov ecx, eax
rep movsb
mov al, '\'
cmp [edi-1], al
jz @f
stosb
@@:
mov eax, '*.*'
stosd
popad
push 0
sub esp, 400h
.loop:
mov esi, esp
push ecx
lea eax, [esi+404h]
call get_next_file
; if no file => zero record
test eax, eax
jnz .still
push edi
mov edi, esi
mov ecx, 0x20/4
rep stosd
pop edi
mov al, 0x20
add [esi+400h], eax
.still:
pop ecx
cmp byte [esp+60Ch], 1
jz @f
cmp word [esi], '..'
jz .loop
@@:
push ecx
cmp ebx, eax
jae .skip
add esi, ebx
mov ecx, eax
sub ecx, ebx
cmp ecx, [esp]
jb @f
mov ecx, [esp]
@@:
sub [esp], ecx
rep movsb
.skip:
sub ebx, eax
jae @f
xor ebx, ebx
@@:
pop ecx
test ecx, ecx
jnz .loop
call done_find_file
.doret:
add esp, 400h
pop ecx
add esp, 200h
.doret2:
xor ebx, ebx
xor eax, eax
cmp byte [esp+8], 0
jz .check_rd1
popfd
; cmp edx, -1
; jz .eof
cmp ecx, 0x200
jae .eof
jmp .ret
.check_rd1:
popfd
jb .ret
.eof:
mov al, 6 ; EOF
.ret: ret 4
 
get_next_file:
; in: eax=mask, edx=hFindData, edx=0 or edx=-1, esi->buffer
; out: buffer filled, eax=length
cmp edx, -1
jnz @f
xor eax, eax
ret
@@:
sub esp, 0x140 ; sizeof(WIN32_FIND_DATA)
pushad
lea ecx, [esp+0x20]
push ecx
test edx, edx
jnz .inited
push eax
call [FindFirstFileA]
mov edx, eax
mov [esp+0x14], edx
inc eax
jmp .cmn
.inited:
push edx
call [FindNextFileA]
mov edx, [esp+0x14]
.cmn:
test eax, eax
jnz .ok
cmp edx, -1
jz @f
push edx
call [FindClose]
@@:
popad
add esp, 0x140
xor eax, eax
or edx, -1
ret
.ok:
popad
; Long File Names are not supported yet
; file name
push edi
lea edi, [esp+4+0x130] ; WIN32_FIND_DATA.cAlternateFileName
cmp byte [edi], 0
jnz .shortname
push esi
lea esi, [esp+8+0x2C] ; WIN32_FIND_DATA.cFileName
push edi
.l2s:
lodsb
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
sub al, 0x20
@@: stosb
cmp al, 0
jnz .l2s
pop edi esi
.shortname:
pushad
push edi
push edi
call [CharToOemA]
popad
; file name
mov ecx, 10
@@:
mov byte [esi+ecx], ' '
dec ecx
jns @b
inc ecx
@@:
cmp byte [edi], '.'
jnz @f
inc edi
mov byte [esi+ecx], '.'
inc ecx
jmp @b
@@:
mov al, [edi]
inc edi
cmp al, 0
jz .namedone
cmp al, '.'
jz .dot
mov [esi+ecx], al
inc ecx
jmp @b
.dot:
mov cl, 8
jmp @b
.namedone:
pop edi
; attributes
mov eax, [esp] ; WIN32_FIND_DATA.dwFileAttributes
and al, 0x3F
mov [esi+11], al
and word [esi+12], 0
; creation file and date
pushad
lea eax, [esi+14]
push eax
inc eax
inc eax
push eax
lea eax, [esp+8+20h+4]
push eax
call [FileTimeToDosDateTime]
; last access date
lea eax, [esp+1Ch]
push eax
lea eax, [esi+18]
push eax
lea eax, [esp+8+20h+0xC]
push eax
call [FileTimeToDosDateTime]
; high word of cluster
and word [esi+20], 0
; last write file and date
lea eax, [esi+22]
push eax
inc eax
inc eax
push eax
lea eax, [esp+8+20h+0x14]
push eax
call [FileTimeToDosDateTime]
; low word of cluster
mov word [esi+26], 0xBAD ; random value
; file size
popad
mov eax, [esp+0x20]
mov [esi+28], eax
; return
add esp, 0x140
mov eax, 0x20
ret
 
done_find_file:
test edx, edx
jz .ret
cmp edx, -1
jz .ret
push edx
push edx
call [FindClose]
pop edx
.ret: ret
 
notify_run_prg:
test esi, esi
jz @f
add esi, [base]
@@:
call acquire_shared
push eax esi edi
mov esi, [ebp+tls.cur_dir]
mov edi, process_curdir
@@:
lodsb
stosb
test al, al
jz @f
cmp edi, process_curdir+4096
jb @b
mov byte [edi-1], 0
@@:
pop edi esi eax
server_run_prg:
div edx
call release_shared
push ecx
push -1
push ecx
call [WaitForSingleObject]
call [CloseHandle]
server_get_run_result:
div edx
jecxz .ret
push eax ecx edx
push 24
call malloc
mov [eax+16], esi
mov [eax+20], edi
mov esi, [ebp + tls.debuggees]
mov [eax], esi
mov [ebp + tls.debuggees], eax
pop dword [eax+12]
pop dword [eax+8]
pop dword [eax+4]
mov eax, [eax+4]
.ret:
ret
 
i40_ipc:
dec ebx
jnz @f
; set IPC memory
call acquire_shared
call get_cur_slot_ptr
add ecx, [base]
mov [edi+4], ecx
mov [edi+8], edx
call release_shared
and dword [esp+20h], 0
ret
@@:
dec ebx
jnz not_supported_i40_fn
add edx, [base]
call acquire_shared
server_send_ipc:
div edx
call release_shared
test eax, eax
jnz @f
push 0
push 0
push 400h ; WM_USER
push ecx
call [PostMessageA]
xor eax, eax
@@:
mov [esp+20h], eax
ret
 
i40_direct_scr_access:
cmp [ColorDepth], 0
jnz @f
push 10h
push 0
push DSADisabled
push 0
call [MessageBoxA]
jmp i40_terminate
@@:
dec ebx
jz .1
dec ebx
jz .2
dec ebx
jz .3
jmp not_supported_i40_fn
.1:
call get_screen_size
add ebx, 10001h
mov [esp+20h], ebx
ret
.2:
mov eax, [ColorDepth]
mov [esp+20h], eax
ret
.3:
call get_screen_size
shr ebx, 16
lea eax, [ebx+1]
mul [ColorDepth]
shr eax, 3
add eax, 3
and eax, not 3
mov [esp+20h], eax
ret
 
i40_pci:
mov eax, [shared_data]
cmp [eax+shared_data_struc.pci_access_enabled], 0
jnz @f
.reterr:
or dword [esp+20h], -1 ; PCI access disabled
ret
@@:
cmp bl, 2
ja .noinit
cmp [eax+shared_data_struc.pci_data_init], 0
jnz @f
push eax ebx
call pci_data_init
pop ebx eax
@@:
test bl, bl
jnz .not0
xor ecx, ecx
cmp [eax+shared_data_struc.pci_data_init], 1
jnz .unsupp0 ; emulate "unsupported" behavior
mov ch, [eax+shared_data_struc.pci_bios_mj]
mov cl, [eax+shared_data_struc.pci_bios_mn]
.unsupp0:
mov [esp+20h], ecx
ret
.not0:
dec bl
mov ecx, ebx
jnz .not1
cmp [eax+shared_data_struc.pci_data_init], 1
jnz .unsupp1
mov cl, [eax+shared_data_struc.pci_bios_lb]
.unsupp1:
.retecx:
mov [esp+20h], ecx
ret
.not1:
test [eax+shared_data_struc.pci_bios_pc], 1
jnz @b
test [eax+shared_data_struc.pci_bios_pc], 2
jz @b
inc ecx
jmp @b
.noinit:
sub bl, 4
cmp bl, 2
ja not_supported_i40_fn
cmp [bIs9x], 0
jz .read_nt
mov ah, 0xB1
mov al, bl
add al, 8
mov bl, ch
movzx di, cl
mov ecx, ebx
call [jmp_temp_int1A]
jc .reterr
jmp .retecx
.read_nt:
push cx
push bx
mov eax, esp
push ecx
mov ecx, esp
push 4
push ecx
push 4
push eax
push 0x222004
call send_driver_request
pop ecx edx
test eax, eax
jnz .retecx
push 30h
push aWarning
push DrvOpenErr
push 0
call [MessageBoxA]
jmp .reterr
 
pci_data_init:
call acquire_shared
cmp [bIs9x], 0
jz .nt
; On 9x systems, just do "int 1Ah" from 16-bit code
mov ax, 0xB101
call [jmp_temp_int1A]
test ah, ah
jnz .err
cmp edx, 'PCI '
jnz .err
mov edx, [shared_data]
mov [edx+shared_data_struc.pci_bios_mj], bh
mov [edx+shared_data_struc.pci_bios_mn], bl
mov [edx+shared_data_struc.pci_bios_lb], cl
mov [edx+shared_data_struc.pci_bios_pc], al
mov [edx+shared_data_struc.pci_data_init], 1
jmp .ok
.nt:
; On NT systems, there is 'HKLM\HARDWARE\DESCRIPTION\System\MultifunctionAdapter' key,
; with some subkeys '0','1',..., which hold information on periphery.
; Each PCI bus has its own subkey with 'Identifier'="PCI".
; For first PCI bus 'Configuration Data' holds 4 additional bytes = info on PCI BIOS.
.loop:
push eax
push esp ; phkResult
push 1 ; samDesired = KEY_QUERY_VALUE
push 0 ; ulOptions
push keymfa ; lpSubKey
push 80000002h ; hKey = HKEY_LOCAL_MACHINE
call [RegOpenKeyExA]
pop esi ; key handle
test eax, eax
jnz .err ; subkeys are done, and we do not find required
push eax
mov eax, esp
push 4
push esp ; lpcbData
push eax ; lpData
push 0 ; lpType
push 0 ; lpReserved
push aIdentifier ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
pop ecx
pop edx
test eax, eax
jnz .cont
cmp ecx, 4
jnz .cont
cmp edx, 'PCI'
jnz .cont
sub esp, 24h
mov eax, esp
push 24h
push esp
push eax
push 0
push 0
push aConfigurationData
push esi
call [RegQueryValueExA]
pop ecx
test eax, eax
jnz .err3
cmp ecx, 24h
jnz .err3
mov eax, [shared_data]
add esp, 20h
pop dword [eax+shared_data_struc.pci_bios_mj]
dec [eax+shared_data_struc.pci_bios_lb]
js .err2
mov [eax+shared_data_struc.pci_data_init], 1
push esi
call [RegCloseKey]
.ok:
call release_shared
ret
.cont:
push esi
call [RegCloseKey]
inc [idxmfa]
cmp [idxmfa], '9'
jbe .loop
jmp .err
.err3:
add esp, 24h
.err2:
push esi
call [RegCloseKey]
.err:
mov eax, [shared_data]
mov [eax+shared_data_struc.pci_data_init], 2
call release_shared
push 40h
push 0
push aCannotGetPci
push 0
call [MessageBoxA]
ret
 
i40_debug_board:
dec ebx
jz .write
dec ebx
jnz not_supported_i40_fn
.read:
call acquire_shared
mov eax, [shared_data]
mov ecx, [eax+shared_data_struc.msg_board_count]
test ecx, ecx
jnz @f
mov [esp+20h], ecx ; zero eax
mov [esp+14h], ecx ; zero ebx
jmp .ret
@@:
dec [eax+shared_data_struc.msg_board_count]
lea edi, [eax+shared_data_struc.msg_board_data]
lea esi, [edi+1]
movzx edx, byte [edi]
mov [esp+20h], edx
mov dword [esp+14h], 1
dec ecx
rep movsb
.ret:
jmp release_shared
.write:
call acquire_shared
mov eax, [shared_data]
mov edx, [eax+shared_data_struc.msg_board_count]
mov [eax+shared_data_struc.msg_board_data+edx], cl
inc edx
and edx, 511
mov [eax+shared_data_struc.msg_board_count], edx
jmp .ret
 
i40_resize_app_memory:
dec ebx
jnz not_supported_i40_fn
cmp [heap_status], 0
jz @f
push 30h
push aWarning
push aInvFn64Call
push 0
call [MessageBoxA]
mov dword [esp+20h], 1
ret
@@:
cmp [NumThreads], 1
jnz not_supported_i40_fn
push ecx
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push ecx
push 0
call [VirtualAlloc]
pop ecx
test eax, eax
jnz .ok
mov dword [esp+0x20], 1
ret
.ok:
mov edi, eax
mov esi, [base]
push ecx
cmp ecx, [limit]
jbe @f
mov ecx, [limit]
inc ecx
@@:
push eax
rep movsb
call acquire_shared
call get_cur_slot_ptr
mov ecx, [edi+4]
jecxz @f
sub ecx, [base]
add ecx, [esp]
mov [edi+4], ecx
@@:
call release_shared
push 8000h ; MEM_RELEASE
push 0
push [base]
call [VirtualFree]
pop eax
pop ecx
mov [base], eax
dec ecx
mov [limit], ecx
mov [fn9limit], ecx
call get_cur_slot_ptr
mov [edi+24], ecx
mov esi, selector_data
mov [esi+2], ax
shr eax, 10h
mov [esi+4], al
mov [esi+7], ah
shr ecx, 0Ch
mov [esi], cx
shr ecx, 10h
or cl, 11000000b
mov [esi+6], cl
mov byte [esi+5], 11110010b
lea edi, [esi+8]
movsd
movsd
mov byte [esi+5], 11111010b
cmp [bIs9x], 0
jnz .9x
push dword [esi-4]
push dword [esi-8]
push 17h
push dword [esi+4]
push dword [esi]
push 0Fh
call [NtSetLdtEntries]
mov esi, ldterr
test eax, eax
js fail
.d: and dword [esp+20h], 0
ret
.9x:
mov eax, sl0p
call CallRing0
jmp .d
 
convert_2bpp:
mov esi, edi
add esi, [base]
movzx eax, word [esp]
pushad
add ecx, 7
shr ecx, 1
and ecx, not 3
mul ecx
push eax
call malloc
mov [esp+1Ch], eax
popad
push eax edx esi
mov edi, eax
movzx eax, word [esp+12]
mov esi, ebx
.extloop:
push eax
push ecx
.innloop:
lodsb
mov dl, al
push eax
shr al, 6
shr dl, 4
shl al, 4
and dl, 3
or al, dl
stosb
pop eax
mov dl, al
shl al, 2
and dl, 3
and al, 0x30
or al, dl
stosb
sub ecx, 4
ja .innloop
test edi, 3
jz @f
stosw
@@:
pop ecx
pop eax
add esi, [esp+16+0Ch]
dec eax
jnz .extloop
pop esi edx edi
jmp pad_cont8
 
pad_bmp8:
movzx eax, word [esp]
pushad
add ecx, 3
and ecx, not 3
mul ecx
push eax
call malloc
mov [esp+1Ch], eax
popad
push eax esi
mov edi, eax
movzx eax, word [esp+8]
mov esi, ebx
.extloop:
push eax
push ecx
mov eax, ecx
shr ecx, 2
rep movsd
mov ecx, eax
and ecx, 3
rep movsb
mov ecx, eax
neg ecx
and ecx, 3
mov al, 0
rep stosb
pop ecx
pop eax
add esi, [esp+4*3+0Ch]
dec eax
jnz .extloop
pop esi edi
jmp pad_cont8
 
i40_putimage_palette:
add ebx, [base]
push ecx
shr ecx, 16
cmp esi, 1
jz .1
cmp esi, 4
jz .4
cmp esi, 8
jz .8
cmp esi, 15
jz .15
cmp esi, 16
jz .16
cmp esi, 32
jz .32
cmp esi, 2
jz convert_2bpp
cmp esi, 24
jz .24
pop ecx
jmp not_supported_i40_fn
.24:
lea ecx, [ecx*3]
jmp @f
.1:
add ecx, 7
shr ecx, 3
jmp @f
.2:
add ecx, 3
shr ecx, 2
jmp @f
.4:
inc ecx
shr ecx, 1
jmp @f
.32:
add ecx, ecx
.15:
.16:
add ecx, ecx
.8:
@@:
add edi, [base]
mov esi, edi
; Windows requires that all scanlines are DWORD-padded
mov edi, ebx
test cl, 3
jnz pad_bmp8
cmp dword [esp+10h], 0
jnz pad_bmp8
pad_cont8:
pop ecx
mov eax, [esp+8]
; palette
sub esp, 256*4
push ecx edi
lea edi, [esp+8]
cmp al, 8
jnz @f
mov ecx, 256
rep movsd
@@:
cmp al, 4
jnz @f
mov ecx, 16
rep movsd
@@:
cmp al, 2
jnz @f
movsd
movsd
movsd
movsd
add eax, eax
@@:
cmp al, 1
jnz @f
movsd
movsd
@@:
cmp al, 16
jnz @f
mov dword [edi+0], 0xF800
mov dword [edi+4], 0x07E0
mov dword [edi+8], 0x001F
@@:
pop edi ecx
xor esi, esi
; BITMAPINFO
push esi ; biClrImportant
push esi ; biClrUsed
push esi ; biYPelsPerMeter
push esi ; biXPelsPerMeter
push esi ; biSizeImage
cmp al, 15
jnz .no15
push esi ; biCompression
push 100001h ; biPlanes, biBitCount
jmp @f
.no15:
cmp al, 16
jnz .no16
push 3 ; biCompression
push 100001h ; biPlanes, biBitCount
jmp @f
.no16:
push esi ; biCompression
; push 80001h ; biPlanes, biBitCount
shl eax, 16
inc eax
push eax ; biPlanes, biBitCount
@@:
movzx eax, cx
neg eax
push eax ; biHeight
neg eax
shr ecx, 10h
push ecx ; biWidth
push 40 ; biSize
push ebx
lea ebx, [esp+4]
; SetDIBitsToDevice
push esi ; fuColorUse = DIB_RGB_COLORS
push ebx ; lpbmi
push edi ; lpvBits
push eax ; cScanLines
dec eax
push eax ; uStartScan
push eax ; YSrc
inc eax
push esi ; XSrc
push eax ; dwHeight
push ecx ; dwWidth
movzx ecx, dx
add ecx, [ebp+tls.client_top]
push ecx ; YDest
shr edx, 10h
add edx, [ebp+tls.client_left]
push edx ; XDest
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, ebx
push ebx ; hdc
call [SetDIBitsToDevice]
xchg eax, ebx
pop ebx
add esp, 40+256*4
push eax
push [ebp+tls.hWnd]
call [ReleaseDC]
cmp edi, ebx
jz @f
push edi
call free
@@:
ret
 
i40_process_def:
dec ebx
jz .setmode
dec ebx
jz .getmode
dec ebx
jz .get_control
dec ebx
jz .add_hotkey
dec ebx
jz .del_hotkey
jmp not_supported_i40_fn
.setmode:
mov [ebp+tls.usescancode], cl
ret
.getmode:
movzx eax, [ebp+tls.usescancode]
mov [esp+20h], eax
ret
.get_control:
mov esi, .vkeycodes
mov edi, 1
.gcloop:
xor eax, eax
lodsb
push eax
call [GetAsyncKeyState]
test ax, ax
jns @f
or ebx, edi
@@:
add edi, edi
cmp esi, .vkeycodes_end
jb .gcloop
mov [esp+20h], ebx
ret
.add_hotkey:
.del_hotkey:
and dword [esp+20h], 0
ret
.vkeycodes:
db 0xA0 ; VK_LSHIFT
db 0xA1 ; VK_RSHIFT
db 0xA2 ; VK_LCONTROL
db 0xA3 ; VK_RCONTROL
db 0xA4 ; VK_LMENU
db 0xA5 ; VK_RMENU
db 0x14 ; VK_CAPITAL
db 0x90 ; VK_NUMLOCK
db 0x91 ; VK_SCROLL
.vkeycodes_end:
 
i40_move_resize:
cmp ebx, -1
jnz @f
movzx ebx, [ebp+tls.x_start]
@@: cmp ecx, -1
jnz @f
movzx ecx, [ebp+tls.y_start]
@@: cmp edx, -1
jnz @f
movzx edx, [ebp+tls.x_size]
dec edx
@@: cmp esi, -1
jnz @f
movzx esi, [ebp+tls.y_size]
dec esi
@@:
inc edx
mov [ebp+tls.x_start], bx
inc esi
mov [ebp+tls.y_start], cx
mov [ebp+tls.x_size], dx
mov [ebp+tls.y_size], si
push 1
push esi
push edx
push ecx
push ebx
push [ebp+tls.hWnd]
call [MoveWindow]
push 0
push 0
push [ebp+tls.hWnd]
call [InvalidateRect]
ret
 
i40_sys_services:
cmp ebx, 3
jnz .not3
mov esi, [shared_data]
cmp [esi+shared_data_struc.bAllowReadMSR], 0
mov edi, aReadMSRDisabled
jz .err
cmp [bIs9x], 0
jz .nt
mov ecx, edx
mov eax, rdmsrp
call CallRing0
test ebx, ebx
jnz .nomsr
mov [esp+20h], eax
mov [esp+14h], edx
ret
.nt:
push 0
push edx
push edx
mov eax, esp
push 9
push eax
push 4
push eax
push 0x222000
call send_driver_request
pop ecx
pop edx
pop esi
mov edi, DrvOpenErr
test eax, eax
jz .err
test esi, esi
jnz .nomsr
mov [esp+20h], ecx
mov [esp+14h], edx
ret
.err:
push 30h
push aWarning
push edi
push 0
call [MessageBoxA]
and dword [esp+20h], 0
and dword [esp+14h], 0
ret
.nomsr:
push 10h
push 0
push aNoMsr
push 0
call [MessageBoxA]
jmp i40_terminate
.not3:
cmp ebx, 11
jnz .not11
.initialize_heap:
; initialize heap
cmp [heap_status], 0
jz .create_heap
@@:
cmp [heap_status], 1
jnz @f
push 5
call [Sleep]
jmp @b
@@:
.heap_ret_size:
mov eax, 0x5FC00000-0x1000
sub eax, [heap_start]
mov [esp+20h], eax
ret
.create_heap:
cmp [NumThreads], 1
jnz not_supported_i40_fn
mov [heap_status], 1
xor ebx, ebx
; reserve needed big region
mov esi, 0x40000000
@@:
push 40h ; PAGE_EXECUTE_READWRITE
push 2000h ; MEM_RESERVE
push esi
push ebx
call [VirtualAlloc]
test eax, eax
jnz @f
shr esi, 1
cmp esi, 0x01000000
jae @b
.nomem_fatal:
xor ebx, ebx
mov esi, memerr
jmp fail
@@:
mov [heap_region_size], esi
push eax
mov ecx, [limit]
inc ecx
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push ecx
push eax
call [VirtualAlloc]
test eax, eax
jz .nomem_fatal
mov esi, [base]
pop edi
push edi
mov edi, eax
mov ecx, [limit]
inc ecx
rep movsb
push 8000h ; MEM_RELEASE
push ebx
push [base]
call [VirtualFree]
pop eax
mov [base], eax
mov ecx, [heap_region_size]
dec ecx
mov [limit], ecx
mov esi, selector_data
mov [esi+2], ax
shr eax, 10h
mov [esi+4], al
mov [esi+7], ah
shr ecx, 0Ch
mov [esi], cx
shr ecx, 10h
or cl, 11000000b
mov [esi+6], cl
mov byte [esi+5], 11110010b
lea edi, [esi+8]
movsd
movsd
mov byte [esi+5], 11111010b
cmp [bIs9x], bl
jnz .9x
push dword [esi-4]
push dword [esi-8]
push 17h
push dword [esi+4]
push dword [esi]
push 0Fh
call [NtSetLdtEntries]
mov esi, ldterr
test eax, eax
js fail
jmp .heap_created
.9x:
mov eax, sl0p
call CallRing0
xor ebx, ebx
.heap_created:
mov eax, [fn9limit]
or eax, 0xFFF
inc eax
mov [heap_start], eax
mov eax, [heap_region_size]
sub eax, [heap_start]
shr eax, 10
call malloc_big
mov [heap_control_block], eax
test eax, eax
jz .nomem_fatal
mov ecx, [heap_region_size]
sub ecx, [heap_start]
or ecx, 4
mov [eax], ecx
push heap_critical_sec
call [InitializeCriticalSection]
mov [heap_status], 2
jmp .heap_ret_size
.not11:
cmp ebx, 12
jnz .not12
; allocate memory block in heap
.allocate_heap:
cmp [heap_status], 0
jnz @f
push 30h
push aWarning
push aHeapNotInited
push 0
call [MessageBoxA]
and dword [esp+20h], 0
ret
@@:
lea edi, [ecx+0x1FFF]
and edi, not 0xFFF
@@:
cmp [heap_status], 1
jnz @f
push 5
call [Sleep]
jmp @b
@@:
push heap_critical_sec
call [EnterCriticalSection]
xor esi, esi
mov ecx, [heap_region_size]
sub ecx, [heap_start]
mov edx, [heap_control_block]
.l_0:
cmp esi, ecx
jae .m_exit
mov ebx, esi
shr ebx, 12
mov eax, [edx+ebx*4]
test al, 4
jz .test_used
and eax, not 0xFFF
cmp eax, edi
jb .m_next
jz @f
push esi
add esi, edi
sub eax, edi
or al, 4
shr esi, 12
mov [edx+esi*4], eax
pop esi
mov eax, edi
@@:
or al, 8
mov [edx+ebx*4], eax
mov eax, [heap_start]
lea eax, [eax+esi+0x1000]
push eax
sub edi, 0x1000
; now do real allocate at eax with size edi
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push edi
add eax, [base]
push eax
call [VirtualAlloc]
test eax, eax
jz .nomem_fatal
jmp .allocated
.m_next:
add esi, eax
jmp .l_0
.test_used:
test al, 8
jnz @f
.fail_internal:
xor ebx, ebx
mov esi, aInternalError
jmp fail
@@:
and eax, not 0xFFF
jmp .m_next
.m_exit:
push 0
.allocated:
push heap_critical_sec
call [LeaveCriticalSection]
cmp dword [esp], 0
jnz @f
push 30h
push aWarning
push aMallocFailed
push 0
call [MessageBoxA]
@@:
pop eax
mov [esp+20h], eax
ret
.not12:
cmp ebx, 13
jnz .not13
; free memory block in heap
.free_heap:
cmp [heap_status], 0
jnz @f
push 30h
push aWarning
push aHeapNotInited
push 0
call [MessageBoxA]
and dword [esp+20h], 0
ret
@@:
test ecx, ecx
jnz @f
; free(NULL) is OK
mov dword [esp+20h], 1
ret
@@:
mov esi, ecx
cmp [heap_status], 1
jnz @f
push 5
call [Sleep]
jmp @b
@@:
cmp esi, [heap_region_size]
jae .inv_exit
sub esi, [heap_start]
jb .inv_exit
cmp esi, 0x1000
jae @f
.inv_exit:
mov dword [esp+20h], 1
.inv_exit_cmn:
push 30h
push aWarning
push aFreeInvalid
push 0
call [MessageBoxA]
ret
.inv_exit_realloc:
and dword [esp+20h], 0
jmp .inv_exit_cmn
@@:
push heap_critical_sec
call [EnterCriticalSection]
mov eax, esi
shr esi, 12
dec esi
mov edx, [heap_control_block]
test byte [edx+esi*4], 10h
jnz .inv_exit_realloc
test byte [edx+esi*4], 8
jz .inv_wrn
test eax, 0xFFF
jz @f
.inv_wrn:
push edx
push 30h
push aWarning
push aFreeInvalid
push 0
call [MessageBoxA]
pop edx
@@:
mov eax, [edx+esi*4]
test al, 8
jz .freed
push edx
and eax, not 0xFFF
push 0x4000 ; MEM_DECOMMIT
sub eax, 0x1000
push eax
lea eax, [esi+1]
shl eax, 12
add eax, [heap_start]
add eax, [base]
push eax
call [VirtualFree]
pop edx
mov eax, [edx+esi*4]
and eax, not 0xFFF
push eax
or al, 4
mov [edx+esi*4], al
shr eax, 12
add eax, esi
test byte [edx+eax*4], 4
jz @f
xor ecx, ecx
xchg ecx, [edx+eax*4]
and ecx, not 0xFFF
add [edx+esi*4], ecx
add [esp], ecx
@@:
pop eax
test esi, esi
jz .freed
xor edi, edi
.findprev:
cmp edi, esi
jz .foundprev
mov ecx, edi
mov ebx, [edx+ecx*4]
shr ebx, 12
add edi, ebx
jmp .findprev
.foundprev:
test byte [edx+ecx*4], 4
jz .freed
and dword [edx+esi*4], 0
add [edx+ecx*4], eax
.freed:
push heap_critical_sec
call [LeaveCriticalSection]
mov dword [esp+20h], 1
ret
.not13:
cmp ebx, 16
jnz .not16
add ecx, [base]
mov esi, ecx
push esi
push aSound
call [lstrcmpA]
test eax, eax
jnz @f
and dword [esp+20h], 0
ret
@@:
push esi
push aInfinity
call [lstrcmpA]
test eax, eax
jnz @f
and dword [esp+20h], 0
ret
@@:
push 10h
push 0
push aUnknownDriver
push 0
call [MessageBoxA]
and dword [esp+20h], 0
ret
.not16:
cmp ebx, 19
jnz .not19
; load DLL
sub esp, 40
mov eax, esp
sub eax, [base]
push 0
push 0
push eax
push 0
push 0
push 0
push 5
mov ebx, esp
mov [ebx+21], ecx
pushad
call i40_file_system_lfn.noadd
popad
test eax, eax
jz @f
.err1:
add esp, 28+40
and dword [esp+20h], 0
ret
@@:
pop eax
push 0
mov ebx, esp
cmp dword [ebx+28+36], 0
jnz .err1
mov eax, [ebx+28+32]
mov [ebx+12], eax
call malloc_big
test eax, eax
jnz @f
.nomem_dll:
push 10h
push memerr
push aCannotLoadDll
push 0
call [MessageBoxA]
jmp .err1
@@:
sub eax, [base]
mov [ebx+16], eax
push ebx
pushad
call i40_file_system_lfn.noadd
popad
pop ebx
test eax, eax
jnz .err1
mov eax, [ebx+16]
add eax, [base]
mov [ebx+16], eax
cmp dword [eax], 'KPCK'
jnz .notpacked
mov eax, [eax+4]
call malloc_big
test eax, eax
jnz @f
push dword [ebx+16]
call free_big
jmp .nomem_dll
@@:
push eax
push eax
push dword [ebx+16]
call unpack
push dword [ebx+16]
call free_big
pop eax
mov [ebx+16], eax
.notpacked:
add esp, 28+40
; eax contains pointer to loaded file
mov ebx, eax
; 1. Calculate image size & allocate memory for image
movzx ecx, word [eax+2]
lea edx, [eax+20+16]
xor esi, esi
@@:
add esi, [edx]
add esi, 0xF
and esi, not 0xF
add edx, 40
loop @b
pushad
call .initialize_heap
mov ecx, [esp+4]
call .allocate_heap
popad
test eax, eax
jnz @f
; no memory in user space, user has already been notified
and dword [esp+20h], 0
ret
@@:
; eax = base addr in user space
; ebx = pointer to loaded DLL data
; 2. Copy image data
mov edi, eax
add edi, [base]
movzx ecx, word [ebx+2]
lea edx, [ebx+20+16]
@@:
mov [edx+12-16], edi
mov esi, [edx+20-16]
test esi, esi
jnz .copy
add edi, [edx+16-16]
jmp .next
.copy:
add esi, ebx
push ecx
mov ecx, [edx+16-16]
rep movsb
pop ecx
.next:
add edi, 0xF
and edi, not 0xF
add edx, 40
loop @b
; 3. Fixup COFF symbols
; symbols table = ebx + [ebx+8]
; strings ptr = (symbols table)+[ebx+12]*18
mov ecx, [ebx+12]
mov edx, ebx
add edx, [ebx+8]
lea esi, [ecx+ecx*8]
lea esi, [edx+esi*2]
.fix_sym:
movsx edi, word [edx+12]
test edi, edi
jnz .internal
; current implementation does not support exports
; this is kernel limitation, not my
and dword [edx+8], 0
jmp .next_sym
.internal:
js .next_sym
dec edi
shl edi, 3
lea edi, [edi+edi*4]
mov edi, [ebx+20+edi+12]
sub edi, [base]
add [edx+8], edi
.next_sym:
add edx, 18
loop .fix_sym
; 4. Fixup COFF relocations
movzx ecx, word [ebx+2]
lea esi, [ebx+20]
.fix_sec_reloc:
mov edi, [esi+24]
add edi, ebx
push ecx
movzx ecx, word [esi+32]
jecxz .next_sec_reloc
.fix_reloc:
mov edx, [edi+4]
lea edx, [edx+edx*8]
lea edx, [ebx+edx*2]
add edx, [ebx+8]
mov edx, [edx+8]
mov eax, [edi]
add eax, [esi+12]
cmp word [edi+8], 6
jz .dir32
cmp word [edi+8], 20
jz .rel32
pushad
push 30h
push aWarning
push aUnknownReloc
push 0
call [MessageBoxA]
popad
jmp .next_reloc
.rel32:
sub edx, eax
sub edx, 4
.dir32:
add [eax], edx
.next_reloc:
add edi, 10
loop .fix_reloc
.next_sec_reloc:
add esi, 40
pop ecx
loop .fix_sec_reloc
; 5. Lookup 'EXPORTS' symbol
mov eax, ebx
add eax, [ebx+8]
mov ecx, [ebx+12]
.find_exp:
cmp dword [eax], 'EXPO'
jnz @f
cmp dword [eax+4], 'RTS'
jz .found_exp
@@:
add eax, 18
loop .find_exp
; 5b. Lookup '_EXPORTS' symbol
mov eax, ebx
add eax, [ebx+8]
mov ecx, [ebx+12]
.find__exp:
cmp dword [eax], '_EXP'
jnz @f
cmp dword [eax+4], 'ORTS'
jz .found_exp
@@:
add eax, 18
loop .find__exp
push 30h
push aWarning
push aExportsNotFound
push 0
call [MessageBoxA]
xor eax, eax
jmp @f
.found_exp:
mov eax, [eax+8]
@@:
mov [esp+20h], eax
push ebx
call free_big
ret
.not19:
cmp ebx, 20
jnz .not20
; reallocate memory block in heap
cmp [heap_status], 0
jnz @f
push 30h
push aWarning
push aHeapNotInited
push 0
call [MessageBoxA]
and dword [esp+20h], 0
ret
@@:
cmp [heap_status], 1
jnz @f
push ecx edx
push 5
call [Sleep]
pop edx ecx
jmp @b
@@:
; realloc(NULL,sz) = malloc(sz)
test edx, edx
jz .allocate_heap
cmp edx, [heap_region_size]
jae .inv_exit_realloc
sub edx, [heap_start]
jb .inv_exit_realloc
cmp edx, 0x1000
jb .inv_exit_realloc
push ecx edx
push heap_critical_sec
call [EnterCriticalSection]
pop edx ecx
test edx, 0xFFF
jnz @f
shr edx, 12
dec edx
mov esi, [heap_control_block]
mov eax, [esi+edx*4]
test al, 10h
jnz @f
test al, 8
jnz .realloc_valid
@@:
push heap_critical_sec
call [LeaveCriticalSection]
jmp .inv_exit_realloc
.realloc_valid:
add ecx, 0x1FFF
and ecx, not 0xFFF
and eax, not 0xFFF
cmp eax, ecx
jb .realloc_inc
jz .realloc_done
sub eax, ecx
push eax ecx edx
push 0x4000 ; MEM_DECOMMIT
push eax
shl edx, 12
add edx, ecx
add edx, [heap_start]
add edx, [base]
push edx
call [VirtualFree]
test eax, eax
jz $
pop edx ecx
mov eax, ecx
cmp eax, 0x1000
jz .realloc_freeall
or al, 8
mov [esi+edx*4], eax
pop eax
shr ecx, 12
add edx, ecx
mov edi, [heap_region_size]
sub edi, [heap_start]
shr edi, 12
push edx
mov edx, eax
shr edx, 12
add edx, [esp]
@@:
cmp edx, edi
jae @f
mov ecx, [esi+edx*4]
test cl, 4
jz @f
and dword [esi+edx*4], 0
and ecx, not 0xFFF
add eax, ecx
shr ecx, 12
add edx, ecx
jmp @b
@@:
pop edx
or al, 4
mov [esi+edx*4], eax
.realloc_done:
push heap_critical_sec
call [LeaveCriticalSection]
mov eax, [esp+18h]
mov [esp+20h], eax
ret
.realloc_freeall:
pop eax
xor ecx, ecx
xor eax, eax
@@:
cmp ecx, edx
jae @f
mov eax, [esi+ecx*4]
shr eax, 12
add ecx, eax
jmp @b
@@:
test eax, eax
jz @f
sub ecx, eax
test byte [esi+ecx*4], 4
jz @f
xor eax, eax
xchg eax, [esi+edx*4]
and eax, not 0xFFF
add [esi+ecx*4], eax
mov edx, ecx
@@:
mov eax, [esi+edx*4]
shr eax, 12
add eax, edx
mov edi, [heap_region_size]
sub edi, [heap_start]
shr edi, 12
cmp eax, edi
jae @f
test byte [esi+eax*4], 4
jz @f
xor ecx, ecx
xchg ecx, [esi+eax*4]
and ecx, not 0xFFF
add [esi+edx*4], ecx
@@:
mov byte [esi+edx*4], 4
push heap_critical_sec
call [LeaveCriticalSection]
and dword [esp+20h], 0
ret
.realloc_inc:
mov edi, [heap_region_size]
sub edi, [heap_start]
shr edi, 12
push eax
shr eax, 12
add eax, edx
cmp eax, edi
jae .realloc_realloc
mov eax, [esi+eax*4]
test al, 4
jz .realloc_realloc
and eax, not 0xFFF
add eax, [esp]
sub eax, ecx
jb .realloc_realloc
; reallocate in place
jz @f
push ecx edx
shr ecx, 12
add edx, ecx
or al, 4
mov [esi+edx*4], eax
pop edx ecx
@@:
pop eax
sub ecx, eax
add [esi+edx*4], ecx
mov edi, edx
inc edi
shl edi, 12
add edi, [heap_start]
mov [esp+20h], edi
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push ecx
shl edx, 12
add edx, eax
add edx, [heap_start]
add edx, [base]
push edx
call [VirtualAlloc]
test eax, eax
jz .nomem_fatal
push heap_critical_sec
call [LeaveCriticalSection]
ret
.realloc_realloc:
pop esi
push ecx
push heap_critical_sec
call [LeaveCriticalSection]
pop ecx
pushad
call .allocate_heap
popad
mov [esp+20h], eax
mov edi, eax
test edi, edi
jnz @f
ret
@@:
lea ecx, [esi-0x1000]
mov esi, [esp+18h]
push esi
add esi, [base]
add edi, [base]
shr ecx, 2
rep movsd
pop ecx
pushad
call .free_heap
popad
ret
.not20:
cmp ebx, 22
jnz .not22
; open/create named memory area
test esi, not 0xD
jnz not_supported_i40_fn
add ecx, [base]
mov edi, ecx
..server_create_shmem:
div edx
test eax, eax
jz @f
.shmem.err:
and dword [esp+20h], 0
mov [esp+18h], eax
ret
@@:
pushad
call .allocate_heap
popad
test eax, eax
jnz @f
mov ecx, edi
call ..server_destroy_shmem
mov al, 30
jmp .shmem.err
@@:
mov [esp+20h], eax
mov [esp+18h], edx
mov ecx, eax
sub ecx, [heap_start]
shr ecx, 12
mov edx, [heap_control_block]
or byte [edx+(ecx-1)*4], 10h
add eax, [base]
..server_notify_shmem:
div edx
push eax
push esp
push 1 ; PAGE_NOACCESS
push ecx
push eax
call [VirtualProtect]
pop eax
ret
.not22:
cmp ebx, 23
jnz not_supported_i40_fn
add ecx, [base]
call ..server_destroy_shmem
jecxz @f
sub ecx, [base]
mov eax, ecx
sub eax, [heap_start]
shr eax, 12
mov edx, [heap_control_block]
and byte [edx+(eax-1)*4], not 10h
pushad
call .free_heap
popad
jmp .ret22
@@:
push 30h
push aWarning
push aCannotDestroyShMem
push 0
call [MessageBoxA]
.ret22:
mov dword [esp+20h], 0x87654320
ret
..server_destroy_shmem:
div edx
ret
 
include 'unpacker.inc'
 
align 4
debug_services_table:
dd i40_debug_services.set_event_data
dd i40_debug_services.getcontext
dd i40_debug_services.setcontext
dd not_supported_i40_fn ;i40_debug_services.detach
dd i40_debug_services.suspend
dd i40_debug_services.resume
dd i40_debug_services.read_process_memory
dd i40_debug_services.write_process_memory
dd i40_debug_services.terminate
; dd i40_debug_services.set_drx
.size = ($ - debug_services_table)/4
 
i40_debug_services:
cmp ebx, debug_services_table.size
jae not_supported_i40_fn
jmp dword [debug_services_table+ebx*4]
.set_event_data:
call get_cur_slot_ptr
; atomic operation, no synchronization required
mov [edi+shared_data_struc.debugger_mem-shared_data_struc.threads], ecx
ret
.m1pop2:
pop eax
.m1pop:
pop eax
.m1:
or dword [esp+20h], -1
.ret:
ret
.getcontext:
call find_debuggee
test ebx, ebx
jz .ret
cmp edx, 40
jnz .ret
push dword [ebx+12]
call suspend_safe
sub esp, 0xB2*4
push 1000Fh
mov edi, esp
push edi
push dword [ebx+12]
call [GetThreadContext]
add esi, [base]
mov ax, cs
cmp word [edi+0xBC], ax
jz .context_win
mov eax, [edi+0xB8]
mov [esi], eax
mov eax, [edi+0xC0]
mov [esi+4], eax
mov eax, [edi+0xB0]
mov [esi+8], eax
mov eax, [edi+0xAC]
mov [esi+12], eax
mov eax, [edi+0xA8]
mov [esi+16], eax
mov eax, [edi+0xA4]
mov [esi+20], eax
mov eax, [edi+0xC4]
mov [esi+24], eax
mov eax, [edi+0xB4]
mov [esi+28], eax
mov eax, [edi+0xA0]
mov [esi+32], eax
mov eax, [edi+0x9C]
mov [esi+36], eax
jmp .gotcontext
.context_win:
mov eax, [ebx+16]
add eax, tls._esp
sub esp, 2Ch
mov ecx, esp
push 0
push esp
push 8
push ecx
push eax
push dword [ebx+8]
call [ReadProcessMemory]
pop eax
pop dword [esi+24]
pop dword [esi]
mov ecx, esp
push 0
push esp
push 24h
push ecx
push dword [ebx+20]
push dword [ebx+8]
call [ReadProcessMemory]
pop eax
pop dword [esi+36]
pop dword [esi+32]
pop dword [esi+28]
pop eax
pop dword [esi+20]
pop dword [esi+16]
pop dword [esi+12]
pop dword [esi+8]
pop dword [esi+4]
.gotcontext:
add esp, 0xB3*4
@@:
push dword [ebx+12]
call [ResumeThread]
ret
.resume:
call find_debuggee
test ebx, ebx
jz .ret
jmp @b
.suspend:
call find_debuggee
test ebx, ebx
jz .ret
push dword [ebx+12]
call suspend_safe
ret
.setcontext:
call find_debuggee
test ebx, ebx
jz .ret
cmp edx, 40
jnz .ret
push dword [ebx+12]
call suspend_safe
sub esp, 0xB2*4
push 1000Fh
mov edi, esp
push edi
push dword [ebx+12]
call [GetThreadContext]
add esi, [base]
mov ax, cs
cmp word [edi+0xBC], ax
jz .context_win_set
lodsd
mov [edi+0xB8], eax
lodsd
mov [edi+0xC0], eax
lodsd
mov [edi+0xB0], eax
lodsd
mov [edi+0xAC], eax
lodsd
mov [edi+0xA8], eax
lodsd
mov [edi+0xA4], eax
lodsd
mov [edi+0xC4], eax
lodsd
mov [edi+0xB4], eax
lodsd
mov [edi+0xA0], eax
lodsd
mov [edi+0x9C], eax
push edi
push dword [ebx+12]
call [SetThreadContext]
jmp .setcontextdone
.context_win_set:
mov edx, [ebx+16]
add edx, tls._esp
lodsd
push eax
push dword [esi-4+24]
mov ecx, esp
push 0
push esp
push 8
push ecx
push eax
push dword [ebx+8]
call [WriteProcessMemory]
pop eax
pop eax
pop eax
push 9
pop ecx
@@:
lodsd
push eax
loop @b
mov ecx, esp
push 0
push esp
push 24h
push ecx
push dword [ebx+20]
push dword [ebx+8]
call [WriteProcessMemory]
add esp, 4+24h
.setcontextdone:
add esp, 0xB3*4
push dword [ebx+12]
call [ResumeThread]
ret
.write_process_memory:
push [WriteProcessMemory]
jmp @f
.read_process_memory:
push [ReadProcessMemory]
@@:
call find_debuggee
test ebx, ebx
jz .m1pop
; get base and limit of target process
push eax
push eax
mov eax, esp
push edx
push 0
push esp
push 8
push eax
push base
push dword [ebx+8]
call [ReadProcessMemory]
pop eax
pop edx
pop ecx ; ecx = [base] for target process
cmp eax, 8
jnz .m1pop2
pop eax ; eax = [limit] for target process
push edx
inc eax
add edx, esi
sub edx, eax
jc @f
sub dword [esp], edx
jnc @f
and dword [esp], 0
@@:
add esi, ecx
pop edx
pop ecx
xor eax, eax
test edx, edx
jz @f
push -1
push esp
add edi, [base]
push edx
push edi
push esi
push dword [ebx+8]
call ecx
pop eax
@@:
mov [esp+20h], eax
ret
.terminate:
call find_debuggee
test ebx, ebx
jnz i40_sys_service.kill
ret
.set_drx:
sub esp, 0xB2*4
push 1001Fh
call find_debuggee
test ebx, ebx
jz .ret1
mov edi, esp
push ecx edx
push edi
push dword [ebx+12]
call [GetThreadContext]
pop edx ecx
test dh, dh
js .clear
; set hardware breakpoint, dl=index (0..3), dh=(length*4)+(condition), esi=address
cmp esi, 0x80000000
jae .ret1
cmp dl, 4
jae .ret1
test dh, 0xF0
jnz .ret1
mov al, dh
and al, 3
cmp al, 2
jz .ret1
movzx eax, dh
shr al, 2
cmp al, 2
jz .ret1
test esi, eax
jnz .ret1
push edx
push 0
mov eax, esp
push eax
push esp
push 4
push eax
push base
push dword [ebx+8]
call [ReadProcessMemory]
pop eax
pop eax
pop edx
add esi, eax
or byte [edi+18h+1], 3 ; set GE and LE flags
movzx eax, dh
movzx ecx, dl
add ecx, ecx
bts dword [edi+18h], ecx ; set L<i> flag
mov [edi+4+ecx*2], esi ; set DR<i>
shl eax, cl
mov edx, 0xF
shl edx, cl
not edx
and [edi+18h+2], dx
or [edi+18h+2], ax ; set R/W and LEN fields
jmp .set_and_ret
.clear:
movzx ecx, dl
add ecx, ecx
btr dword [edi+18h], ecx ; clear L<i> flag
.set_and_ret:
push edi
push dword [ebx+12]
call [SetThreadContext]
add esp, 0xB3*4
and dword [esp+20h], 0
ret
.ret1:
add esp, 0xB3*4
push 30h
push aWarning
push aInvalidDataForDR
push 0
call [MessageBoxA]
mov dword [esp+20h], 1
ret
 
find_debuggee:
lea ebx, [ebp+tls.debuggees]
@@:
mov ebx, [ebx]
test ebx, ebx
jz @f
cmp dword [ebx+4], ecx
jnz @b
@@:
ret
 
suspend_safe:
xchg ebx, [esp+4]
.redo:
push ebx
call [SuspendThread]
sub esp, 0xB2*4
push 1000Fh
push esp
push ebx
call [GetThreadContext]
mov ax, cs
cmp word [context+0xBC], ax
jnz .ok
cmp dword [context+0xB8], i40_nt
jz .wait
cmp dword [context+0xB8], i40_9x
jb .test2
cmp dword [context+0xB8], safe_to_suspend
ja .test2
.wait:
add esp, 0xB3*4
push ebx
call [ResumeThread]
push 50
call [Sleep]
jmp .redo
.test2:
cmp dword [context+0xB8], i40_done
jb .ok
cmp dword [context+0xB8], not_supported_i40_fn
jb .wait
.ok:
add esp, 0xB3*4
xchg ebx, [esp+4]
ret 4
 
rootdirs:
db 2,'rd'
dd fs_OnRamdisk
dd fs_NextRamdisk
db 7,'ramdisk'
dd fs_OnRamdisk
dd fs_NextRamdisk
; db 2,'fd'
; dd fs_OnFloppy
; dd fs_NextFloppy
; db 10,'floppydisk'
; dd fs_OnFloppy
; dd fs_NextFloppy
db 3,'hd0'
dd fs_OnHd0
dd fs_NextHd0
db 3,'hd1'
dd fs_OnHd1
dd fs_NextHd1
db 3,'hd2'
dd fs_OnHd2
dd fs_NextHd2
db 3,'hd3'
dd fs_OnHd3
dd fs_NextHd3
db 0
 
virtual_root_query:
dd fs_HasRamdisk
db 'rd',0
; dd fs_HasFloppy
; db 'fd',0
dd fs_HasHd0
db 'hd0',0
dd fs_HasHd1
db 'hd1',0
dd fs_HasHd2
db 'hd2',0
dd fs_HasHd3
db 'hd3',0
dd 0
 
i40_file_system_lfn:
add ebx, [base]
.noadd:
push 0
; parse file name
lea esi, [ebx+20]
lodsb
test al, al
jnz @f
mov esi, [esi]
add esi, [base]
lodsb
jmp @f
.parse:
push edi
lodsb
@@:
push 0
cmp al, '/'
jz @f
dec esi
mov dword [esp], esi
mov esi, [ebp+tls.cur_dir]
inc esi
jmp @f
.notfound:
pop eax
pop eax
test eax, eax
mov eax, 5 ; file not found
jnz .notfound_retparse
mov [esp+20h], eax
.notfound_retparse:
ret
@@:
mov eax, [esi]
or eax, ' '
cmp eax, 'sys'
jz .sys1
cmp eax, 'sys/'
jnz @f
inc esi
.sys1:
mov eax, ramdisk_path
add esi, 3
jmp fs_common
@@:
cmp byte [esi], 0
jz .rootdir
mov edi, rootdirs-8
xor ecx, ecx
push esi
.scan1:
pop esi
add edi, ecx
scasd
scasd
mov cl, byte [edi]
jecxz .notfound
inc edi
push esi
@@:
lodsb
or al, 20h
scasb
loopz @b
jnz .scan1
lodsb
cmp al, '/'
jz .found1
test al, al
jnz .scan1
pop eax
; directory /xxx
.maindir:
pop eax
pop eax
test eax, eax
jz @f
.parse_access_denied:
mov eax, 10 ; access denied
ret
@@:
cmp dword [ebx], 1
jnz .access_denied
xor eax, eax
push dword [ebx+12]
mov edx, [ebx+16]
add edx, [base]
push dword [ebx+4] ; first block
mov ebx, [ebx+8] ; flags
and ebx, 1
mov esi, [edi+4]
; [esp]=first block, [esp+4]=number of blocks, ebx=flags, edx=return area, esi='Next' handler
mov edi, edx
mov ecx, 32/4
rep stosd
mov byte [edx], 1 ; version
.maindir_loop:
call esi
jc .maindir_done
inc dword [edx+8]
dec dword [esp]
jns .maindir_loop
dec dword [esp+4]
js .maindir_loop
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx ; name type
push eax
xor eax, eax
add edi, 8
mov ecx, 40/4-2
rep stosd
pop eax
push eax edx
; convert number in eax to decimal ANSI/UNICODE string
push edi
push -'0'
mov cl, 10
@@:
xor edx, edx
div ecx
push edx
test eax, eax
jnz @b
@@:
pop eax
add al, '0'
stosb
pushf
test bl, 1
jz .ansi_name
xor eax, eax
stosb
.ansi_name:
popf
jnz @b
pop edi
add edi, 520
test bl, 1
jnz @f
sub edi, 520-264
@@:
pop edx eax
jmp .maindir_loop
.maindir_done:
mov ebx, [edx+4]
xor eax, eax
pop ecx ecx
dec ecx
js @f
mov al, 6
@@:
mov [esp+20h], eax
mov [esp+14h], ebx
ret
; directory /
.rootdir:
pop eax
pop eax
test eax, eax
jnz .parse_access_denied
cmp dword [ebx], 1 ; read folder?
jz .readroot
.access_denied:
mov dword [esp+20h], 10 ; access denied
ret
 
.readroot:
; virtual root folder - special handler
mov esi, virtual_root_query
push dword [ebx+12]
mov edx, [ebx+16]
add edx, [base]
push dword [ebx+4]
mov ebx, [ebx+8]
xor eax, eax
; eax=0, [esp]=first block, [esp+4]=number of blocks, ebx=flags, edx=return area
mov edi, edx
mov ecx, 32/4
rep stosd
mov byte [edx], 1 ; version
.readroot_loop:
cmp dword [esi], eax
jz .readroot_done
call dword [esi]
add esi, 4
test eax, eax
jnz @f
.readroot_next:
or ecx, -1
xchg esi, edi
repnz scasb
xchg esi, edi
jmp .readroot_loop
@@:
xor eax, eax
inc dword [edx+8]
dec dword [esp]
jns .readroot_next
dec dword [esp+4]
js .readroot_next
inc dword [edx+4]
mov dword [edi], 0x10 ; attributes: folder
mov dword [edi+4], ebx ; name type
add edi, 8
push 40/4-2
pop ecx
rep stosd
push edi
@@:
lodsb
stosb
test bl, 1
jz .ansi_name2
mov byte [edi], 0
inc edi
.ansi_name2:
test eax, eax
jnz @b
pop edi
add edi, 520
test bl, 1
jnz @f
sub edi, 520-264
@@:
jmp .readroot_loop
.readroot_done:
mov ebx, [edx+4]
xor eax, eax
pop ecx ecx
dec ecx
js @f
mov al, 6
@@:
mov [esp+20h], eax
mov [esp+14h], ebx
ret
 
.found1:
pop eax
cmp byte [esi], 0
jz .maindir
; read partition number
xor ecx, ecx
xor eax, eax
@@:
lodsb
cmp al, '/'
jz .done1
test al, al
jz .done1
sub al, '0'
cmp al, 9
ja .notfound
imul ecx, 10
add ecx, eax
jmp @b
.done1:
test ecx, ecx
jz .notfound
test al, al
jnz @f
dec esi
@@:
; now [edi] contains handler address, ecx - partition number,
; esi points to ASCIIZ string - rest of name
jmp dword [edi]
 
fs_NextRamdisk:
test eax, eax
stc
jnz @f
mov al, 1
clc
@@: ret
 
fs_NextHd0:
push 0
jmp fs_NextHd
fs_NextHd1:
push 1
jmp fs_NextHd
fs_NextHd2:
push 2
jmp fs_NextHd
fs_NextHd3:
push 3
fs_NextHd:
pop ecx
mov ecx, [hd_partitions_num+ecx*4]
cmp eax, ecx
jae .no
inc eax
clc
ret
.no:
stc
ret
 
fs_HasRamdisk:
mov al, 1
ret
 
fs_HasHd0:
cmp [hd_partitions_num], 0
setnz al
ret
fs_HasHd1:
cmp [hd_partitions_num+4], 0
setnz al
ret
fs_HasHd2:
cmp [hd_partitions_num+8], 0
setnz al
ret
fs_HasHd3:
cmp [hd_partitions_num+12], 0
setnz al
ret
 
fs_OnRamdisk:
cmp ecx, 1
jnz i40_file_system_lfn.notfound
mov eax, ramdisk_path
jmp fs_common
 
fs_OnHd0:
push 0
jmp fs_OnHd
fs_OnHd1:
push 1
jmp fs_OnHd
fs_OnHd2:
push 2
jmp fs_OnHd
fs_OnHd3:
push 3
fs_OnHd:
pop eax
cmp ecx, [hd_partitions_num+eax*4]
jbe @f
pop eax eax
test eax, eax
mov eax, 5
.hderr:
jnz .ret
mov dword [esp+20h], eax
.ret:
ret
@@:
dec ecx
mov eax, [hd_partitions_array+eax*4]
shl ecx, 9
add eax, ecx
cmp byte [eax+511], 0
jz fs_common
; readonly disk - allow only subfunctions 0,1,5,7
cmp dword [ebx], 0
jz fs_common
cmp dword [ebx], 1
jz fs_common
cmp dword [ebx], 5
jz fs_common
cmp dword [ebx], 7
jz fs_common
; access denied!
pop eax eax
test eax, eax
mov eax, 10
jmp .hderr
fs_common:
pop ecx
pop edi
test edi, edi
jnz @f
sub esp, 204h
mov edi, esp
@@:
push ecx
push eax
push edi
call [lstrcpyA]
push edi
call [lstrlenA]
pop ecx
push edi
add edi, eax
sub eax, 204h
neg eax
push ecx
push eax
push esi
push edi
call [lstrcpynA]
pop ecx
jecxz .slash_pass
cmp byte [ecx], 0
jz .slash_pass
mov esi, ecx
push edi
call [lstrlenA]
add edi, eax
mov eax, edi
sub eax, [esp]
sub eax, 204h
neg eax
push eax
push esi
push edi
call [lstrcpynA]
.slash_pass:
mov al, [edi]
test al, al
jz .slash_pass_done
cmp al, '\'
jz .invalid
cmp al, '/'
jnz @f
mov al, '\'
@@:
stosb
jmp .slash_pass
.slash_pass_done:
; delete trailing slashes, if present
dec edi
cmp byte [edi], '\'
jz .slash_pass_done
inc edi
stosb
; but do not delete one slash in X:\
pop edi
cmp byte [edi+1], ':'
jnz @f
cmp byte [edi+2], 0
jnz @f
mov word [edi+2], '\'
@@:
push edi
push edi
call [OemToCharA]
; now edi -> Win32 path
cmp edi, esp
jz fs_do
xor eax, eax
ret
.invalid:
pop edi
cmp edi, esp
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
ret
@@:
push 5
pop eax
ret
fs_do:
cmp dword [ebx], 10
jb @f
fs_unsupported:
add esp, 204h
jmp not_supported_i40_fn
@@:
push edi
call [GetFileAttributesA]
mov ecx, dword [ebx]
jmp dword [i40_fs_subfunctions + ecx*4]
 
i40_fs_subfunctions:
dd fs_read
dd fs_read_folder
dd fs_rewrite
dd fs_write
dd fs_setsize
dd fs_getattr
dd fs_setattr
dd fs_execute
dd fs_delete
dd fs_makedir
 
fs_read:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
or dword [esp+14h], -1
ret
@@:
dec eax
test al, 10h ; FILE_ATTRIBUTE_DIRECTORY
jz @f
add esp, 204h
.access_denied:
mov dword [esp+20h], 10 ; access denied
or dword [esp+14h], -1
ret
@@:
push 0
push 0
push 3
push 0
push 1
push 80000000h
push edi
call [CreateFileA]
add esp, 204h
inc eax
jz .access_denied
dec eax
xchg eax, esi
push dword [ebx+8]
mov eax, esp
push 0
push eax
push dword [ebx+4]
push esi
call [SetFilePointer]
inc eax
jnz @f
call [GetLastError]
test eax, eax
jz @f
pop eax
mov dword [esp+20h], 6 ; EOF
and dword [esp+14h], 0 ; no bytes read
push esi
call [CloseHandle]
ret
@@:
mov eax, esp
push 0
push eax
; mov eax, [limit]
; inc eax
; sub eax, [ebx+16]
; cmp eax, [ebx+12]
; jb @f
; mov eax, [ebx+12]
;@@:
; push eax
push dword [ebx+12]
mov eax, [ebx+16]
add eax, [base]
push eax
push esi
call [ReadFile]
pop ecx
xor eax, eax
cmp ecx, [ebx+12]
jz @f
mov al, 6 ; EOF
@@:
mov [esp+20h], eax
mov [esp+14h], ecx ; bytes read
push esi
call [CloseHandle]
ret
 
fs_read_folder:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
or dword [esp+14h], -1
ret
@@:
push edi
call [lstrlenA]
cmp eax, 202h
jb @f
add esp, 204h
mov dword [esp+20h], 5
or dword [esp+14h], -1
ret
@@:
cmp byte [edi+eax-1], '/'
jz @f
cmp byte [edi+eax-1], '\'
jz @f
mov byte [edi+eax], '/'
inc eax
@@:
mov word [edi+eax], '*'
cmp byte [esi], 0
mov esi, 2
jz @f
xor esi, esi
@@:
sub esp, 140h ; sizeof(WIN32_FIND_DATAA)
push esp
push edi
call [FindFirstFileA]
inc eax
jnz @f
add esp, 140h+204h
mov dword [esp+20h], 10 ; access denied
or dword [esp+14h], -1
ret
@@:
dec eax
push dword [ebx+8] ; flags
push dword [ebx+4] ; 1st block
push dword [ebx+12] ; number of blocks
mov edi, [ebx+16] ; buffer
add edi, [base]
push edi
xchg eax, ebx
mov ecx, 32/4
xor eax, eax
rep stosd
mov byte [edi-32], 1 ; version
.loop:
test esi, 2
jz .noroot
cmp word [esp+16+44], '.'
jz .cont
cmp word [esp+16+44], '..'
jnz .noroot
cmp byte [esp+16+46], 0
jz .cont
.noroot:
pop eax
push eax
inc dword [eax+8] ; new file found
dec dword [esp+8]
jns .cont
dec dword [esp+4]
js .cont
inc dword [eax+4] ; new file copied
mov eax, [esp+16] ; attributes
and eax, 3Fh
stosd
mov al, [esp+12] ; name type
and eax, 1
stosd
lea eax, [esp+16+4]
call get_bdfe_time
lea eax, [esp+16+12]
call get_bdfe_time
lea eax, [esp+16+20]
call get_bdfe_time
mov eax, [esp+16+32]
stosd
mov eax, [esp+16+28]
stosd
lea eax, [esp+16+44]
test byte [esp+12], 1
jz .name_ansi
push 260
push edi
push -1
push eax
push 0
push 0
call [MultiByteToWideChar]
add edi, 260*2
jmp .cont
.name_ansi:
push edi
push eax
call [CharToOemA]
add edi, 264
.cont:
lea eax, [esp+16]
push eax
push ebx
call [FindNextFileA]
test eax, eax
jnz .loop
push ebx
call [FindClose]
pop edx
mov ebx, [edx+4]
xor eax, eax
pop ecx
dec ecx
js @f
mov al, 6
@@:
add esp, 140h+204h+8
mov [esp+20h], eax
mov [esp+14h], ebx
ret
 
get_bdfe_time:
sub esp, 10h
push esp
push eax
call [FileTimeToSystemTime]
mov ax, [esp+8]
shl eax, 16
mov ah, [esp+10]
mov al, [esp+12]
stosd
mov ax, [esp+0]
shl eax, 16
mov ah, [esp+2]
mov al, [esp+6]
stosd
add esp, 10h
ret
from_bdfe_time:
sub esp, 10h
xor eax, eax
lodsb
mov [esp+12], ax
lodsb
mov [esp+10], ax
lodsw
mov [esp+8], ax
mov ah, 0
lodsb
mov [esp+6], ax
lodsb
mov [esp+2], ax
lodsw
mov [esp+0], ax
mov eax, esp
push edi
push eax
call [SystemTimeToFileTime]
add esp, 10h
add edi, 8
ret
 
fs_rewrite:
push 0
push 80h
push 2
push 0
push 0
push 40000000h
push edi
call [CreateFileA]
add esp, 204h
inc eax
jnz @f
mov dword [esp+20h], 10
and dword [esp+14h], 0
ret
@@:
dec eax
xchg eax, esi
push eax
mov eax, esp
push 0
push eax
push dword [ebx+12]
mov eax, [ebx+16]
add eax, [base]
push eax
push esi
call [WriteFile]
pop ebx
push esi
call [CloseHandle]
and dword [esp+20h], 0
mov [esp+14h], ebx
ret
 
fs_write:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
or dword [esp+14h], -1
ret
@@:
dec eax
test al, 10h ; FILE_ATTRIBUTE_DIRECTORY
jz @f
add esp, 204h
.access_denied:
mov dword [esp+20h], 10 ; access denied
or dword [esp+14h], -1
ret
@@:
push 0
push 0
push 3
push 0
push 1
push 40000000h
push edi
call [CreateFileA]
add esp, 204h
inc eax
jz .access_denied
dec eax
xchg eax, esi
push dword [ebx+8]
mov eax, esp
push 0
push eax
push dword [ebx+4]
push esi
call [SetFilePointer]
inc eax
jnz @f
call [GetLastError]
test eax, eax
jz @f
pop eax
mov dword [esp+20h], 6 ; EOF
and dword [esp+14h], 0 ; no bytes read
push esi
call [CloseHandle]
ret
@@:
mov eax, esp
push 0
push eax
mov eax, [limit]
inc eax
sub eax, [ebx+16]
cmp eax, [ebx+12]
jb @f
mov eax, [ebx+12]
@@:
push eax
mov eax, [ebx+16]
add eax, [base]
push eax
push esi
call [WriteFile]
pop ecx
xor eax, eax
cmp ecx, [ebx+12]
jz @f
mov al, 6 ; EOF
@@:
mov [esp+20h], eax
mov [esp+14h], ecx ; bytes read
push esi
call [CloseHandle]
ret
 
fs_setsize:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
or dword [esp+14h], -1
ret
@@:
dec eax
test al, 10h ; FILE_ATTRIBUTE_DIRECTORY
jz @f
add esp, 204h
.access_denied:
mov dword [esp+20h], 10 ; access denied
or dword [esp+14h], -1
ret
@@:
push 0
push 0
push 3
push 0
push 1
push 40000000h
push edi
call [CreateFileA]
add esp, 204h
inc eax
jz .access_denied
dec eax
xchg eax, esi
push dword [ebx+8]
mov eax, esp
push 0
push eax
push dword [ebx+4]
push esi
call [SetFilePointer]
inc eax
jnz @f
call [GetLastError]
test eax, eax
jz @f
pop eax
mov dword [esp+20h], 6 ; EOF
mov dword [esp+14h], 1234567h ; destroy ebx
push esi
call [CloseHandle]
ret
@@:
pop ecx
push esi
call [SetEndOfFile]
and dword [esp+20h], 0
mov dword [esp+14h], 234567h ; destroy ebx
push esi
call [CloseHandle]
ret
 
fs_getattr:
inc eax
jnz @f
.notfound:
add esp, 204h
mov dword [esp+20h], 5 ; file not found
.ret_destroy_ebx:
mov dword [esp+14h], 12345678h
ret
@@:
; Win32 does not allow to read attributes of root directories through FindFirstFile.
; Moreover, on FAT systems the root directory simply does not contain attributes.
; The current kernel implementation in Kolibri returns error eax = 2.
; Let it be.
cmp word [edi+1], ':\'
jnz @f
cmp byte [edi+3], 0
jnz @f
; The program requests root directory. Return eax=2.
; N.B. All previous words are related to the case when Kolibri-disk is mapped to
; real disk, /hdi/j = N:\. Otherwise, it is possible to get real attributes
; of root directory, and emulator will do so (in another branch).
add esp, 204h
mov dword [esp+20h], 2
jmp .ret_destroy_ebx
@@:
sub esp, 140h ; sizeof(WIN32_FIND_DATAA)
push esp
push edi
call [FindFirstFileA]
inc eax
jnz @f
add esp, 140h+204h
mov dword [esp+20h], 10 ; access denied
mov dword [esp+14h], 12345678h
ret
@@:
dec eax
push eax
call [FindClose]
mov edi, [ebx+16]
add edi, [base]
pop eax ; attributes
and eax, 3Fh
stosd
xor eax, eax
stosd
mov eax, esp
call get_bdfe_time
lea eax, [esp+12-4]
call get_bdfe_time
lea eax, [esp+20-4]
call get_bdfe_time
mov eax, [esp+32-4]
stosd
mov eax, [esp+28-4]
stosd
add esp, 140h-4+204h
and dword [esp+20h], 0
mov dword [esp+14h], 12345678h
ret
 
fs_setattr:
inc eax
jz fs_getattr.notfound
mov esi, [ebx+16]
add esi, [base]
lodsd
push eax ; remember attributes
push 80h ; FILE_ATTRIBUTE_NORMAL
push edi
call [SetFileAttributesA]
push 0
push 0
push 3 ; OPEN_EXISTING
push 0
push 3 ; FILE_SHARE_READ | FILE_SHARE_WRITE
push 0x40000000 ; GENERIC_WRITE
push edi
call [CreateFileA]
mov ebx, eax
inc eax
jnz @f
push edi
call [SetFileAttributesA]
add esp, 204h
mov dword [esp+20h], 10
ret
@@:
lodsd
sub esp, 8*3
mov edi, esp
call from_bdfe_time
call from_bdfe_time
call from_bdfe_time
lea eax, [esp+16]
push eax
sub eax, 8
push eax
sub eax, 8
push eax
push ebx
call [SetFileTime]
add esp, 8*3
push ebx
call [CloseHandle]
push edi
call [SetFileAttributesA]
add esp, 204h
and dword [esp+20h], 0
ret
 
fs_execute:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], -5 ; file not found
or dword [esp+14h], -1
ret
@@:
mov eax, [ebx+4]
mov esi, [ebx+8]
call notify_run_prg
add esp, 204h
mov [esp+20h], eax
mov dword [esp+14h], 23456789h
ret
 
fs_delete:
inc eax
jnz @f
add esp, 204h
mov dword [esp+20h], 5 ; file not found
.ret:
mov dword [esp+14h], 0x12345678
ret
@@:
dec eax
test al, 10h
jnz .directory
push edi
call [DeleteFileA]
@@:
add esp, 204h
and dword [esp+20h], 0
test eax, eax
jnz .ret
mov byte [esp+20h], 10 ; access denied
jmp .ret
.directory:
push edi
call [RemoveDirectoryA]
jmp @b
 
fs_makedir:
push 0
push edi
call [CreateDirectoryA]
add esp, 204h
and dword [esp+20h], 0
test eax, eax
jnz @f
call [GetLastError]
cmp eax, 183 ; ERROR_ALREADY_EXISTS
jz @f
mov byte [esp+20h], 10
@@:
ret
 
i40_window_settings:
cmp ebx, 1
jnz not_supported_i40_fn
mov [ebp+tls.caption], ecx
or byte [ebp+tls.color_main+3], 10h
push [ebp+tls.hWnd]
call [GetDC]
push eax
push [ebp+tls.hWnd]
mov edi, eax
; redraw caption
mov al, byte [ebp+tls.color_main+3]
and eax, 0xF
dec eax
js .type1
jz .nodraw
dec eax
jz .type2
call draw_caption_skinned
.str:
call draw_caption_string
.nodraw:
call [ReleaseDC]
ret
.type1:
call draw_caption_type1
jmp .str
.type2:
call draw_caption_type2
jmp .str
/programs/emulator/KlbrInWin/KlbrInWin.asm
0,0 → 1,6359
; Cb-n#%li.-# @l$i Lkbnbe
format PE GUI 4.0 at 400000h
section '.text' code readable executable
entry start
i40_nt:
jmp i40_9x
start:
xor ebx, ebx
call [GetVersion]
shr eax, 31
mov [bIs9x], al
; get default heap
call [GetProcessHeap]
mov [hHeap], eax
push 261
push startcurdir
push ebx
call [GetModuleFileNameA]
xchg ecx, eax
inc ecx
inc ecx
lea edi, [ecx+startcurdir-1]
mov al, '\'
std
repnz scasb
cld
mov byte [edi+2], bl
mov esi, startcurdir
mov edi, esi
xor ecx, ecx
dec ecx
mov al, 0
repnz scasb
not ecx
dec ecx
mov edi, win32_path
push edi
rep movsb
mov al, '\'
cmp byte [edi-1], al
jz @f
stosb
@@: mov esi, inifilename
mov ecx, inifilenamesize
rep movsb
; parse command line
call [GetCommandLineA]
xchg eax, esi
mov edi, inname
call getfilename
mov edi, inname
call getfilename
jc no_file_given
cmp byte [esi], bl
jz file_known
mov [parameters], esi
jmp file_known
no_file_given:
mov [inname], bl
push comdlg32_name
call [LoadLibraryA]
test eax, eax
jz @f
push eax
push aGetOpenFileNameA
push eax
call [GetProcAddress]
test eax, eax
jz @f
push ofn
call eax
test eax, eax
jz @f
call [FreeLibrary]
jmp file_known
@@:
push ebx
call [ExitProcess]
file_known:
; TLS data
mov eax, [tls_index]
mov ecx, [fs:2Ch]
mov ebp, [ecx+eax*4]
; save registers
mov [ebp+tls._cs], cs
mov [ebp+tls._ds], ds
mov [ebp+tls._fs], fs
mov [ebp+tls._esp], esp
mov [ebp+tls._eip], exception
mov eax, 1000h
call malloc_big
mov edi, eax
; test for server
push seh
push dword [fs:ebx]
mov [fs:ebx], esp
xor eax, eax
server_test:
div edx
pop dword [fs:ebx]
pop esi
test eax, eax
jz server
mov [ebp+tls.cur_slot], eax
mov [hSharedData], ecx
mov [hSharedMutex], edx
push edi
push user32_thunks
push user32_name
call init_dll
push gdi32_thunks
push gdi32_name
call init_dll
pop edi
push edi
call [lstrlenA]
inc eax
push eax
push eax
call malloc
pop ecx
mov [ebp+tls.cur_dir], eax
push edi
xchg eax, edi
xchg eax, esi
rep movsb
call free_big
call map_shared_data
push bgr_mutex_name
push ebx
push ebx
call [CreateMutexA]
mov [hBgrMutex], eax
push ebx
push ebx
push 3 ; OPEN_EXISTING
push ebx
push 1 ; FILE_SHARE_READ
push 80000000h ; GENERIC_READ
push inname
call [CreateFileA]
inc eax
jnz infileopened
mov esi, fileopenerr
fail:
push 10h
push ebx
fail2:
push esi
push ebx
cmp [bInitialized], 0
jnz @f
mov eax, [esi-4]
loadfailed:
div edx
@@:
call [MessageBoxA]
call free_ldt
push ebx
call [ExitProcess]
infileopened:
dec eax
xchg eax, edi
push eax
mov eax, esp
push ebx
push eax
push 36
push header
push edi
call [ReadFile]
test eax, eax
pop eax
mov esi, filereaderr
jz fail
cmp eax, 36
jnz fail
cmp [header], 'KPCK'
jnz .program_not_packed
mov eax, [header+4]
call malloc_big
test eax, eax
mov esi, memerr
jz fail
push eax
push eax
push ebx
push edi
call [GetFileSize]
mov [limit], eax
call malloc_big
test eax, eax
jz fail
push eax
push ebx
push ebx
push ebx
push edi
call [SetFilePointer]
push eax
mov eax, esp
push ebx
push eax
push [limit]
push dword [esp+16]
push edi
call [ReadFile]
test eax, eax
pop eax
mov esi, filereaderr
jz fail
cmp eax, [limit]
jnz fail
pop esi
push esi
mov eax, [esi+4]
mov [limit], eax
call unpack
push esi
call free_big
pop edx
mov esi, notexe
cmp dword [edx], 'MENU'
jnz fail
cmp word [edx+4], 'ET'
jnz fail
mov ax, word [edx+6]
sub ax, '00'
xchg al, ah
cmp ax, 1
ja fail
push edi
mov esi, edx
mov edi, header
mov ecx, 9
rep movsd
jz @f
mov eax, [edx+18h]
mov [header+1Ch], eax
mov eax, [edx+14h]
shr eax, 1
sub eax, 10h
mov [header+18h], eax
mov [header+20h], ebx
@@:
push edx
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push dword [edx+14h]
push ebx
call [VirtualAlloc]
pop edx
test eax, eax
mov esi, memerr
jz fail
mov [base], eax
mov edi, eax
mov esi, edx
mov ecx, [limit]
mov eax, ecx
shr ecx, 2
rep movsd
mov ecx, eax
and ecx, 3
rep movsb
jmp .program_packed_common
.program_not_packed:
mov esi, notexe
cmp [header], 'MENU'
jnz fail
cmp word [header+4], 'ET'
jnz fail
mov ax, word [header+6]
sub ax, '00'
xchg al, ah
cmp ax, 1
ja fail
jz @f
mov eax, [header+18h]
mov [header+1Ch], eax
mov eax, [header+14h]
shr eax, 1
sub eax, 10h
mov [header+18h], eax
mov [header+20h], ebx
@@:
; hmm... Menuet/Kolibri seems to ignore app_i_end field in case of running from ramdisk (fn 19)
; but depend on app_i_end in case of running from fn 58
 
; so force read all file
push ebx
push edi
call [GetFileSize]
mov [header+10h], eax
mov eax, [header+14h]
cmp eax, [header+10h]
jb fail
push 40h ; PAGE_EXECUTE_READWRITE
push 1000h ; MEM_COMMIT
push eax
push ebx
call [VirtualAlloc]
test eax, eax
mov esi, memerr
jz fail
mov [base], eax
push ebx
push ebx
push ebx
push edi
call [SetFilePointer]
push eax
mov eax, esp
push ebx
push eax
push [header+10h]
push [base]
push edi
call [ReadFile]
test eax, eax
pop eax
mov esi, filereaderr
jz fail
push edi
.program_packed_common:
call [CloseHandle]
mov esi, [parameters]
mov edi, esi
test esi, esi
jz no_params
mov eax, [header+1Ch]
test eax, eax
jz no_params
mov edx, eax
add eax, 256
cmp eax, [header+14h]
mov esi, params_err
ja fail
mov esi, edi
mov ecx, 256
xor eax, eax
repnz scasb
neg cl
mov edi, edx
add edi, [base]
rep movsb
no_params:
; read ini file client settings
; disks
push 512
push ramdisk_path
push default_ramdisk
push ramdisk_keyname
push aDisk
call [GetPrivateProfileStringA]
mov edi, hd_partitions_num
hdloop:
push win32_path
push ebx
push hdxn
push aDisk
call [GetPrivateProfileIntA]
stosd
test eax, eax
jz .cont
push eax
shl eax, 9 ; *512
push eax
call malloc
mov [edi-4+hd_partitions_array-hd_partitions_num], eax
pop ecx
xchg esi, eax
xor eax, eax
inc eax
.partitions:
push eax ecx
push eax
push hdpart
push converted_path
call [wsprintfA]
add esp, 12
mov byte [esi+511], 0
push win32_path
push 511
push esi
push null_string
push converted_path
push aDisk
call [GetPrivateProfileStringA]
test eax, eax
jnz @f
push 10h
push converted_path
mov esi, no_partition
jmp fail2
@@:
push esi
call [lstrlenA]
cmp eax, 10
jbe @f
lea eax, [eax+esi-9]
cmp byte [eax], ','
jnz @f
cmp dword [eax+1], 'read'
jnz @f
cmp dword [eax+5], 'only'
jnz @f
mov byte [eax], 0
mov byte [esi+511], 1
@@:
add esi, 512
pop ecx eax
inc eax
dec ecx
jnz .partitions
.cont:
inc [hdxn+2]
inc [hdpart+2]
cmp edi, hd_partitions_num+4*4
jnz hdloop
mov esi, converted_path
; read fonts
push win32_path
push 512
push esi
push null_string
push aFont1
push aMain
call [GetPrivateProfileStringA]
call getfilemap
mov [char_mt], eax
push win32_path
push 512
push esi
push null_string
push aFont2
push aMain
call [GetPrivateProfileStringA]
call getfilemap
mov [char2_mt], eax
push win32_path
push ebx
push aSetBgr
push aQuestions
call [GetPrivateProfileIntA]
mov [SetBgrQuestion], eax
; read skin
push win32_path
push 512
push esi
push null_string
push aSkin
push aMain
call [GetPrivateProfileStringA]
call getfilemap
xchg eax, edi
cmp dword [edi], 'KPCK'
jnz @f
mov eax, [edi+4]
call malloc_big
mov esi, memerr
test eax, eax
jz fail
push eax
push eax
push edi
call unpack
push edi
call [UnmapViewOfFile]
pop edi
inc ebx
@@:
cmp dword [edi], 'SKIN' ; ident
mov esi, skinfileerr
jnz fail
cmp dword [edi+4], 1 ; version
jnz fail
; skin parameters
mov esi, edi
add esi, [esi+8] ; parameters offset
mov ecx, 9
push edi
mov edi, _skinh
rep movsd
pop edi
mov ecx, common_colors
mov edx, 127
call get_wnd_colors
test al, al
jnz @f
lodsd
and eax, edx
push eax
xchg eax, ecx
push edi
mov edi, common_colors
push edi
rep movsb
pop ecx
pop edi
pop edx
call set_wnd_colors
@@:
; skin bitmaps
mov esi, edi
add esi, [esi+16]
skinbmploop:
cmp dword [esi], 0
jz skinbmploopend
movzx eax, word [esi]
movzx ecx, word [esi+2]
mov edx, [esi+4]
add esi, 8
add edx, edi
lea eax, [eax*2+ecx-1]
; convert bmp data to Win32 DIB
push eax edx
mov eax, [edx]
add eax, 3
and al, not 3
mul dword [edx+4]
imul eax, 3
add eax, 40
push eax
push 8 ; HEAP_ZERO_MEMORY
push [hHeap]
call [HeapAlloc]
pop edx
mov dword [eax], 40 ; biSize
mov ecx, [edx]
mov [eax+4], ecx ; biWidth
mov ecx, [edx+4]
mov [eax+8], ecx ; biHeight
mov dword [eax+12], 180001h ; biPlanes, biBitCount
push esi edi
lea edi, [eax+40]
lea esi, [edx+8]
mov ecx, [edx+4]
push eax
mov eax, [edx]
imul eax, ecx
add esi, eax
add esi, eax
add esi, eax
.x1:
push ecx
mov ecx, [edx]
add ecx, ecx
add ecx, [edx]
sub esi, ecx
push esi
rep movsb
add edi, 3
and edi, not 3
pop esi
pop ecx
loop .x1
pop edx
pop edi esi
pop eax
dec eax
jnz @f
; inactive left
mov [left1_bmp], edx
jmp skinbmploop
@@:
dec eax
jnz @f
; active left
mov [left_bmp], edx
jmp skinbmploop
@@:
dec eax
jnz @f
; inactive oper
mov [oper1_bmp], edx
jmp skinbmploop
@@:
dec eax
jnz @f
; active oper
mov [oper_bmp], edx
jmp skinbmploop
@@:
dec eax
jnz @f
; inactive base
mov [base1_bmp], edx
jmp skinbmploop
@@:
dec eax
jnz skinbmploop
; active base
mov [base_bmp], edx
jmp skinbmploop
skinbmploopend:
; skin buttons
mov esi, edi
add esi, [esi+12]
skinbuttonsloop:
lodsd
test eax, eax
jz skinbuttonsloopend
mov edx, skin_btn_close
dec eax
jz .button
mov edx, skin_btn_minimize
dec eax
jz .button
lodsd
lodsd
jmp skinbuttonsloop
.button:
mov ecx, 4
@@:
lodsw
cwde
mov [edx], eax
add edx, 4
loop @b
jmp skinbuttonsloop
skinbuttonsloopend:
dec ebx
jz .mem
xor ebx, ebx
push edi
call [UnmapViewOfFile]
jmp @f
.mem:
push edi
call free_big
@@:
; sound volume
push win32_path
push 10
push aSoundVol
push aSetup
call [GetPrivateProfileIntA]
and al, 0x7F
mov [sound_vol], al
; direct screen access parameters
push win32_path
push 32
push aColorDepth
push aDirectScreenAccess
call [GetPrivateProfileIntA]
test eax, eax
jz @f
cmp eax, 24
jz @f
cmp eax, 32
jz @f
mov esi, aInvalidColorDepth
jmp fail
@@:
mov [ColorDepth], eax
push win32_path
push 200
push aInvalidateTime
push aDirectScreenAccess
call [GetPrivateProfileIntA]
mov [InvalidateTime], eax
mov [DSA], ebx
push DSACritSect
call [InitializeCriticalSection]
cmp [ColorDepth], ebx
jz @f
push 4 ; PAGE_READWRITE
push 2000h ; MEM_RESERVE
push 1000000h
push ebx
call [VirtualAlloc]
mov esi, memerr
test eax, eax
jz fail
mov [DSA], eax
@@:
; parse path
mov eax, [header+20h]
test eax, eax
jz path_done
cmp eax, [header+14h]
jae path_done
; jb @f
; push 30h
; push aWarning
; push aPathInvalid
; push 0
; call [MessageBoxA]
; jmp path_done
;@@:
push 0
push startcurdir
push 261
push inname
call [GetFullPathNameA]
; test for /rd/1
push ramdisk_path
call [lstrlenA]
push eax
push eax
push ramdisk_path
push eax
push startcurdir
push 1
push 800h
call [CompareStringA]
cmp eax, 2
pop eax
jz .ramdisk
; test for /hdx/y
xor ecx, ecx
.hdxloop:
push ecx
mov esi, [hd_partitions_array+ecx*4]
mov edi, [hd_partitions_num+ecx*4]
test edi, edi
jz .hdxcont
.hdyloop:
push esi
call [lstrlenA]
push eax
push eax
push esi
push eax
push startcurdir
push 1
push 800h
call [CompareStringA]
cmp eax, 2
pop eax
jz .hdxy
add esi, 512
dec edi
jnz .hdyloop
.hdxcont:
pop ecx
inc ecx
cmp ecx, 4
jb .hdxloop
mov esi, aPathUnknown
jmp fail
.ramdisk:
push eax
mov edi, [header+20h]
add edi, [base]
mov eax, '/RD/'
stosd
mov ax, '1/'
stosw
jmp .common
.hdxy:
pop ecx
sub esi, [hd_partitions_array+ecx*4]
shr esi, 9
inc esi
push eax
mov edi, [header+20h]
add edi, [base]
push esi
push ecx
push hdxy_str
push edi
call [wsprintfA]
add esp, 10h
add edi, eax
.common:
pop eax
lea esi, [startcurdir+eax]
.l:
lodsb
cmp al, '\'
jnz @f
mov al, '/'
@@:
stosb
test al, al
jnz .l
mov eax, [header+20h]
add eax, [base]
push eax
push eax
call [CharToOemA]
path_done:
; create window
; push 0
; push 16
; push 16
; push 1
; push 1
; push 400000h
; call [LoadImageA]
; push eax ; hIconSm
push ebx ; hIconSm
push classname ; lpszClassName
push ebx ; lpszMenuName
push ebx ; hbrBackground
push 32512
push ebx
call [LoadCursorA]
mov [hArrow], eax
push eax ; hCursor
; push ebx ; hIcon
push 1
push 400000h
call [LoadIconA]
push eax ; hIcon
push 400000h ; hInstance
push ebx ; cbWndExtra
push ebx ; cbClsExtra
push wndproc ; lpfnWndProc
push 3 ; style = CS_HREDRAW or CS_VREDRAW
push 48 ; cbSize
push esp
call [RegisterClassExA]
add esp, 48
push ebx ; lpParam
push 400000h ; hInstance
push ebx ; hMenu
push ebx ; hWndParent
mov eax, 80000000h ; CW_USEDEFAULT
push eax ; nHeight
push eax ; nWidth
push eax ; y
push eax ; x
push eax ; dwStyle = WS_POPUP
; push ebx ; lpWindowName
mov esi, inname
mov edx, esi
@@:
lodsb
cmp al, 0
jz .done
cmp al, '\'
jz .x
cmp al, '/'
jz .x
cmp al, ':'
jnz @b
.x: mov edx, esi
jmp @b
.done:
dec esi
cmp byte [esi-1], '.'
jnz @f
dec esi
mov byte [esi], 0
@@:
push edx
mov [process_name], edx
push classname ; lpClassName
push ebx ; dwExStyle
call [CreateWindowExA]
mov [ebp+tls.hWnd], eax
mov [ebp+tls.bActive], 1
mov [ebp+tls.bFirstMouseMove], 1
test eax, eax
mov esi, createwnderr
jz fail
call get_cur_slot_ptr
mov [edi+shared_data_struc.hWnd-shared_data_struc.threads], eax
cmp [edi+shared_data_struc.thread_id-shared_data_struc.threads], 2
jnz .notfirst
mov esi, [shared_data]
cmp [esi+shared_data_struc.vk], 0
jnz .workarea_vk
push ebx
lea eax, [esi+shared_data_struc.workarea_left]
push eax
push ebx
push 30h ; SPI_GETWORKAREA
call [SystemParametersInfoA]
dec [esi+shared_data_struc.workarea_right]
dec [esi+shared_data_struc.workarea_bottom]
jmp .workarea_set
.workarea_vk:
push esi
call get_screen_size
pop esi
inc ebx
mov word [esi+shared_data_struc.workarea_bottom], bx
shr ebx, 10h
inc ebx
mov [esi+shared_data_struc.workarea_right], ebx
xor ebx, ebx
.workarea_set:
.notfirst:
push newprg_section_name
push 1000h
push ebx
push 4
push ebx
push -1
call [CreateFileMappingA]
push eax
mov esi, shared_section_create_err
test eax, eax
jz fail
push ebx
push ebx
push ebx
push 2
push eax
call [MapViewOfFile]
pop ecx
push eax
push ecx
call [CloseHandle]
pop eax
push eax
cmp word [eax], 0x201
jnz @f
mov ecx, [ebp+tls.hWnd]
mov [eax+2], ecx
mov byte [eax+1], 3
@@:
call [UnmapViewOfFile]
; allocate LDT selectors
; data segment
mov esi, selector_data
mov eax, [base]
mov [esi+2], ax
shr eax, 10h
mov [esi+4], al
mov [esi+7], ah
mov eax, [header+14h]
dec eax
mov [limit], eax
mov [fn9limit], eax
call get_cur_slot_ptr
mov [edi+24], eax
shr eax, 0Ch
mov [esi], ax
shr eax, 10h
or al, 11000000b
mov [esi+6], al
mov byte [esi+5], 11110010b
lea edi, [esi+8]
; code segment
movsd
movsd
mov byte [esi+5], 11111010b
cmp [bIs9x], 0
jnz alloc_ldt_9x
push ntdll_name
call [GetModuleHandleA]
push aNtSetLdtEntries
push eax
call [GetProcAddress]
mov [NtSetLdtEntries], eax
push dword [esi-4]
push dword [esi-8]
push 17h
push dword [esi+4]
push dword [esi]
push 0Fh
call eax
mov esi, ldterr
test eax, eax
js fail
mov eax, [DSA]
test eax, eax
jz @f
push ebx
push ebx
push ebx
mov edx, eax
mov dx, (11000000b shl 8) + 11110010b
ror edx, 16
xchg dl, dh
ror edx, 8
push edx
shl eax, 16
mov ax, 0FFFh
push eax
push 1Fh
call [NtSetLdtEntries]
test eax, eax
js fail
mov [_gs], 1Fh
@@:
dorunklbr:
; jump to program code
mov eax, [header+18h]
mov [ebp+tls._esp], eax
mov eax, [header+0Ch]
mov [ebp+tls._eip], eax
push 3200h ; eflags
xor eax, eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
push eax
; Kolibri process was successfully created, notify parent
call get_cur_slot_ptr
mov [edi+shared_data_struc.win32_stack-shared_data_struc.threads], esp
mov [bInitialized], 1
notify_parent:
div edx
jmp i40_done
 
alloc_ldt_9x:
mov eax, r0p
call CallRing0
; patch int40
add edi, (40h-9)*8
mov eax, i40_9x
mov [edi], ax
mov word [edi+2], cs
shr eax, 16
mov [edi+6], ax
mov word [edi+4], 1110111100000000b
xor ebx, ebx
jmp dorunklbr
free_ldt:
cmp [bIs9x], 0
jnz @f
.ret: ret
@@:
cmp [temp_cs], 0
jz .ret
mov eax, fl0p
 
CallRing0:
call acquire_shared ; int 9 is global resource
sidt [idtr]
mov edi, dword [idtr+2]
add edi, 8*9
push dword [edi]
push dword [edi+4]
mov [edi], ax
mov word [edi+2], 28h
; mov word [edi+4], 0xEE00
; shr eax, 16
; mov [edi+6], ax
mov [edi+4], eax
mov word [edi+4], 0xEE00
int 9
pop dword [edi+4]
pop dword [edi]
call release_shared
ret
 
r0p:
int 20h ; VMMCall Get_Cur_VM_Handle
dw 1
dw 1
push 0
push 1
push dword [esi]
push dword [esi+4]
push ebx
int 20h ; VMMCall _Allocate_LDT_Selector
dw 78h
dw 1
add esp, 14h
mov [klbr_cs], ax
push 0
push 1
push dword [esi-8]
push dword [esi-4]
push ebx
int 20h ; VMMCall _Allocate_LDT_Selector
dw 78h
dw 1
add esp, 14h
mov [klbr_ds], ax
mov eax, [DSA]
test eax, eax
jz @f
push 0
push 1
mov edx, eax
mov dx, (11000000b shl 8) + 11110010b
ror edx, 16
xchg dl, dh
ror edx, 8
shl eax, 16
mov ax, 0FFFh
push eax
push edx
push ebx
int 20h ; VMMCall _Allocate_LDT_Selector
dw 78h
dw 1
add esp, 14h
mov [_gs], ax
@@:
push 0
push 1
mov eax, temp_code
mov ecx, eax
shl eax, 16
add eax, temp_code_size-1
push eax
mov eax, ecx
and eax, 0xFF000000
add eax, 0000000011111011b shl 8
shr ecx, 16
mov al, cl
push eax
push ebx
int 20h ; VMMCall _Allocate_LDT_Selector
dw 78h
dw 1
add esp, 14h
mov [temp_cs], ax
mov [temp_cs2], ax
push 0
push 1
mov eax, temp_stack
mov ecx, eax
shl eax, 16
add eax, temp_stack_size-1
push eax
mov eax, ecx
and eax, 0xFF000000
add eax, 0000000011110011b shl 8
shr ecx, 16
mov al, cl
push eax
push ebx
int 20h ; VMMCall _Allocate_LDT_Selector
dw 78h
dw 1
add esp, 14h
mov [temp_ss], ax
; mov eax, 40h
; mov cx, [_cs]
; mov edx, i40_9x
; int 20h ; VMMCall Set_PM_Int_Vector
; dw 45h
; dw 1
; xor ecx, ecx
; xor edx, edx
; int 20h ; VMMCall Get_PM_Int_Vector
; dw 44h
; dw 1
iret
fl0p:
int 20h ; VMMCall Get_Cur_VM_Handle
dw 1
dw 1
movzx eax, [klbr_cs]
call free_selector
movzx eax, [klbr_ds]
call free_selector
movzx eax, [temp_cs]
call free_selector
movzx eax, [temp_ss]
call free_selector
xor ebx, ebx
iret
sl0p:
int 20h ; VMMCall Get_Cur_VM_Handle
dw 1
dw 1
push 0
push dword [esi]
push dword [esi+4]
push ebx
movzx eax, [klbr_cs]
push eax
int 20h ; VMMCall _SetDescriptor
dw 7Ch
dw 1
push 0
push dword [esi-8]
push dword [esi-4]
push ebx
movzx eax, [klbr_ds]
push eax
int 20h ; VMMCall _SetDescriptor
dw 7Ch
dw 1
add esp, 40
iret
rdmsrp:
; rdmsr may throw exception
mov esi, .exception_struc
int 20h ; VMMCall Install_Exception_Handler
dw 0EFh
dw 1
xor ebx, ebx ; assume OK
.start_eip:
rdmsr
.end_eip:
mov esi, .exception_struc
int 20h ; VMMCall Remove_Exception_Handler
dw 0F0h
dw 1
iret
.exception_struc:
dd 0
dd .start_eip
dd .end_eip
dd .exception_handler
.exception_handler:
inc ebx
jmp .end_eip
 
free_selector:
push 0
push eax
push ebx
int 20h ; VMMCall _Free_LDT_Selector
dw 79h
dw 1
add esp, 12
ret
 
seh:
mov eax, [esp+12]
add dword [eax+0xB8], 2
xor eax, eax
ret
 
ofn_hook:
cmp dword [esp+8], 2 ; WM_DESTROY
jnz @f
push 260
mov eax, converted_path
mov [parameters], eax
push eax
push 23
push dword [esp+12+4]
push user32_name
call [GetModuleHandleA]
push GetDlgItemTextA_thunk+2
push eax
call [GetProcAddress]
call eax
@@:
xor eax, eax
ret 10h
 
getfilename:
@@:
lodsb
cmp al, 0
jz .not
cmp al, ' '
jbe @b
cmp al, '"'
setz dl
jz .loo
dec esi
.loo:
lodsb
cmp al, 0
jz .end
cmp al, ' '
ja @f
test dl, 1
jz .end
@@: cmp al, '"'
jnz @f
test dl, 1
jnz .end_quote
@@: stosb
jmp .loo
.end_quote:
lodsb
.end:
or al, al
jnz @f
dec esi
@@: mov al, 0
stosb
clc
ret
.not:
stc
ret
 
map_shared_data:
push 0
push 0
push 0
push 2
push [hSharedData]
call [MapViewOfFile]
mov [shared_data], eax
ret
 
acquire_shared:
pushad
push -1
push [hSharedMutex]
call [WaitForSingleObject]
popad
ret
release_shared:
pushad
push [hSharedMutex]
call [ReleaseMutex]
popad
ret
 
get_cur_slot_ptr_server:
push eax
mov eax, [cur_slot]
@@:
call get_slot_ptr
pop eax
ret
get_cur_slot_ptr:
push eax
mov eax, [ebp+tls.cur_slot]
jmp @b
get_slot_ptr:
mov edi, [shared_data]
shl eax, 6
lea edi, [eax+edi+shared_data_struc.threads]
ret
 
read_color:
push esi
mov ecx, 6
xor edx, edx
.l:
lodsb
cmp al, 0
jz .d
or al, 20h
sub al, '0'
cmp al, 10
jb @f
sub al, 'a'-10-'0'
@@:
shl edx, 4
or dl, al
loop .l
.d:
pop esi
xchg eax, edx
ret
 
i40_9x:
; set Win32 context
push eax ecx
mov eax, [cs:tls_index]
shl eax, 2
add eax, [fs:2Ch]
mov eax, [cs:eax]
mov ds, [cs:eax+tls._ds]
mov es, [eax+tls._ds]
; mov fs, [_fs]
mov ecx, [esp+8] ; eip
dec ecx
dec ecx
mov [eax+tls._eip], ecx
mov ecx, [esp+16] ; eflags
mov ss, [eax+tls._ds]
xchg esp, [eax+tls._esp]
push ecx
add [eax+tls._esp], 20
mov eax, [eax+tls._esp]
add eax, [base]
mov ecx, [eax-20]
mov eax, [eax-16]
popfd
 
exception:
pushfd
cld
; test for page fault in direct screen area
push ebp eax
mov eax, [tls_index]
mov ebp, [fs:2Ch]
mov ebp, [ebp+eax*4]
mov eax, [ebp+tls.saved_fs0]
mov [fs:0], eax
mov eax, [ebp+tls.saved_fs4]
mov [fs:4], eax
cmp [ebp+tls.exc_code], 0C0000005h
jnz noaccvio
mov eax, [ebp+tls.exc_data]
sub eax, [DSA]
cmp eax, 0FFFFFFh
ja noaccvio
; handle page fault in direct screen area
pop eax ebp
pushad
mov ebp, [tls_index]
shl ebp, 2
add ebp, [fs:2Ch]
mov ebp, [ebp]
push DSACritSect
call [EnterCriticalSection]
cmp [bHaveDSA], 0
jnz dsafail
call get_screen_size
mov eax, ebx
shr eax, 16
movzx ebx, bx
inc eax
inc ebx
mov edi, eax
mul ebx
mul [ColorDepth]
shr eax, 3
add eax, 0xFFF
and eax, not 0xFFF
mov ecx, [ebp+tls.exc_data]
sub ecx, [DSA]
cmp ecx, eax
jb @f
dsafail:
push DSACritSect
call [LeaveCriticalSection]
push 40h
push 0
push DSAErr
push 0
mbni:
call [MessageBoxA]
popad
push ebp eax
mov ebp, [tls_index]
shl ebp, 2
add ebp, [fs:2Ch]
mov ebp, [ebp]
jmp notint40
@@:
push 4
push 1000h
push eax
push [DSA]
call [VirtualAlloc]
; get screen data
push ebp
push 0
call [GetDC]
push eax
xchg eax, ebp
call [CreateCompatibleDC]
xchg eax, esi
push ebx
push edi
push ebp
call [CreateCompatibleBitmap]
push eax
push esi
call [SelectObject]
push eax
xor eax, eax
push 0xCC0020
push eax
push eax
push ebp
push ebx
push edi
push eax
push eax
push esi
call [BitBlt]
push esi
call [SelectObject]
push ebp
xchg eax, ebp
xor eax, eax
; now esi=hDC, ebp=hBitmap
push eax ; biClrImportant
push eax ; biClrUsed
push eax ; biYPelsPerMeter
push eax ; biXPelsPerMeter
push eax ; biSizeImage
push eax ; biCompression
push 1 ; biPlanes
mov ecx, [ColorDepth]
mov [esp+2], cx ; biBitColor
neg ebx
push ebx ; biHeight
neg ebx
push edi ; biWidth
push 40 ; biSize
mov ecx, esp
push eax
push ecx
push [DSA]
push ebx
push eax
push ebp
push esi
call [GetDIBits]
add esp, 40
push ebp
call [DeleteObject]
push esi
call [DeleteDC]
push 0
call [ReleaseDC]
mov [bHaveDSA], 1
push eax
push esp
push 0
push 0
push DSAFreeThread
push 10000h
push 0
call [CreateThread]
pop eax
push DSACritSect
call [LeaveCriticalSection]
pop ebp
mov ebp, [tls_index]
shl ebp, 2
add ebp, [fs:2Ch]
mov ebp, [ebp]
jmp i40_done
noaccvio:
; test for int40
mov eax, [ebp+tls._eip]
cmp eax, [limit]
jae notint40
add eax, [base]
cmp word [eax], 0x40CD
jz int40
notint40:
 
pop eax
push esi
sub esp, 400h
mov esi, esp
push dword [esi+408h]
push [ebp+tls._eip]
push dword [esi+404h]
push [ebp+tls._esp]
push edi
push dword [esi+400h]
push edx
push ecx
push ebx
push eax
push excstr
push esi
call [wsprintfA]
push 0
push exceptionstr
push esi
push 0
call [MessageBoxA]
lock dec [NumThreads]
jnz .et
call free_ldt
push 0
call [ExitProcess]
.et:
push 0
call [ExitThread]
 
int40:
add [ebp+tls._eip], 2
pop eax ebp
pushad
safe_to_suspend:
mov ebp, [tls_index]
shl ebp, 2
add ebp, [fs:2Ch]
mov ebp, [ebp]
inc eax
cmp eax, num_i40_fns
push eax ; emulate ret addr for not_supported_i40_fn
jae not_supported_i40_fn
pop eax
call [i40fns + eax*4]
i40_done:
cmp [NumThreads], 1
jnz i40_done_mt
mov eax, [ebp+tls._esp]
mov [klbr_esp], eax
mov eax, [ebp+tls._eip]
mov [jmp_klbr_eip], eax
lea eax, [esp+24h]
mov [ebp+tls._esp], eax
mov [ebp+tls._eip], exception
mov eax, [fs:0]
mov [ebp+tls.saved_fs0], eax
mov eax, [fs:4]
mov [ebp+tls.saved_fs4], eax
popad
popfd
mov ss, [klbr_ds]
mov esp, [klbr_esp]
mov es, [klbr_ds]
; mov fs, [klbr_null]
; mov gs, [klbr_null]
mov gs, [_gs]
mov ds, [klbr_ds]
i40_done_jmp1:
jmp [cs:jmp_klbr]
i40_done_mt:
mov eax, [ebp+tls._esp]
mov [esp+12], eax
mov ecx, [ebp+tls._eip]
xchg [fs:0], ecx
mov [ebp+tls.saved_fs0], ecx
movzx ecx, [klbr_cs]
xchg [fs:4], ecx
mov [ebp+tls.saved_fs4], ecx
lea eax, [esp+24h]
mov [ebp+tls._esp], eax
mov [ebp+tls._eip], exception
popad
popfd
mov ss, [klbr_ds]
mov esp, [ds:esp-24h+12]
mov es, [klbr_ds]
; mov fs, [klbr_null]
; mov gs, [klbr_null]
mov gs, [_gs]
mov ds, [klbr_ds]
i40_done_jmp2:
jmp fword [fs:0]
 
not_supported_i40_fn:
sub esp, 200h-4
mov esi, esp
push dword [esi+200h+20h]
push [ebp+tls._eip]
push dword [esi+200h+8]
push [ebp+tls._esp]
push dword [esi+200h]
push dword [esi+200h+4]
push dword [esi+200h+14h]
push dword [esi+200h+18h]
push dword [esi+200h+10h]
push dword [esi+200h+1Ch]
push notsupportedmsg
push esi
call [wsprintfA]
push 0
push nsm
push esi
push 0
call [MessageBoxA]
i40_terminate:
lock dec [NumThreads]
jnz .thread
call free_ldt
push 0
call [ExitProcess]
.thread:
push 0
call [ExitThread]
 
align 4
i40fns dd i40_terminate ; -1
dd i40_draw_window ; 0
dd i40_put_pixel ; 1
dd i40_getkey ; 2
dd i40_get_sys_time ; 3
dd i40_writetext ; 4
dd i40_delay ; 5
dd i40_read_floppy_file ; 6
dd i40_putimage ; 7
dd i40_define_button ; 8
dd i40_get_process_info ; 9
dd i40_wait_event ; 10
dd i40_check_event ; 11
dd i40_redraw_status ; 12
dd i40_drawrect ; 13
dd i40_get_screen_size ; 14
dd i40_set_background ; 15
dd not_supported_i40_fn ; 16
dd i40_getbutton ; 17
dd i40_sys_service ; 18
dd not_supported_i40_fn ; 19
dd not_supported_i40_fn ; 20
dd i40_sys_setup ; 21
dd not_supported_i40_fn ; 22
dd i40_wait_event_timeout ; 23
dd not_supported_i40_fn ; 24
dd not_supported_i40_fn ; 25
dd i40_getsetup ; 26
dd not_supported_i40_fn ; 27
dd not_supported_i40_fn ; 28
dd i40_get_sys_date ; 29
dd i40_current_folder ; 30
dd not_supported_i40_fn ; 31
dd i40_delete_ramdisk_file ; 32
dd i40_write_ramdisk_file ; 33
dd not_supported_i40_fn ; 34
dd i40_screen_getpixel ; 35
dd i40_screen_getarea ; 36
dd i40_read_mouse_pos ; 37
dd i40_draw_line ; 38
dd i40_get_background ; 39
dd i40_set_event_mask ; 40
dd not_supported_i40_fn ; 41
dd not_supported_i40_fn ; 42
dd not_supported_i40_fn ; 43
dd not_supported_i40_fn ; 44
dd not_supported_i40_fn ; 45
dd i40_reserve_free_ports ; 46
dd i40_display_number ; 47
dd i40_display_settings ; 48
dd not_supported_i40_fn ; 49
dd i40_set_window_shape ; 50
dd i40_create_thread ; 51
dd not_supported_i40_fn ; 52
dd not_supported_i40_fn ; 53
dd not_supported_i40_fn ; 54
dd i40_sound_interface ; 55
dd not_supported_i40_fn ; 56
dd not_supported_i40_fn ; 57
dd i40_file_system ; 58
dd not_supported_i40_fn ; 59
dd i40_ipc ; 60
dd i40_direct_scr_access ; 61
dd i40_pci ; 62
dd i40_debug_board ; 63
dd i40_resize_app_memory ; 64
dd i40_putimage_palette ; 65
dd i40_process_def ; 66
dd i40_move_resize ; 67
dd i40_sys_services ; 68
dd i40_debug_services ; 69
dd i40_file_system_lfn ; 70
dd i40_window_settings ; 71
num_i40_fns = ($ - i40fns)/4
 
getfilemap:
; in: esi->filename
; out: eax->mapped file
push esi
sub esp, 200h
cmp word [esi+1], ':\'
jz .fullpath
mov edi, esp
push esi
mov esi, startcurdir
@@:
lodsb
stosb
test al, al
jnz @b
pop esi
dec edi
mov al, '\'
cmp byte [edi-1], al
jz @f
stosb
@@:
lodsb
stosb
test al, al
jnz @b
mov esi, esp
.fullpath:
push ebx
push ebx
push 3 ; OPEN_EXISTING
push ebx
push 1 ; FILE_SHARE_READ
push 80000000h ; GENERIC_READ
push esi
call [CreateFileA]
add esp, 200h
pop esi
inc eax
jz .failed
dec eax
xchg eax, edi
push ebx
push ebx
push ebx
push 2 ; PAGE_READONLY
push ebx
push edi
call [CreateFileMappingA]
test eax, eax
jz .failed
push edi
xchg eax, edi
call [CloseHandle]
push ebx
push ebx
push ebx
push 4 ; FILE_MAP_READ
push edi
call [MapViewOfFile]
test eax, eax
jz .failed
push eax
push edi
call [CloseHandle]
pop eax
ret
.failed:
push ebx
push filereaderr
jmp fail2
 
DSAFreeThread:
push [InvalidateTime]
call [Sleep]
push DSACritSect
call [EnterCriticalSection]
push 4000h
push 0
push [DSA]
call [VirtualFree]
mov [bHaveDSA], 0
push DSACritSect
call [LeaveCriticalSection]
ret
 
virtual at 0
button_desc:
.next dd ? ; must be 1st dword
.id dd ?
.xsize dw ?
.xstart dw ?
.ysize dw ?
.ystart dw ?
.color dd ?
.size = $
end virtual
 
test_maximized:
sub esp, 40
push 44
push esp
push [ebp+tls.hWnd]
call [GetWindowPlacement]
mov eax, [esp+8] ; showCmd
add esp, 44
cmp eax, 3 ; SW_SHOWMAXIMIZED
ret
 
wndproc:
; LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
push ebp
mov ebp, [tls_index]
mov eax, [fs:2Ch]
mov ebp, [eax+ebp*4]
mov eax, [esp+8+4]
cmp eax, 0xF ; WM_PAINT
jz wmpaint
dec eax
; jz wmcreate
dec eax
jz wmdestroy
dec eax
jz wmmove
dec eax
dec eax
jz wmsize
dec eax
jz wmactivate
cmp eax, 0x1A-6
jz wmsettingchange
cmp eax, 0x20-6
jz wmsetcursor
cmp eax, 0x24-6
jz wmgetminmaxinfo
sub eax, 0x84-6
jz wmnchittest
cmp eax, 0xA1-0x84
jz wmnclbuttondown
cmp eax, 0xA3-0x84
jz wmnclbuttondblclk
sub eax, 0x100-0x84 ; WM_KEYDOWN
jz wmkeydown
dec eax
jz wmkeyup
dec eax
jz wmchar
dec eax
dec eax
jz wmsyskeydown
dec eax
jz wmsyskeyup
sub eax, 0x200-0x105 ; WM_MOUSEMOVE
jz wmmousemove
dec eax
jz wmlbuttondown
dec eax
jz wmlbuttonup
dec eax
dec eax
jz wmrbuttondown
dec eax
jz wmrbuttonup
cmp eax, 0x20A-0x205
jz wmmousewheel
cmp eax, 0x214-0x205
jz wmsizing
sub eax, 0x400-0x205 ; WM_USER
jz wm_ipc
cmp eax, 0xC000-0x400
jz vk_mouse
dec eax
jz wm_debug1
dec eax
jz wm_debug2
wmdef:
pop ebp
jmp [DefWindowProcA]
wmsettingchange:
call del_background
@@:
test [ebp+tls.message_mask], 10h
jz wmdef
mov [ebp+tls.translated_msg_code], 5
push 0
push 0
push 0
push dword [esp+20]
call [PostMessageA]
jmp wmdef
wmactivate:
mov eax, [shared_data]
mov ecx, [ebp+tls.cur_slot]
inc ecx
cmp word [esp+12+4], 0
jz .inact1
mov [eax+shared_data_struc.active_process], ecx
jmp .cmn1
.inact1:
call acquire_shared
cmp [eax+shared_data_struc.active_process], ecx
jnz @f
mov [eax+shared_data_struc.active_process], 1
@@: call release_shared
.cmn1:
mov al, byte [ebp+tls.color_main+3]
and al, 0Fh
cmp al, 3
jz .setactive
cmp al, 4
jnz wmdef
.setactive:
mov al, [esp+12+4]
mov [ebp+tls.bActive], al ; 0/1/2
wndproc_update_wnd:
mov [ebp+tls.curdraw], 0
push 0
push 0
push [ebp+tls.hWnd]
call [InvalidateRect]
jmp wmdef
wmpaint:
push esi
push edi
sub esp, 0x40
push esp
push [ebp+tls.hWnd]
call [BeginPaint]
; test [ebp+tls.message_mask], 1
; jz @f
; mov [ebp+tls.translated_msg_code], 1
@@: xchg eax, edi
cmp [ebp+tls.curdraw], 0
mov [ebp+tls.curdraw], 1
jz .nopaint
call draw_window_base
.nopaint:
push esp
push [ebp+tls.hWnd]
call [EndPaint]
add esp, 40h
pop edi
pop esi
pop ebp
xor eax, eax
ret 10h
wmdestroy:
push 0
call [PostQuitMessage]
@@:
xor eax, eax
pop ebp
ret 10h
wmnclbuttondown:
call test_maximized
jnz wmdef
push [ebp+tls.hWnd]
call [SetForegroundWindow]
jmp @b
;wmwindowposchanging:
; call test_maximized
; jnz @b
; mov eax, [esp+0x10+4]
; or byte [eax+18h], 2 ; SWP_NOMOVE
; jmp @b
wmnchittest:
; for window type 1 always return HTCLIENT
mov cl, byte [ebp+tls.color_main+3]
and cl, 0x0F
cmp cl, 0x01
jz .client
mov ax, [esp+0x10+4] ; x
sub ax, [ebp+tls.x_start]
mov dx, [esp+0x12+4] ; y
sub dx, [ebp+tls.y_start]
; test for caption
push eax
mov eax, [_skinh]
cmp cl, 0x03
jz @f
mov al, 21
@@:
cmp dx, ax
pop eax
jae .nocaption
; check for buttons
push esi
call find_button
test esi, esi
pop esi
jnz .button
.caption:
push 2 ; HTCAPTION
pop eax
pop ebp
ret 10h
.button:
.client:
push 1 ; HTCLIENT
jmp .ret
.nocaption:
; do not resize window with type 0
jecxz .client
; do not resize window with type 4
cmp ecx, 0x04000000
jz .client
; do not resize maximized window
push eax edx
call test_maximized
pop edx eax
jz .client
sub dx, [ebp+tls.y_size]
neg dx
cmp dx, 7
jbe .bottomall
cmp ax, 7
jbe .left
sub ax, [ebp+tls.x_size]
neg ax
cmp ax, 7
ja .client
push 11 ; HTRIGHT
jmp .ret
.left:
push 10 ; HTLEFT
.ret:
pop eax
pop ebp
ret 10h
.bottomall:
cmp ax, 7
jbe .bottomleft
sub ax, [ebp+tls.x_size]
neg ax
cmp ax, 7
ja .bottom
push 17 ; HTBOTTOMRIGHT
jmp .ret
.bottomleft:
push 16 ; HTBOTTOMLEFT
jmp .ret
.bottom:
push 15 ; HTBOTTOM
jmp .ret
wmsetcursor:
cmp [ebp+tls.hCursor], 0
jz wmdef
push [ebp+tls.hCursor]
call [SetCursor]
push 1
pop eax
pop ebp
ret 10h
wmnclbuttondblclk:
mov al, byte [ebp+tls.color_main+3]
and al, 0xF
jz .nomaximize
cmp al, 1
jz .nomaximize
cmp al, 4
jz .nomaximize
call test_maximized
mov eax, 3 ; SW_MAXIMIZED
jnz @f
mov al, 1 ; SW_SHOWNORMAL
@@:
push eax
push [ebp+tls.hWnd]
call [ShowWindow]
push 1
push 0
push [ebp+tls.hWnd]
call [InvalidateRect]
.nomaximize:
xor eax, eax
pop ebp
ret 10h
wmmove:
mov ax, [esp+0x10+4]
mov [ebp+tls.x_start], ax
mov ax, [esp+0x12+4]
mov [ebp+tls.y_start], ax
; jmp wndproc_update_wnd
xor eax, eax
pop ebp
ret 10h
wmsize:
mov ax, [esp+0x10+4]
mov [ebp+tls.x_size], ax
mov ax, [esp+0x12+4]
mov [ebp+tls.y_size], ax
; jmp wndproc_update_wnd
xor eax, eax
pop ebp
ret 10h
wmsizing:
mov eax, [esp+0x14]
mov ecx, [eax]
mov [ebp+tls.x_start], cx
mov ecx, [eax+4]
mov [ebp+tls.y_start], cx
mov ecx, [eax+8]
sub ecx, [eax]
mov [ebp+tls.x_size], cx
mov ecx, [eax+12]
sub ecx, [eax+4]
mov [ebp+tls.y_size], cx
; push 0
; push 0
; push [ebp+tls.hWnd]
; call [InvalidateRect]
xor eax, eax
inc eax
pop ebp
ret 10h
wmsyskeydown:
; test byte [esp+16+3+4], 20h ; Alt pressed?
; jnz wmdef
cmp byte [esp+16+2+4], 3Eh ; Alt+F4?
jz wmdestroy
wmkeydown:
movzx eax, byte [esp+16+2+4]
test eax, eax
jnz @f
mov al, 1Ch ; <Enter>
@@:
cmp [ebp+tls.usescancode], 0
jnz .putkeycode
; ignore keys-modifiers
cmp al, 2Ah
jz .ret
cmp al, 36h
jz .ret
cmp al, 38h
jz .ret
cmp al, 1Dh
jz .ret
cmp al, 3Ah
jz .ret
cmp al, 45h
jz .ret
cmp al, 46h
jz .ret
; translate NumPad keys
test byte [esp+14h+3], 1
jnz .nonumpad
mov cl, '*'
cmp al, 55
jz @f
cmp al, 71
jb .nonumpad
cmp al, 83
ja .nonumpad
mov cl, [numlock_map+eax-71]
@@:
push eax
push ecx
sub esp, 100h
push esp
call [GetKeyboardState]
mov al, [esp+0x90] ; VK_NUMLOCK
add esp, 100h
test al, 1
pop ecx
pop eax
jnz .put_cl
.nonumpad:
mov cl, [keymap+eax]
push eax
push ecx
push 0x11 ; VK_CONTROL
call [GetAsyncKeyState]
test ax, ax
jns @f
sub byte [esp], 60h
@@:
push 0x10 ; VK_SHIFT
call [GetAsyncKeyState]
test ax, ax
jns @f
pop ecx
pop eax
mov cl, [keymap_shift+eax]
push eax
push ecx
@@:
push 0x12 ; VK_MENU
call [GetAsyncKeyState]
test ax, ax
pop ecx
pop eax
jns @f
mov cl, [keymap_alt+eax]
@@:
.put_cl:
xchg eax, ecx
.putkeycode:
movzx ecx, [ebp+tls.keybuflen]
inc cl
jz .ret
; test for extended key (0xE0 prefix)
test byte [esp+14h+3], 1 ; lParam+3
jz .noext
cmp [ebp+tls.usescancode], 0
jz .noext
mov [ebp+tls.keybuflen], cl
mov [ebp+tls.keybuffer+ecx-1], 0xE0
inc cl
jz .ret
.noext:
mov [ebp+tls.keybuflen], cl
mov [ebp+tls.keybuffer+ecx-1], al
test [ebp+tls.message_mask], 2
jz @f
mov [ebp+tls.translated_msg_code], 2
@@:
.ret:
wmchar:
xor eax, eax
pop ebp
ret 10h
wmkeyup:
wmsyskeyup:
cmp [ebp+tls.usescancode], 0
jz wmkeydown.ret
mov al, [esp+16+2+4]
or al, 80h
jmp wmkeydown.putkeycode
;wmchar:
; cmp [usescancode], 0
; jnz wmkeydown.ret
; mov al, [esp+12]
; jmp wmkeydown.putkeycode
wmlbuttondown:
push esi
push 1
jmp @f
wmrbuttondown:
push esi
push 2
@@:
call capture1
mov ax, [esp+0x10+12] ; x
mov dx, [esp+0x12+12] ; y
call find_button
pop eax
test esi, esi
jnz .onbutton
test [ebp+tls.message_mask], 20h
jz @f
mov [ebp+tls.translated_msg_code], 6
@@:
.done:
pop esi
pop ebp
xor eax, eax
ret 10h
.onbutton:
or [ebp+tls.current_buttons], al
cmp [ebp+tls.original_buttons], 0
jnz @f
mov [ebp+tls.original_buttons], al
@@:
mov [ebp+tls.active_button], esi
; don't highlight button if bit 29 is set
test [esi+button_desc.id], 20000000h
jnz .done
; highlight - negate border
call negate_button_border
jmp .done
wmrbuttonup:
push -3
jmp @f
wmlbuttonup:
push -2
@@:
call capture2
pop eax
cmp [ebp+tls.active_button], 0
jz wmrbuttondown.nobutton
and [ebp+tls.current_buttons], al
jnz wmrbuttondown.nobutton
push esi
xor esi, esi
xchg esi, [ebp+tls.active_button]
test byte [esi+button_desc.id+3], 20h
jnz @f
call negate_button_border
@@:
; minimize button - special handler (see event.inc)
cmp word [esi+button_desc.id], 0FFFFh
jz .minimize
test [ebp+tls.message_mask], 4
jz @f
mov [ebp+tls.translated_msg_code], 3
@@:
test [ebp+tls.message_mask], 20h
jz @f
mov [ebp+tls.translated_msg_code], 86h
@@:
mov [ebp+tls.bFirstMouseMove], 1
movzx ecx, [ebp+tls.butbuflen]
inc cl
jz @f
mov [ebp+tls.butbuflen], cl
mov eax, [esi+button_desc.id]
shl eax, 8
mov al, [ebp+tls.original_buttons]
mov [ebp+tls.butbuffer+ecx*4-4], eax
@@:
mov [ebp+tls.original_buttons], 0
.done:
pop esi
.ret:
xor eax, eax
pop ebp
ret 10h
.minimize:
call minimize_window
jmp .done
wmrbuttondown.nobutton:
wmmousemove:
cmp [ebp+tls.bFirstMouseMove], 0
mov [ebp+tls.bFirstMouseMove], 0
jnz wmdef
vk_mouse:
; N.B. Due of current implementation of buttons in the kernel
; mouse events are NOT processed when any button is active!
cmp [ebp+tls.active_button], 0
jnz wmlbuttonup.ret
test [ebp+tls.message_mask], 20h
jz wmlbuttonup.ret
mov [ebp+tls.translated_msg_code], 6
jmp wmlbuttonup.ret
wmmousewheel:
movsx eax, word [esp+0xE+4]
sub [ebp+tls.scroll], eax
jmp vk_mouse
wm_ipc:
test [ebp+tls.message_mask], 40h
jz wmlbuttonup.ret
mov [ebp+tls.translated_msg_code], 7
jmp wmlbuttonup.ret
wm_debug1:
test byte [ebp+tls.message_mask+1], 1
jz .failed2
push edi
call get_cur_slot_ptr
mov edi, [edi+shared_data_struc.debugger_mem-shared_data_struc.threads]
test edi, edi
jz .failed
add edi, [base]
mov eax, [edi]
mov ecx, [edi+4]
sub eax, ecx
cmp eax, 12
jl .failed
add dword [edi+4], 12
lea edi, [edi+ecx+8]
xor eax, eax
inc eax
stosd
push edi
mov eax, [esp+0xC+12]
call get_slot_ptr
mov eax, [edi]
pop edi
stosd
mov eax, [esp+0x10+8]
; translate Win32 exception code to x86 exception vector
cmp eax, 0x80000004
jz .singlestep
xor ecx, ecx
push edi
mov edi, exccode2number-5
.1:
add edi, 5
cmp eax, [edi]
jnz .2
mov cl, [edi+4]
jmp .3
.2:
cmp dword [edi], ecx
jnz .1
mov cl, 0xD ; translate unrecognized codes to #GP
.3:
pop edi
jmp .4
.singlestep:
push ebx
mov ecx, [edi-4]
call find_debuggee
mov ecx, ebx
pop ebx
jecxz .failed
sub esp, 0xB2*4
push 1001Fh
push esp
push dword [ecx+12]
call [GetThreadContext]
mov ecx, [esp+0x14] ; DR6
mov byte [edi-8], 3 ; signal #DB
add esp, 0xB3*4
.4:
mov [edi], ecx
.written:
pop edi
mov [ebp+tls.translated_msg_code], 9
jmp wmlbuttonup.ret
.failed:
pop edi
.failed2:
push 40h
push 0
push aFailedToDeliverDebugMessage
push [ebp+tls.hWnd]
call [MessageBoxA]
jmp wmlbuttonup.ret
wm_debug2:
test byte [ebp+tls.message_mask+1], 1
jz wm_debug1.failed2
push edi
call get_cur_slot_ptr
mov edi, [edi+shared_data_struc.debugger_mem-shared_data_struc.threads]
test edi, edi
jz wm_debug1.failed
add edi, [base]
mov eax, [edi]
mov ecx, [edi+4]
sub eax, ecx
cmp eax, 8
jl wm_debug1.failed
add dword [edi+4], 8
lea edi, [edi+ecx+8]
push 2
pop eax
stosd
push edi
mov eax, [esp+0xC+12]
call get_slot_ptr
mov eax, [edi]
pop edi
stosd
; delete this item from debuggees list
lea ecx, [ebp+tls.debuggees]
@@:
mov edx, [ecx]
test edx, edx
jz wm_debug1.written
cmp dword [edx+4], eax
jz .found
mov ecx, edx
jmp @b
.found:
push dword [edx]
push ecx
push edx
call free
pop ecx
pop dword [ecx]
jmp wm_debug1.written
 
wmgetminmaxinfo:
mov ecx, [shared_data]
cmp [ecx+shared_data_struc.vk], 0
jnz @f
sub esp, 10h
mov eax, esp
push 0
push eax
push 0
push 30h ; SPI_GETWORKAREA
call [SystemParametersInfoA]
mov eax, [esp+20+10h] ; lParam
mov ecx, esp
mov edx, [ecx]
mov [eax+10h], edx
mov edx, [ecx+4]
mov [eax+14h], edx
mov edx, [ecx+8]
sub edx, [ecx]
mov [eax+8], edx
mov edx, [ecx+12]
sub edx, [ecx+4]
mov [eax+0Ch], edx
add esp, 10h
jmp .ret
@@:
call acquire_shared
mov eax, [esp+20] ; lParam
mov edx, [ecx+shared_data_struc.workarea_left]
mov [eax+10h], edx
mov edx, [ecx+shared_data_struc.workarea_top]
mov [eax+14h], edx
mov edx, [ecx+shared_data_struc.workarea_right]
sub edx, [ecx+shared_data_struc.workarea_left]
mov [eax+8], edx
mov edx, [ecx+shared_data_struc.workarea_bottom]
sub edx, [ecx+shared_data_struc.workarea_top]
mov [eax+0Ch], edx
call release_shared
.ret:
xor eax, eax
pop ebp
ret 10h
 
find_button:
mov esi, [ebp+tls.buttons]
.loop:
test esi, esi
jz .done
push eax
sub ax, [esi+button_desc.xstart]
cmp ax, [esi+button_desc.xsize]
pop eax
jae .cont
push edx
sub dx, [esi+button_desc.ystart]
cmp dx, [esi+button_desc.ysize]
pop edx
jb .done
.cont:
mov esi, [esi]
jmp .loop
.done:
ret
 
negate_button_border:
push edi
push [ebp+tls.hWnd]
call [GetDC]
xchg eax, edi
push 6 ; R2_NOT
push edi
call [SetROP2]
push eax
movzx eax, [esi+button_desc.xstart]
movzx edx, [esi+button_desc.ystart]
; point 4
push edx
push eax
; point 3
mov ecx, edx
add cx, [esi+button_desc.ysize]
push ecx
push eax
; point 2
push ecx
mov ecx, eax
add cx, [esi+button_desc.xsize]
push ecx
; point 1
push edx
push ecx
; point 0
push edx
push eax
; Polyline
mov eax, esp
push 5
push eax
push edi
call [Polyline]
add esp, 5*8
push edi
call [SetROP2]
push edi
push [ebp+tls.hWnd]
call [ReleaseDC]
pop edi
ret
 
draw_border:
mov eax, [ebp+tls.color_border]
shr eax, 1
and eax, 0x007F7F7F
cmp byte [esp+4], 0
jz @f
mov eax, [skin_active_outer]
cmp [ebp+tls.bActive], 0
jnz @f
mov eax, [skin_passive_outer]
@@:
call create_select_pen
push eax
xor esi, esi
call rect_wnd
call select_delete
mov eax, [ebp+tls.color_border]
cmp byte [esp+4], 0
jz @f
mov eax, [skin_active_frame]
cmp [ebp+tls.bActive], 0
jnz @f
mov eax, [skin_passive_frame]
@@:
call create_select_pen
push eax
@@:
inc esi
call rect_wnd
cmp esi, 3
jnz @b
call select_delete
mov eax, [ebp+tls.color_border]
shr eax, 1
and eax, 0x007F7F7F
cmp byte [esp+4], 0
jz @f
mov eax, [skin_active_inner]
cmp [ebp+tls.bActive], 0
jnz @f
mov eax, [skin_passive_inner]
@@:
call create_select_pen
push eax
inc esi
call rect_wnd
call select_delete
ret 4
 
rect_wnd:
movzx ecx, [ebp+tls.y_size]
dec ecx
sub ecx, esi
movzx edx, [ebp+tls.x_size]
dec edx
sub edx, esi
; point 5
push esi
push esi
; point 4
push esi
push edx
; point 3
push ecx
push edx
; point 2
push ecx
push esi
; point 1
push esi
push esi
mov eax, esp
push 5
push eax
push edi
call [Polyline]
add esp, 40
ret
 
rectangle_gradient:
; in: edi=hDC
; stack:
; [esp+4] = xstart
; [esp+8] = ystart
; [esp+12] = xend
; [esp+16] = yend (end is excluded)
; [esp+20] = color
; [esp+24] = color_delta (if gradient specified)
test byte [esp+20+3], 80h
jnz .dograd
; no gradient
mov eax, [esp+20]
call convert_color
push eax
call [CreateSolidBrush]
push eax
push dword [esp+4+16]
push dword [esp+8+12]
push dword [esp+12+8]
push dword [esp+16+4]
mov ecx, esp
push eax
push ecx
push edi
call [FillRect]
add esp, 10h
call [DeleteObject]
.done:
ret 24
.dograd:
; gradient
mov esi, [esp+8]
.gradloop:
cmp esi, [esp+16]
jae .done
mov eax, [esp+20]
call create_select_pen
push eax
push 0
push esi
push dword [esp+12+4]
push edi
call [MoveToEx]
push esi
push dword [esp+8+12]
push edi
call [LineTo]
call select_delete
inc esi
; mov eax, [esp+24]
; sub [esp+20], eax
test byte [esp+27], 80h
jnz .signed
mov al, [esp+24]
sub [esp+20], al
jnb @f
add [esp+20], al
@@: mov al, [esp+25]
sub [esp+21], al
jnb @f
add [esp+21], al
@@: mov al, [esp+26]
sub [esp+22], al
jnb @f
add [esp+22], al
@@: jmp .gradloop
.signed:
mov al, [esp+24]
add [esp+20], al
jnb @f
sub [esp+20], al
@@: mov al, [esp+25]
add [esp+21], al
jnb @f
sub [esp+21], al
@@: mov al, [esp+26]
add [esp+22], al
jnb @f
sub [esp+22], al
@@: jmp .gradloop
 
create_select_pen:
call convert_color
push eax
push 1
push 0
call [CreatePen]
push eax
push edi
call [SelectObject]
ret
select_delete:
push dword [esp+4]
push edi
call [SelectObject]
push eax
call [DeleteObject]
ret 4
 
malloc:
push dword [esp+4]
push 0
push [hHeap]
call [HeapAlloc]
ret 4
free:
push dword [esp+4]
push 0
push [hHeap]
call [HeapFree]
ret 4
malloc_big:
push 4 ; PAGE_READWRITE
push 1000h ; MEM_COMMIT
push eax
push 0
call [VirtualAlloc]
ret
free_big:
push 8000h ; MEM_RELEASE
push 0
push dword [esp+12]
call [VirtualFree]
ret 4
 
capture1:
inc [bCaptured]
cmp [bCaptured], 1
jnz @f
push [ebp+tls.hWnd]
call [SetCapture]
@@: ret
capture2:
cmp [bCaptured], 0
jz @f
dec [bCaptured]
jnz @f
call [ReleaseCapture]
@@: ret
 
server_fail:
push 10h
push 0
push esi
push 0
call init_MessageBox
call [MessageBoxA]
push 0
call [ExitProcess]
 
server_exists:
mov esi, vkerr
cmp [vk], 0
jnz server_fail
mov al, 1
mov edx, [newprg_section]
lock xchg [edx], al
test al, al
jz @f
push edx
push 200
call [Sleep]
pop edx
dec edi
jnz server_exists
@@:
mov esi, inname
lea edi, [edx+8]
mov ecx, 108h/4
rep movsd
mov esi, [parameters]
test esi, esi
jnz @f
mov esi, converted_path
@@: mov ecx, 100h/4
rep movsd
mov byte [edx+1], 1
mov esi, edx
push 50
pop edi
@@:
push 200
call [Sleep]
cmp byte [esi+1], 3
jz @f
dec edi
jnz @b
push ebx
call [ExitProcess]
@@:
push esi
push user32_thunks
push user32_name
call init_dll
pop esi
push dword [esi+2]
call [SetForegroundWindow]
mov word [esi], bx
push ebx
call [ExitProcess]
 
newprg_request:
lea edi, [eax+8]
lea esi, [eax+110h]
call acquire_shared
call new_kolibri_process_with_default_curdir
call release_shared
mov eax, [newprg_section]
mov byte [eax+1], 2
jmp debugloop
 
server:
push edi
call free_big
sub esp, 44h
push esp
call [GetStartupInfoA]
mov eax, [esp+8]
test eax, eax
jz @f
cmp dword [eax], 'Koli'
jnz @f
cmp dword [eax+4], 'briD'
jnz @f
mov [vk], 1
@@:
push newprg_section_name
push 1000h
push ebx
push 4
push ebx
push -1
call [CreateFileMappingA]
mov esi, shared_section_create_err
test eax, eax
jz server_fail
xchg eax, edi
call [GetLastError]
push eax
push ebx
push ebx
push ebx
push 2
push edi
call [MapViewOfFile]
mov [newprg_section], eax
test eax, eax
jz server_fail
; push edi
; call [CloseHandle]
pop eax
cmp eax, 183
jz server_exists
mov ecx, [esp+2Ch]
add esp, 44h
test cl, cl
js @f
cmp [vk], 0
jnz @f
; We were created without STARTF_FORCEOFFFEEDBACK flag.
; Rerun self. This has two goals: first, this avoids "hour glass" cursor,
; second, if GetOpenFileNameA was used, it didn't cleanup all resources,
; but new process will run in clean environment.
push [newprg_section]
call [UnmapViewOfFile]
push edi
call [CloseHandle]
mov [bDontDebug], 1
call create_child
push ebx
call [ExitProcess]
@@:
if 0
push ebx
push ebx
push ebx
call [GetCurrentThreadId]
push eax
call [PostThreadMessageA]
sub esp, 40h
mov eax, esp
push ebx
push ebx
push ebx
push eax
call [GetMessageA]
add esp, 40h
end if
; create shared data
push ebx
push shared_section_size
push ebx
push 4
push ebx
push -1
call [CreateFileMappingA]
test eax, eax
jz server_fail
mov [hSharedData], eax
push ebx
push ebx
push ebx
call [CreateMutexA]
mov esi, shared_mutex_create_err
test eax, eax
jz server_fail
mov [hSharedMutex], eax
call map_shared_data
xor ecx, ecx
inc ecx
mov dword [eax], ecx ; 1 process (OS/IDLE)
mov dword [eax+4], ecx ; 1 process
mov [eax+shared_data_struc.active_process], ecx
mov [eax+shared_data_struc.thread_id], ecx ; PID=1
mov [eax+shared_data_struc.sound_dma], ecx
mov [eax+shared_data_struc.fat32part], ecx
mov [eax+shared_data_struc.hd_base], cl
mov [eax+shared_data_struc.mouse_delay], 10
mov [eax+shared_data_struc.mouse_speed_factor], 3
xchg eax, esi
mov al, [vk]
or [esi+shared_data_struc.vk], al
mov [esi+shared_data_struc.pci_data_init], bl
; read ini file server settings
mov edi, aSetup
push win32_path
push ebx
push aSoundFlag
push edi
call [GetPrivateProfileIntA]
mov [esi+shared_data_struc.sound_flag], al
push win32_path
push 1
push aSysLang
push edi
call [GetPrivateProfileIntA]
mov [esi+shared_data_struc.syslang], eax
push win32_path
push 1
push aKeyboard
push edi
call [GetPrivateProfileIntA]
mov [esi+shared_data_struc.keyboard], ax
mov ebp, esi
mov ecx, 1028
sub esp, ecx
mov esi, esp
mov edi, aMain
push win32_path
push ecx
push esi
push null_string
push aAllowReadMSR
push edi
call [GetPrivateProfileStringA]
cmp byte [esi], 't'
setz [ebp+shared_data_struc.bAllowReadMSR]
push win32_path
push 1028
push esi
push null_string
push aAllowReadPCI
push edi
call [GetPrivateProfileStringA]
cmp byte [esi], 't'
setz [ebp+shared_data_struc.bAllowReadPCI]
setz byte [ebp+shared_data_struc.pci_access_enabled]
push win32_path
push 1028
push esi
push null_string
push aKeepLoadedDriver
push edi
call [GetPrivateProfileStringA]
cmp byte [esi], 't'
setz [keep_loaded_driver]
push win32_path
push 1028
push esi
push null_string
push aEnablePorts
push edi
call [GetPrivateProfileStringA]
; parse EnablePorts parameter
or eax, -1
lea edi, [ebp+shared_data_struc.DisabledPorts]
mov ecx, 1000h
rep stosd
ParseEnablePorts:
lodsb
test al, al
jz .done
cmp al, 0x20
jbe ParseEnablePorts
call read_hex
cmp al, '-'
jz .minus
mov edx, ecx
shr ecx, 3
and edx, 7
btr dword [ebp+shared_data_struc.DisabledPorts+ecx], edx
.x1: test al, al
jz .done
cmp al, 0x20
jbe ParseEnablePorts
.err:
mov esi, EnablePortsSyntaxErr
jmp server_fail
.minus:
push ecx
lodsb
call read_hex
cmp ecx, [esp]
jb .err
push eax
@@:
mov eax, ecx
shr ecx, 3
mov edx, eax
and edx, 7
btr dword [ebp+shared_data_struc.DisabledPorts+ecx], edx
test eax, eax
jz @f
lea ecx, [eax-1]
cmp ecx, [esp+4]
jae @b
@@:
pop eax
pop ecx
jmp .x1
.done:
add esp, 1028
xor eax, eax
cmp [bIs9x], al
jnz .skipload
cmp [ebp+shared_data_struc.bAllowReadMSR], bl
jnz .load
cmp [ebp+shared_data_struc.bAllowReadPCI], bl
jnz .load
mov ecx, 2000h
lea edi, [ebp+shared_data_struc.DisabledPorts]
mov al, -1
repz scasb
jz .skipload
.load:
; load driver kiw0.sys
; note that this must execute after all work with ini-file
; because win32_path is overwritten
call load_kiw0
.skipload:
call create_child
debugloop:
mov eax, [newprg_section]
cmp byte [eax+1], 1
jz newprg_request
push 500 ; wait a half of second
push debugevent
call [WaitForDebugEvent]
test eax, eax
jz debugloop
; get hProcess
mov eax, [debugevent+4]
mov ecx, [pids]
@@: cmp [ecx+4], eax
jz @f
mov ecx, [ecx]
jmp @b
@@: mov eax, [ecx+8]
mov [hProcess], eax
; parse debug event
mov eax, [debugevent] ; dwDebugEventCode
dec eax ; EXCEPTION_DEBUG_EVENT = 1
jz exceptionevent
dec eax ; CREATE_THREAD_DEBUG_EVENT = 2
jz threadcreated
dec eax ; CREATE_PROCESS_DEBUG_EVENT = 3
jz processcreated
dec eax ; EXIT_THREAD_DEBUG_EVENT = 4
jz threadexited
dec eax ; EXIT_PROCESS_DEBUG_EVENT = 5
jz exited
debugcont:
push 10002h ; DBG_CONTINUE
dodebugcont:
push [debugevent+8]
push [debugevent+4]
call [ContinueDebugEvent]
jmp debugloop
exited:
; delete Win32 pid and tid
mov eax, [debugevent+4]
mov ecx, pids
call delete_id
call find_tid
jecxz @f
call on_thread_exited
mov eax, [debugevent+8]
mov ecx, tids
call delete_id
@@:
; if all processes are done, exit
dec [num_kolibri_proc]
jnz debugcont
jmp server_done
threadcreated:
mov eax, [debugevent+12]
mov [hThread], eax
mov eax, [debugevent+8]
mov [dwThreadId], eax
call alloc_thread
mov eax, [debugevent+16]
mov ecx, [cur_tid_ptr]
mov [ecx+16], eax
mov [ecx+20], ebx
jmp debugcont
processcreated:
call find_tid
test ecx, ecx
jz debugcont
push [debugevent+12]
call [CloseHandle]
mov eax, [debugevent+24h]
mov ecx, [cur_tid_ptr]
mov [ecx+16], eax
jmp debugcont
threadexited:
call find_tid
test ecx, ecx
jz debugcont
cmp [cur_slot], -1
jz @f
call on_thread_exited
@@:
mov eax, [debugevent+8]
mov ecx, tids
call delete_id
jmp debugcont
exceptionevent:
call find_tid
test eax, eax
jz debugcont
; special handling of #PF exceptions in shared memory areas
cmp [debugevent+12], 0xC0000005
jnz .nopf
mov ecx, [debugevent+36]
call get_cur_slot_ptr_server
mov edi, [edi+shared_data_struc.shmem_list-shared_data_struc.threads]
.scanaddr:
test edi, edi
jz .nopf
cmp ecx, [edi+shmem_proc_descr.ptr]
jb @f
cmp ecx, [edi+shmem_proc_descr.end]
jb .pfshared
@@:
mov edi, [edi+shmem_proc_descr.next]
jmp .scanaddr
.pfshared:
; this is really exception in shared area
mov esi, [edi+shmem_proc_descr.item]
mov eax, [esi+shmem_item.pOwner]
cmp eax, ebx
jz .pfsh_noowner
call shmem_load
.pfsh_noowner:
mov edx, [edi+shmem_proc_descr.end]
mov ecx, [edi+shmem_proc_descr.ptr]
sub edx, ecx
push ecx edx
push eax
push esp
push 4 ; PAGE_READWRITE
push edx
push ecx
push [hProcess]
call [VirtualProtectEx]
pop eax
pop edx ecx
push ecx edx
push ebx
push edx
push [esi+shmem_item.ptr]
push ecx
push [hProcess]
call [WriteProcessMemory]
pop edx ecx
cmp dword [debugevent+32], ebx
jz .pfsh_read
cmp [edi+shmem_proc_descr.access], ebx
jz .nopf
mov [esi+shmem_item.pOwner], edi
mov eax, [hProcess]
mov [esi+shmem_item.hOwner], eax
jmp debugcont
.pfsh_read:
push eax
push esp
push 2 ; PAGE_READONLY
push edx
push ecx
push [hProcess]
call [VirtualProtectEx]
pop eax
jmp debugcont
.nopf:
; first exception is int3 in loader code
; ignore all exceptions before executing our code
; (there is one exception, debugging int3, in ntdll loader code,
; this exception must be continued as handled)
mov edi, context
push edi
push [hThread]
mov dword [edi], 1000Fh
call [GetThreadContext]
add edi, 0xB8
; breakpoints int3 (0xCC): decrement EIP (incremented by Windows)
cmp [debugevent+12], 0x80000003
jnz @f
dec dword [edi]
@@:
; single-step exceptions: restore TF flag (cleared by Windows)
mov dx, cs
mov eax, [edi]
mov ecx, [cur_tid_ptr]
cmp [debugevent+12], 0x80000004
jnz .noss
cmp word [edi+4], dx
jnz .set_tf
cmp eax, exception+1
jz @f
.set_tf:
or byte [edi+8+1], 1
@@:
cmp [ecx+52], ebx
mov [ecx+52], ebx
jnz x
cmp word [edi+4], dx
jnz .noss
cmp eax, i40_done_jmp1
jz .skipnext
cmp eax, i40_done_jmp2
jnz @f
.skipnext:
inc dword [ecx+52]
@@:
cmp eax, exception+1
jz x
cmp eax, i40_done
jb .noss
cmp eax, not_supported_i40_fn
jb x
.noss:
mov [ecx+52], ebx
mov esi, tls_index
push eax
push esp
push 4
push esi
push esi
push [hProcess]
call [ReadProcessMemory]
mov eax, [cur_tid_ptr]
mov eax, [eax+16]
add eax, 2Ch
mov ecx, esp
push ebx
push ecx
sub ecx, 4
push 4
push ecx
push eax
push [hProcess]
call [ReadProcessMemory]
pop eax
pop ecx
test eax, eax
jz debugcont
mov ecx, [esi]
cmp ecx, -1
jz debugcont
lea eax, [eax+ecx*4]
push eax
mov ecx, esp
push ebx
push ecx
sub ecx, 4
push 4
push ecx
push eax
push [hProcess]
call [ReadProcessMemory]
pop eax
pop ecx
; now eax -> TLS data
xchg eax, esi
push eax
push esp
push 24
push _cs
push esi
push [hProcess]
call [ReadProcessMemory]
pop eax
mov ax, [_cs]
test ax, ax
jz debugcont
; test for exceptions in Kolibri code
cmp word [context+0xBC], ax
jz process_exception
; debugged process?
mov edx, [cur_tid_ptr]
mov edi, [edx+20]
test edi, edi
jz .nodebuggee
; yes
; int40?
cmp [debugevent+12], 0xC0000005
jnz .exception2dbg
push edx edi
push ebx
mov ecx, esp
push ebx
push esp
push 4
push ecx
push base
call get_cur_slot_ptr_server
push [edi+shared_data_struc.win32_hBaseProcess-shared_data_struc.threads]
call [ReadProcessMemory]
lea ecx, [esp+4]
push esp
mov eax, [ecx]
push 2
add eax, [context+0xB8]
push ecx
push eax
push [edi+shared_data_struc.win32_hBaseProcess-shared_data_struc.threads]
call [ReadProcessMemory]
pop eax
pop ecx
pop edi edx
cmp al, 2
jnz .exception2dbg
cmp cx, 0x40CD
jz .nodebuggee
; suspend current thread and notify debugger
.exception2dbg:
push dword [edx+8]
call [SuspendThread]
push context
push [hThread]
call [SetThreadContext]
mov eax, [edi+12]
call get_slot_ptr
push [debugevent+12]
push [cur_slot]
push 401h
push [edi+shared_data_struc.hWnd-shared_data_struc.threads]
call init_MessageBox
call [PostMessageA]
jmp debugcont
.nodebuggee:
; set Win32 context
mov word [context+0xBC], ax
mov ax, [_ds]
mov word [context+0x98], ax
mov word [context+0x94], ax
mov word [context+0xC8], ax
mov ax, [_fs]
mov word [context+0x90], ax
; mov word [context+0x8C], 0
mov eax, [_eip]
xchg eax, [context+0xB8]
mov [_eip], eax
mov eax, [_esp]
xchg eax, [context+0xC4]
mov [_esp], eax
mov eax, [debugevent+12]
mov [exc_code], eax
mov eax, [debugevent+36]
mov [exc_data], eax
push eax
push esp
push 24
push _cs
push esi
push [hProcess]
call [WriteProcessMemory]
pop eax
x:
push context
push [hThread]
call [SetThreadContext]
jmp debugcont
process_exception:
mov eax, [context+0xB8]
cmp eax, server_test
jnz .no_server_test
mov eax, [debugevent+4]
mov ecx, [pids]
@@: cmp [ecx+4], eax
jz @f
mov ecx, [ecx]
jmp @b
@@:
mov edi, [ecx+12]
push ebx
push 1000h
push edi
push [context+0x9C]
push [hProcess]
call [WriteProcessMemory]
push edi
call free_big
mov eax, [cur_slot]
mov [context+0xB0], eax
mov eax, context+0xAC ; ecx
mov ecx, [hSharedData]
call DuplicateMyHandle
mov eax, context+0xA8 ; edx
mov ecx, [hSharedMutex]
call DuplicateMyHandle
jmp add2
.no_server_test:
cmp eax, server_new_thread
jnz @f
mov eax, [debugevent+8]
mov [dwThreadId], eax
call new_kolibri_thread
mov eax, [cur_slot]
mov [context+0xAC], eax
jmp add2
@@:
cmp eax, server_run_prg
jnz @f
; create new process
push ebx
push 4096
push process_curdir
push process_curdir
push [hProcess]
call [ReadProcessMemory]
mov eax, [context+0x9C]
mov edx, converted_path
mov edi, edx ; edi=name
call read_asciz
mov eax, [context+0xA0]
xor esi, esi ; esi=params
test eax, eax
jz .x
mov edx, win32_path
mov esi, edx
call read_asciz
.x:
mov eax, [cur_tid_ptr]
mov [parent_tid_ptr], eax
push 2 ; dwOptions = DUPLICATE_SAME_ACCESS
push ebx ; bInheritHandle
push ebx ; dwDesiredAccess
push context+0xAC ; lpTargetHandle
push [hProcess]
push eax
call new_kolibri_process
pop ecx
mov edx, [context+0xB0] ; flags for 70.7
mov [ecx+32], edx
mov [ecx+36], ebx
mov [ecx+40], ebx
; mov [context+0xB0], eax
mov [ecx+28], eax
push dword [ecx+24]
call [GetCurrentProcess]
push eax
call [DuplicateHandle]
jmp add2
@@:
cmp eax, server_get_run_result
jnz @f
mov esi, [cur_tid_ptr]
push dword [esi+24]
call [CloseHandle]
mov eax, [esi+28]
mov [context+0xB0], eax
mov eax, context+0xAC
mov ecx, [esi+36]
call DuplicateMyHandle
mov eax, context+0xA8
mov ecx, [esi+40]
call DuplicateMyHandle
mov eax, [esi+44]
mov [context+0xA0], eax
mov eax, [esi+48]
mov [context+0x9C], eax
jmp add2
@@:
cmp eax, set_wnd_colors
jnz @f
mov ecx, [context+0xA8]
and ecx, 7Fh
push ebx
push ecx
push common_colors
push [context+0xAC]
push [hProcess]
call [ReadProcessMemory]
mov [bCommonColorsSet], 1
add2:
add [context+0xB8], 2
jmp x
@@:
cmp eax, notify_parent
jnz nonotifyparent
mov eax, [cur_tid_ptr]
mov edi, [eax+20]
test edi, edi
jz add2
test byte [edi+32], 1
jz @f
push [hThread]
call [SuspendThread]
mov eax, [hProcess]
mov [edi+36], eax
mov eax, [hThread]
mov [edi+40], eax
mov eax, [context+0xB4]
mov [edi+44], eax
mov eax, [context+0xC4]
mov [edi+48], eax
jmp setparev
@@:
mov dword [eax+20], ebx
setparev:
push dword [edi+24]
call [SetEvent]
jmp add2
nonotifyparent:
cmp eax, loadfailed
jnz @f
mov ecx, [context+0xB0]
mov eax, [cur_tid_ptr]
mov edi, [eax+20]
test edi, edi
jz add2
mov [edi+28], ecx
jmp @b
@@:
cmp eax, get_wnd_colors
jnz @f
mov ecx, [context+0xA8]
and ecx, 7Fh
push ebx
push ecx
push common_colors
push [context+0xAC]
push [hProcess]
call [WriteProcessMemory]
mov al, [bCommonColorsSet]
mov byte [context+0xB0], al
jmp add2
@@:
cmp eax, set_button_style
jnz @f
mov ecx, [context+0xAC]
cmp cl, [buttontype]
jz add2
mov [buttontype], cl
call update_buttontype
jmp add2
@@:
cmp eax, server_send_ipc
jnz no_server_send_ipc
; find target slot
mov eax, [context+0xAC] ; ecx
mov esi, [shared_data]
mov ecx, [esi]
add esi, shared_data_struc.threads
@@:
cmp [esi], eax
jz @f
add esi, 64
loop @b
mov [context+0xB0], 4 ; no such PID
jmp .done
@@:
mov eax, [esi+4]
test eax, eax
jnz @f
mov [context+0xB0], 1 ; no IPC memory
jmp .done
@@:
push -1
mov ecx, esp
push ebx
push 4
push ecx
push eax
push dword [esi+12]
call [ReadProcessMemory]
pop ecx
jecxz @f
mov [context+0xB0], 2 ; IPC blocked
jmp .done
@@:
push ebx
mov eax, esp
push ebx
push 4
push eax
mov eax, [esi+4]
add eax, 4
push eax
push dword [esi+12]
call [ReadProcessMemory]
pop eax
mov ecx, [esi+8]
sub ecx, 8
sub ecx, eax
sub ecx, [context+0xA0] ; esi = message length
jns @f
mov [context+0xB0], 3 ; buffer overflow
jmp .done
@@:
mov edi, eax
add eax, 8
add eax, [context+0xA0]
push eax
mov eax, esp
push ebx
push 4
push eax
mov eax, [esi+4]
add eax, 4
push eax
push dword [esi+12]
call [WriteProcessMemory]
pop eax
add edi, [esi+4] ; edi = pointer to place for our message
; message header: dd source_pid, dd size
push [context+0xA0]
push edi
call get_cur_slot_ptr_server
mov eax, [edi]
pop edi
push eax
mov eax, esp
push ebx
push 8
push eax
push edi
push dword [esi+12]
call [WriteProcessMemory]
pop eax
pop eax
; now read message from source process and write it to target
push eax
call malloc
xchg eax, ebp
push ebx
push [context+0xA0]
push ebp
push [context+0xA8]
push [hProcess]
call [ReadProcessMemory]
add edi, 8
push ebx
push [context+0xA0]
push ebp
push edi
push dword [esi+12]
call [WriteProcessMemory]
push ebp
call free
mov [context+0xB0], ebx ; success
; now notify window of target handle
; push 0
; push 0
; push 400h ; WM_USER
; push dword [esi+20]
; call [PostMessageA]
; let source thread to notify target window
mov eax, [esi+20]
mov [context+0xAC], eax
.done:
jmp add2
no_server_send_ipc:
cmp eax, server_convert
jnz no_server_convert
mov eax, context+0xB0 ; eax
mov ecx, [eax]
call DuplicateMyHandle
jmp add2
no_server_convert:
cmp eax, ..server_create_shmem
jnz no_server_create_shmem
sub esp, 32
mov eax, esp
push ebx
push 32
push eax
push dword [context+0xAC] ; ecx
push [hProcess]
call [ReadProcessMemory]
test eax, eax
jnz @f
.invparam:
push 33 ; E_PARAM
pop edx
.ret:
add esp, 32
mov dword [context+0xB0], edx ; eax
jmp add2
@@:
; scan for shared memory area with requested name
mov edx, [shmem_list]
.scan:
mov esi, esp
cmp edx, shmem_list - shmem_item.next
jz .new
mov edi, edx
push 32
pop ecx
@@:
lodsb
scasb
jnz @f
test al, al
loopnz @b
@@:
jz .found
mov edx, [edx+shmem_item.next]
jmp .scan
.new:
; requested section was not found, create new if needed
push 5 ; E_NOTFOUND
pop edx
mov al, byte [context+0xA0] ; esi
and al, 0xC
jz .ret
jp .invparam
; create
mov eax, [context+0xA8] ; edx
test eax, eax
jz .invparam
call malloc_big
push 30 ; E_NOMEM
pop edx
test eax, eax
jz .ret
push eax
push shmem_item.sizeof
call malloc
test eax, eax
jnz @f
call free_big
push 30
pop edx
jmp .ret
@@:
mov edi, eax
push 32/4
pop ecx
rep movsd
mov ecx, [shmem_list]
mov [eax+shmem_item.next], ecx
mov [ecx+shmem_item.prev], eax
mov [eax+shmem_item.prev], shmem_list - shmem_item.next
mov [shmem_list], eax
mov [eax+shmem_item.refs], ebx
pop [eax+shmem_item.ptr]
push [context+0xA8]
pop [eax+shmem_item.size]
mov [eax+shmem_item.hOwner], ebx
mov [eax+shmem_item.pOwner], ebx
mov esi, eax
mov eax, [context+0xA0] ; esi
and eax, 1
mov [esi+shmem_item.access], eax
jmp .created
.found:
mov esi, edx
push 10 ; E_ACCESS
pop edx
mov al, byte [context+0xA0] ; esi
and al, 0xC
jz @f
jp .invparam
cmp al, 8
jz .ret
@@:
test byte [context+0xA0], 1
jz .created
cmp [esi+shmem_item.access], ebx
jz .ret
.created:
inc [esi+shmem_item.refs]
; section ok, now create descriptor for address space in target process
push shmem_proc_descr.sizeof
call malloc
test eax, eax
jnz @f
push [esi+shmem_item.next]
pop [shmem_list]
push esi
push [esi+shmem_item.ptr]
call free_big
call free
push 30
pop edx
jmp .ret
@@:
mov [eax+shmem_proc_descr.item], esi
mov [eax+shmem_proc_descr.ptr], ebx
mov [eax+shmem_proc_descr.end], ebx
xor edx, edx
test byte [context+0xA0], 1
jz @f
inc edx
@@:
cmp [esi+shmem_item.refs], 1
jnz @f
mov dl, 1
@@:
mov [eax+shmem_proc_descr.access], edx
; no need to synchronize - only server uses this list
call get_cur_slot_ptr_server
push [edi+shared_data_struc.shmem_list-shared_data_struc.threads]
pop [eax+shmem_proc_descr.next]
mov [edi+shared_data_struc.shmem_list-shared_data_struc.threads], eax
; all is OK, return to caller
mov [context+0xB0], ebx ; eax
mov eax, [esi+shmem_item.size]
mov [context+0xAC], eax ; ecx
add eax, 0xFFF
and eax, not 0xFFF
cmp [esi+shmem_item.refs], 1
jnz @f
xor eax, eax
@@:
mov [context+0xA8], eax ; edx
add esp, 32
jmp add2
no_server_create_shmem:
cmp eax, ..server_notify_shmem
jnz no_server_notify_shmem
call get_cur_slot_ptr_server
mov edi, [edi+shared_data_struc.shmem_list-shared_data_struc.threads]
push [context+0xB0] ; eax
pop [edi+shmem_proc_descr.ptr]
mov eax, [edi+shmem_proc_descr.item]
mov eax, [eax+shmem_item.size]
add eax, 0xFFF
and eax, not 0xFFF
add eax, [edi+shmem_proc_descr.ptr]
mov [edi+shmem_proc_descr.end], eax
jmp add2
no_server_notify_shmem:
cmp eax, ..server_destroy_shmem
jnz no_server_destroy_shmem
sub esp, 32
mov eax, esp
push ebx
push 32
push eax
push dword [context+0xAC] ; ecx
push [hProcess]
call [ReadProcessMemory]
mov [context+0xAC], ebx
test eax, eax
jz .ret
call get_cur_slot_ptr_server
lea ebp, [edi+shared_data_struc.shmem_list-shared_data_struc.threads - shmem_proc_descr.next]
.scan:
mov edx, [ebp+shmem_proc_descr.next]
test edx, edx
jz .ret
mov esi, [edx+shmem_proc_descr.item]
mov edi, esp
push 32
pop ecx
@@:
lodsb
scasb
jnz @f
test al, al
loopnz @b
@@:
jz .found
mov ebp, edx
jmp .scan
.found:
push [edx+shmem_proc_descr.next]
pop [ebp+shmem_proc_descr.next]
push [edx+shmem_proc_descr.ptr]
pop [context+0xAC] ; ecx
mov esi, [edx+shmem_proc_descr.item]
push edx
call free
dec [esi+shmem_item.refs]
jnz .ret
call shmem_free_item
.ret:
add esp, 32
jmp add2
no_server_destroy_shmem:
cmp eax, i40_sys_service.server_terminate
jz server_done
no_server_terminate:
if idletime_via_ring0
cmp eax, i40_sys_service.idlecount_init
jnz @f
push eax
push esp
push ebx
push [cur_slot]
push idlecount_thread
push 2000h
push ebx
call [CreateThread]
pop eax
mov eax, [shared_data]
mov [eax+shared_data_struc.idlecount], 1000
mov [eax+shared_data_struc.b9xPerfInited], 1
jmp add2
@@:
end if
cont_nh:
; ignore int3 breaks (continue as handled)
cmp [debugevent+12], 80000003h ; EXCEPTION_BREAKPOINT
jz debugcont
if 1
; ignore first-chance exceptions (continue as not handled)
cmp dword [debugevent+0x5C], ebx
jnz .first_chance
mov eax, context
int3
mov eax, [context+0xB8]
mov edi, eeeeip+7
std
mov ecx, 8
@@:
mov edx, eax
and al, 0xF
cmp al, 10
sbb al, 69h
das
stosb
mov eax, edx
shr eax, 4
loop @b
cld
call init_MessageBox
push ebx
push ebx
push eee
push ebx
call [MessageBoxA]
.first_chance:
end if
push 80010001h ; DBG_EXCEPTION_NOT_HANDLED
jmp dodebugcont
 
find_tid:
; get hThread
mov [hThread], ebx
mov [cur_slot], ebx
mov eax, [debugevent+8]
mov ecx, [tids]
@@: jecxz .ret
cmp [ecx+4], eax
jz @f
mov ecx, [ecx]
jmp @b
@@: mov eax, [ecx+12]
mov [cur_slot], eax
mov eax, [ecx+8]
mov [hThread], eax
mov [cur_tid_ptr], ecx
.ret:
ret
 
read_asciz:
; in: eax=client pointer, edx->buffer
push eax
push edx
push eax
push esp
push 260
push edx
push eax
push [hProcess]
call [ReadProcessMemory]
test eax, eax
pop ecx
pop edx
pop eax
jnz @f
xor ecx, ecx
@@: mov byte [edx+ecx], bl
ret
 
create_child:
mov edi, inname
mov esi, [parameters]
 
new_kolibri_process_with_default_curdir:
mov dword [process_curdir], '/rd/'
mov word [process_curdir+4], '1'
mov [parent_tid_ptr], ebx
 
new_kolibri_process:
; in: edi=pointer to process name, esi=pointer to parameters
; create command line
mov [process_name], edi
push esi
push edi
mov edi, cmdline
mov al, '"'
stosb
push 2000
push edi
push ebx
call [GetModuleFileNameA]
add edi, eax
mov ax, '" '
stosw
mov al, '"'
stosb
pop esi
push esi
call [lstrlenA]
xchg eax, ecx
rep movsb
mov al, '"'
stosb
mov al, ' '
stosb
pop esi
test esi, esi
jz @f
push esi
call [lstrlenA]
xchg eax, ecx
rep movsb
@@:
xor eax, eax
stosb
; create process
push [hThread]
push pinfo
push sinfo
push ebx
push ebx
push ebx
cmp [bDontDebug], bl
jnz @f
pop ebx
push 2 ; DEBUG_ONLY_THIS_PROCESS
@@:
push ebx
push ebx
push ebx
push cmdline
push ebx
call [CreateProcessA]
test eax, eax
jnz @f
call init_MessageBox
push ebx
push ebx
push cpe
push ebx
call [MessageBoxA]
pop eax
xor eax, eax
dec eax
ret
@@:
cmp [bDontDebug], bl
jz @f
pop eax
ret
@@:
mov eax, pids
@@: mov ecx, [eax]
jecxz @f
xchg eax, ecx
jmp @b
@@: push eax
push 16
call malloc
pop ecx
mov [ecx], eax
mov [eax], ebx
mov ecx, [dwProcessId]
mov [eax+4], ecx
mov ecx, [hProcess]
mov [eax+8], ecx
push eax
mov eax, 1000h
call malloc_big
pop ecx
mov [ecx+12], eax
mov edi, eax
mov esi, process_curdir
mov ecx, 1000h/4
rep movsd
call alloc_thread
call new_kolibri_thread
push eax
add edi, 8
mov esi, [process_name]
mov edx, esi
.1:
lodsb
cmp al, '\'
jnz @f
mov edx, esi
@@: cmp al, 0
jnz .1
mov esi, edx
mov ecx, 11
push ecx edi
mov al, ' '
rep stosb
pop edi ecx
push edi
.s:
lodsb
test al, al
jz .d
cmp al, '.'
jnz @f
mov edi, [esp]
add edi, 8
mov cl, 3
jmp .s
@@:
cmp al, 'a'
jb @f
cmp al, 'z'
ja @f
and al, not 20h
@@: stosb
loop .s
.d:
pop edi
add edi, 11
mov byte [edi], 0
pop eax
pop [hThread]
inc [num_kolibri_proc]
ret
alloc_thread:
mov eax, tids
@@: mov ecx, [eax]
jecxz @f
xchg eax, ecx
jmp @b
@@: push eax
push 56
call malloc
pop ecx
mov [ecx], eax
mov [eax], ebx
mov ecx, [dwThreadId]
mov [eax+4], ecx
mov ecx, [hThread]
mov [eax+8], ecx
or dword [eax+12], -1
mov ecx, [parent_tid_ptr]
mov [eax+20], ecx
mov [eax+52], ebx
mov [cur_tid_ptr], eax
push ecx
push ebx ; lpName
push ebx ; bInitialState
push ebx ; bManualReset
push ebx ; lpEventAttributes
call [CreateEventA]
pop ecx
jecxz @f
mov [ecx+24], eax
@@:
ret
new_kolibri_thread:
; find free slot
mov edi, [shared_data]
inc dword [edi+4]
mov ecx, [edi]
add edi, shared_data_struc.threads
xor edx, edx
@@:
cmp dword [edi], 0
jz @f
inc edx
add edi, 64
loop @b
mov ecx, [shared_data]
inc dword [ecx]
@@:
mov eax, [cur_tid_ptr]
mov [eax+12], edx
mov [cur_slot], edx
mov eax, [max_pid]
inc eax
mov [max_pid], eax
stosd
push eax
xor eax, eax
stosd
stosd
mov eax, [hProcess]
stosd
mov eax, [dwThreadId]
stosd
push edi
add edi, 20
mov eax, [hThread]
stosd
xor eax, eax
stosd
stosd
stosd
stosd
stosd
pop edi
pop eax
ret
 
delete_id:
@@: mov edx, [ecx]
cmp [edx+4], eax
jz @f
mov ecx, edx
jmp @b
@@:
push dword [edx]
push ecx
push edx
push ebx
push [hHeap]
; push dword [edx+8]
; call [CloseHandle]
call [HeapFree]
pop ecx
pop dword [ecx]
.ret:
ret
 
on_thread_exited:
mov ecx, [cur_tid_ptr]
; send notification message to debugger, if it is present
mov edi, [ecx+20]
test edi, edi
jz @f
push ecx
mov eax, [edi+12]
call get_slot_ptr
push ebx
push [cur_slot]
push 402h
push [edi+shared_data_struc.hWnd-shared_data_struc.threads]
call init_MessageBox
call [PostMessageA]
pop ecx
@@:
; terminate all debuggees, if are
mov esi, tids
@@:
mov esi, [esi]
test esi, esi
jz @f
cmp [esi+20], ecx
jnz @b
push ecx
push ebx
push dword [esi+8]
call [TerminateThread]
pop ecx
jmp @b
@@:
; free all shared memory
call get_cur_slot_ptr_server
mov edi, [edi+shared_data_struc.shmem_list-shared_data_struc.threads]
.freeshared:
test edi, edi
jz .doneshared
push [edi+shmem_proc_descr.next]
mov esi, [edi+shmem_proc_descr.item]
dec [esi+shmem_item.refs]
jz .freephys
cmp [esi+shmem_item.pOwner], edi
jnz .nextshared
call shmem_load
jmp .nextshared
.freephys:
call shmem_free_item
.nextshared:
push edi
call free
pop edi
jmp .freeshared
.doneshared:
; create thread to do rest of job (part which must be done with SharedDataMutex acquired)
; it is not safe to acquire_shared right here, because of possible deadlock
push eax
push esp
push ebx
push [cur_slot]
push on_thread_exited_thread
push 10000h
push ebx
call [CreateThread]
pop eax
ret
 
on_thread_exited_thread:
call acquire_shared
mov eax, [shared_data]
dec dword [eax+4]
mov eax, [esp+4]
call get_slot_ptr
and dword [edi], 0
; avoid problems with @panel
mov eax, ' '
add edi, 28
stosd
stosd
stosd
call release_shared
push 0
call [ExitThread]
 
if idletime_via_ring0
idlecount_thread:
mov eax, .count
call CallRing0
.workloop:
mov esi, eax
push 1000
call [Sleep]
mov eax, .count
call CallRing0
sub esi, eax
; add esi, 1000
; jc @f
; mov esi, 1000
;@@:
neg esi
cmp esi, 1000
jb @f
mov esi, 1000
@@:
mov ecx, [shared_data]
mov [ecx+shared_data_struc.idlecount], esi
jmp .workloop
.count:
push edi
; xor edx, edx
int 0x20 ; VMMCall Get_Sys_Thread_Handle
dw 10Ah
dw 1
push edi
int 0x20 ; VMMCall _GetThreadExecTime
dw 106h
dw 1
pop edi
; int 0x20 ; VMMCall Get_Sys_Thread_Handle
; dw 10Ah
; dw 1
;@@:
; int 0x20 ; VMMCall Get_Next_Thread_Handle
; dw 113h
; dw 1
; int 0x20 ; VMMCall Test_Sys_Thread_Handle
; dw 10Bh
; dw 1
; jz @f
; push edi
; int 0x20 ; VMMCall _GetThreadExecTime
; dw 106h
; dw 1
; add edx, eax
; pop eax
; jmp @b
;@@:
; mov eax, edx
pop edi
iret
end if
 
update_buttontype:
mov esi, [pids]
@@:
test esi, esi
jz .done
push 0
push 1
push buttontype
push buttontype
push dword [esi+8]
call [WriteProcessMemory]
mov esi, [esi]
jmp @b
.done:
ret
 
init_background:
push -1
push [hBgrMutex]
call [WaitForSingleObject]
cmp [bgr_section], 0
jnz .ret
push ebx
call get_screen_size
movzx eax, bx
shr ebx, 16
inc eax
inc ebx
mul ebx
imul eax, 3
pop ebx
add eax, 20h
push bgr_section_name
; push 0
push eax
push 0
push 4
push 0
push -1
call [CreateFileMappingA]
test eax, eax
jz .ret
xchg eax, esi
call [GetLastError]
push eax
push 0
push 0
push 0
push 2
push esi
call [MapViewOfFile]
push eax
; push esi
; call [CloseHandle]
pop eax
mov [bgr_section], eax
test eax, eax
xchg eax, edi
pop eax
jz .ret
cmp eax, 183
jz .ret
; init background data
call get_screen_size
xor eax, eax
shld eax, ebx, 16
inc eax
stosd
mov ax, bx
inc eax
stosd
mov byte [edi], 2
add edi, 8
xor ebx, ebx
; cmp byte [esp+4], 0
; jz read_bgr
jmp read_bgr
.ret:
push [hBgrMutex]
call [ReleaseMutex]
ret 4
 
read_bgr:
; read and parse desktop background to edi (=[bgr_section]+10h)
; call [GetDesktopWindow]
xor eax, eax
push eax
push eax
call [GetDC]
push eax
push eax
call [CreateCompatibleDC]
xchg eax, esi
push dword [edi-0Ch]
push dword [edi-10h]
push dword [esp+8]
call [CreateCompatibleBitmap]
push eax
push esi
call [SelectObject]
push eax
push 0xCC0020
push ebx
push ebx
push dword [esp+16]
push dword [edi-0Ch]
push dword [edi-10h]
push ebx
push ebx
push esi
call [BitBlt]
push dword [esp+4]
call [PaintDesktop]
push 0x660046
push ebx
push ebx
push dword [esp+16]
push dword [edi-0Ch]
push dword [edi-10h]
push ebx
push ebx
push esi
call [BitBlt]
push 0x660046
push ebx
push ebx
push esi
push dword [edi-0Ch]
push dword [edi-10h]
push ebx
push ebx
push dword [esp+36]
call [BitBlt]
push 0x660046
push ebx
push ebx
push dword [esp+16]
push dword [edi-0Ch]
push dword [edi-10h]
push ebx
push ebx
push esi
call [BitBlt]
push esi
call [SelectObject]
push ebp
xchg eax, ebp
; now esi=hDC, ebp=hBitmap
push ebx ; biClrImportant
push ebx ; biClrUsed
push ebx ; biYPelsPerMeter
push ebx ; biXPelsPerMeter
push ebx ; biSizeImage
push ebx ; biCompression
push 200001h ; biBitCount, biPlanes
push dword [edi-0Ch] ; biHeight
push dword [edi-10h] ; biWidth
push 40 ; biSize
mov ecx, esp
push ebx
push ecx
mov eax, [edi-0Ch]
mul dword [edi-10h]
shl eax, 2
call malloc_big
push eax
push dword [edi-0Ch]
push ebx
push ebp
push esi
xchg eax, edi
call [GetDIBits]
add esp, 40
push ebp
call [DeleteObject]
pop ebp
push esi
call [DeleteDC]
pop eax
pop ecx
push eax
push ecx
call [ReleaseDC]
mov esi, [bgr_section]
mov eax, [esi] ; width
mov ecx, [esi+4] ; height
add esi, 10h
xchg esi, edi
; esi=source, edi=destination
push eax
mul ecx
shl eax, 2
add esi, eax
pop edx
.1:
push ecx
mov ecx, edx
neg ecx
lea esi, [esi+ecx*4]
neg ecx
push esi
.2:
lodsd
; call convert_color
stosd
dec edi
loop .2
pop esi
pop ecx
loop .1
push esi
call free_big
push [hBgrMutex]
call [ReleaseMutex]
ret 4
 
del_background:
call [GetTickCount]
mov ecx, [shared_data]
cmp eax, [ecx+shared_data_struc.dwNewBgrTime]
jb .ret
add eax, 3000
mov [ecx+shared_data_struc.dwNewBgrTime], eax
xor eax, eax
lock xchg eax, [bgr_section]
test eax, eax
jz .ret
push eax
call [UnmapViewOfFile]
.ret:
ret
 
read_hex:
xor ecx, ecx
.l:
cmp al, '0'
jb .done
cmp al, '9'
jbe .digit
cmp al, 'A'
jb .done
cmp al, 'F'
jbe .digit2
cmp al, 'a'
jb .done
cmp al, 'f'
jbe .digit3
.done:
ret
.digit3:
sub al, 0x20
.digit2:
sub al, 'A'-'0'-10
.digit:
sub al, '0'
movzx eax, al
shl ecx, 4
add ecx, eax
cmp ecx, 0x10000
jae ParseEnablePorts.err
lodsb
jmp .l
 
send_driver_request:
xor ebx, ebx
push ebx
push ebx
push 3
push ebx
push ebx
push 0xC0000000
push kiw0
call [CreateFileA]
inc eax
jz .ret
dec eax
push eax
push eax
mov ecx, esp
push ebx ; lpOverlapped
push ecx ; lpBytesReturned
push dword [ecx+8+20] ; nOutBufferSize
push dword [ecx+8+16] ; lpOutBuffer
push dword [ecx+8+12] ; nInBufferSize
push dword [ecx+8+8] ; lpInBuffer
push dword [ecx+8+4] ; dwIoControlCode
push eax
call [DeviceIoControl]
pop ecx
pop ecx
push eax
push ecx
call [CloseHandle]
pop eax
.ret:
ret 20
 
driver_via_scm = 0
REQUIRED_DRIVER_VERSION = 1
 
load_kiw0:
; check whether driver with required version is already loaded
push eax
mov eax, esp
push 4
push eax
push ebx
push ebx
push 0x222008
call send_driver_request
test eax, eax
pop edi
jz .load
if driver_via_scm
push 3 ; dwDesiredAccess = SC_MANAGER_CONNECT+SC_MANAGER_CREATE_SERVICE
cmp edi, REQUIRED_DRIVER_VERSION
jnz .open
pop eax
cmp [keep_loaded_driver], 0
jnz .noopen
push 1 ; dwDesiredAccess = SC_MANAGER_CONNECT
.open:
mov esi, DrvLoadErr
push ebx ; lpDatabaseName
push ebx ; lpMachineName
call [OpenSCManagerA]
test eax, eax
jz server_fail
mov [hSCManager], eax
push 10030h
push kiw0_drivername
push [hSCManager]
call [OpenServiceA]
test eax, eax
jz server_fail
mov [hService], eax
.noopen:
cmp edi, REQUIRED_DRIVER_VERSION
jz .driverok
; driver is loaded, but has incorrect version
; try to unload and load new driver
call unload_kiw0
jmp @f
 
.load:
mov esi, DrvLoadErr
push 2 ; dwDesiredAccess = SC_MANAGER_CREATE_SERVICE
push ebx ; lpDatabaseName
push ebx ; lpMachineName
call [OpenSCManagerA]
test eax, eax
jz server_fail
mov [hSCManager], eax
@@:
mov edi, win32_path
push edi
push edi
call [lstrlenA]
lea edi, [edi+eax+1-inifilenamesize]
push esi
mov esi, kiw0filename
mov ecx, kiw0filenamesize
rep movsb
pop esi
pop edi
push ebx ; lpPassword
push ebx ; lpServiceStartName
push ebx ; lpDependencies
push ebx ; lpdwTagId
push ebx ; lpLoadOrderGroup
push edi ; lpBinaryPathName
push ebx ; dwErrorControl = SERVICE_ERROR_IGNORE
push 3 ; dwStartType = SERVICE_DEMAND_START
push 1 ; dwServiceType = SERVICE_KERNEL_DRIVER
push 10030h ; dwDesiredAccess = SERVICE_START or SERVICE_STOP or DELETE
push kiw0_username ; lpDisplayName
push kiw0_drivername ; lpServiceName
push [hSCManager]
call [CreateServiceA]
; test eax, eax
; jnz .cont
; call [GetLastError]
; cmp eax, 431h ; ERROR_SERVICE_EXISTS
; jnz server_fail
; push 10030h
; push kiw0_drivername
; push [hSCManager]
; call [OpenServiceA]
test eax, eax
jz server_fail
.cont:
mov [hService], eax
push ebx ; lpServiceArgVectors
push ebx ; dwNumServiceArgs
push eax
call [StartServiceA]
test eax, eax
jz server_fail
.driverok:
ret
 
unload_kiw0:
sub esp, 20h
push esp
push 1 ; SERVICE_CONTROL_STOP
push [hService]
call [ControlService]
add esp, 20h
push [hService]
call [DeleteService]
push [hService]
call [CloseServiceHandle]
ret
 
server_done:
cmp [hService], 0
jz .skip_drv
cmp [keep_loaded_driver], 0
jnz .skip_drv
call unload_kiw0
push [hSCManager]
call [CloseServiceHandle]
.skip_drv:
 
else
cmp edi, REQUIRED_DRIVER_VERSION
jz load_kiw0.driverok
call unload_kiw0
load_kiw0.load:
mov esi, DrvLoadErr
push eax
mov eax, esp
xor ecx, ecx
push ecx ; lpdwDisposition
push eax ; phkResult
push ecx ; lpSecurityAttributes
push 6 ; samDesired = KEY_SET_VALUE | KEY_CREATE_SUB_KEY
push ecx ; dwOptions
push ecx ; lpClass
push ecx ; Reserved
push DrvKey ; lpSubKey
push 0x80000002 ; hKey = HKEY_LOCAL_MACHINE
call [RegCreateKeyExA]
test eax, eax
jnz server_fail
push esi
mov esi, win32_path
push esi
call [lstrlenA]
lea esi, [esi+eax-1]
lea edi, [esi+4]
mov ecx, eax
push edi
std
rep movsb
cld
mov dword [edi-3], '\??\'
pop edi
sub edi, inifilenamesize-2
mov esi, kiw0filename
mov ecx, kiw0filenamesize
rep movsb
sub edi, win32_path+1
mov [drvpathlen], edi
pop esi
mov edi, DrvKeyValues
.write_values:
push dword [edi+12] ; cbData
push dword [edi+8] ; lpData
push dword [edi+4] ; dwType
push 0 ; Reserved
push dword [edi] ; lpValueName
push dword [esp+20] ; hKey
call [RegSetValueExA]
test eax, eax
jz @f
call [RegCloseKey]
.del_fail:
push DrvKey
push 0x80000002
call [RegDeleteKeyA]
jmp server_fail
@@:
add edi, 16
cmp dword [edi], 0
jnz .write_values
call [RegCloseKey]
; NtLoadDriver and NtUnloadDriver require SeLoadPrivilege enabled.
; But I found that if user has this privilege, then it is already enabled
; (unlike things like SeShutdownPrivilege - in such cases there must be
; additional code with AdjustTokenPrivileges(OpenProcessToken(...),LookupPrivilegeValue(...),...))
push ntdll_name
call [GetModuleHandleA]
push aNtLoadDriver
push eax
call [GetProcAddress]
push DrvKeySys
call eax
test eax, eax
js .del_fail
load_kiw0.driverok:
mov [bDriverLoaded], 1
ret
 
unload_kiw0:
; Unload and delete driver kiw0.sys
; 1. Unload
push ntdll_name
call [GetModuleHandleA]
push aNtUnloadDriver
push eax
call [GetProcAddress]
push DrvKeySys
call eax
; 2. When the kernel loads driver, it (kernel) creates auxiliary reg keys
; in HKLM\System\CurrentControlSet\Enum\
; (for legacy drivers such as kiw0, this is Root\LEGACY_KIW0\<instance>)
; To delete this key and possibly reenumerate, call umpnpmgr.DeleteServicePlugPlayRegKeys
; In Win2k the library umpnpmgr.dll doesn't export this function,
; but under Win2k there is impossible to delete this key, because it is still opened by the kernel
mov esi, aCannotLoadDll
push umpnpmgr_name
call [LoadLibraryA]
test eax, eax
jz .nodll
push eax
push umpnpmgr_uninst
push eax
call [GetProcAddress]
test eax, eax
jz @f
push kiw0_unicode
call eax
@@:
call [FreeLibrary]
.nodll:
; 3. Delete main registry key, HKLM\System\CurrentControlSet\Services\kiw0
; (and created by the kernel subkey Enum)
push DrvKeyEnum
push 0x80000002
call [RegDeleteKeyA]
push DrvKey
push 0x80000002
call [RegDeleteKeyA]
.ret:
ret
 
server_done:
cmp [bDriverLoaded], 0
jz .skip_drv
cmp [keep_loaded_driver], 0
jnz .skip_drv
call unload_kiw0
.skip_drv:
end if
 
cmp [bIs9x], 0
jz server_done_perf
mov eax, [shared_data]
cmp [eax+shared_data_struc.b9xPerfInited], 0
jz server_done_perf
if ~idletime_via_ring0
push eax
push esp ; phkResult
push 1 ; samDesired = KEY_QUERY_VALUE
push ebx ; ulOptions
push perfend ; lpSubKey
push 80000006h ; hKey = HKEY_DYN_DATA
call [RegOpenKeyExA]
pop esi
test eax, eax
jnz server_done_perf
push eax
mov eax, esp
push 4
push esp ; lpcbData
push eax ; lpData
push ebx ; lpType
push ebx ; lpReserved
push perfval ; lpValueName
push esi ; hKey
call [RegQueryValueExA]
pop ecx
pop ecx
push esi
call [RegCloseKey]
end if
server_done_perf:
push ebx
call [ExitProcess]
 
PlaySoundA_delayed_imp:
push winmm_name
call [LoadLibraryA]
test eax, eax
jz .fail
push eax
push aPlaySoundA
push eax
call [GetProcAddress]
pop ecx
test eax, eax
jz .fail_free
mov [PlaySoundA], eax
jmp eax
.fail_free:
push ecx
call [FreeLibrary]
.fail:
mov [PlaySoundA], @f
@@:
xor eax, eax
ret 12
 
init_dll:
push dword [esp+4]
call [LoadLibraryA]
xchg edi, eax
mov esi, [esp+8]
@@:
lodsd
test eax, eax
jz @f
add eax, 0x400002
push eax
push edi
call [GetProcAddress]
mov [esi-4], eax
jmp @b
@@:
ret 8
 
init_MessageBox:
cmp [MessageBoxA], rva MessageBoxA_thunk
jnz @f
push user32_thunks
push user32_name
call init_dll
@@:
ret
 
DuplicateMyHandle:
jecxz @f
push 2 ; DUPLICATE_SAME_ACCESS
push ebx
push ebx
push eax
push [hProcess]
push ecx
call [GetCurrentProcess]
push eax
call [DuplicateHandle]
ret
@@:
mov [eax], ecx
ret
 
shmem_load:
mov edx, [eax+shmem_proc_descr.end]
mov ecx, [eax+shmem_proc_descr.ptr]
sub edx, ecx
push eax ecx edx
push eax
push esp
push 2 ; PAGE_READONLY
push edx
push ecx
push [esi+shmem_item.hOwner]
call [VirtualProtectEx]
pop eax
pop edx ecx eax
push ebx
push edx
push [esi+shmem_item.ptr]
push ecx
push [esi+shmem_item.hOwner]
call [ReadProcessMemory]
mov [esi+shmem_item.hOwner], ebx
mov [esi+shmem_item.pOwner], ebx
ret
 
shmem_free_item:
mov eax, [esi+shmem_item.next]
mov ecx, [esi+shmem_item.prev]
mov [eax+shmem_item.prev], ecx
mov [ecx+shmem_item.next], eax
push [esi+shmem_item.ptr]
call free_big
push esi
call free
ret
 
include 'i40emul.inc'
 
section '.rdata' data readable
 
data import
macro thunk a {
a#_thunk:dw 0
db `a,0}
dd 0,0,0, rva kernel32_name, rva kernel32_thunks
; dd 0,0,0, rva user32_name, rva user32_thunks
; dd 0,0,0, rva gdi32_name, rva gdi32_thunks
; dd 0,0,0, rva comdlg32_name, rva comdlg32_thunks
dd 0,0,0, rva advapi32_name, rva advapi32_thunks
; dd 0,0,0, rva winmm_name, rva winmm_thunks
dd 0,0,0,0,0
kernel32_name db 'kernel32.dll',0
user32_name db 'user32.dll',0
gdi32_name db 'gdi32.dll',0
ntdll_name db 'ntdll.dll',0
comdlg32_name db 'comdlg32.dll',0
advapi32_name db 'advapi32.dll',0
winmm_name db 'winmm.dll',0
;winsock_name db 'wsock32.dll',0
kernel32_thunks:
CreateFileA dd rva CreateFileA_thunk
CloseHandle dd rva CloseHandle_thunk
CreateFileMappingA dd rva CreateFileMappingA_thunk
OpenFileMappingA dd rva OpenFileMappingA_thunk
MapViewOfFile dd rva MapViewOfFile_thunk
UnmapViewOfFile dd rva UnmapViewOfFile_thunk
ReadFile dd rva ReadFile_thunk
WriteFile dd rva WriteFile_thunk
GetFileSize dd rva GetFileSize_thunk
SetEndOfFile dd rva SetEndOfFile_thunk
VirtualAlloc dd rva VirtualAlloc_thunk
VirtualFree dd rva VirtualFree_thunk
VirtualProtect dd rva VirtualProtect_thunk
VirtualProtectEx dd rva VirtualProtectEx_thunk
SetFilePointer dd rva SetFilePointer_thunk
ExitProcess dd rva ExitProcess_thunk
ExitThread dd rva ExitThread_thunk
CreateProcessA dd rva CreateProcessA_thunk
CreateThread dd rva CreateThread_thunk
TerminateThread dd rva TerminateThread_thunk
GetCommandLineA dd rva GetCommandLineA_thunk
ReadProcessMemory dd rva ReadProcessMemory_thunk
WriteProcessMemory dd rva WriteProcessMemory_thunk
WaitForDebugEvent dd rva WaitForDebugEvent_thunk
ContinueDebugEvent dd rva ContinueDebugEvent_thunk
SuspendThread dd rva SuspendThread_thunk
ResumeThread dd rva ResumeThread_thunk
GetThreadContext dd rva GetThreadContext_thunk
SetThreadContext dd rva SetThreadContext_thunk
GetProcessHeap dd rva GetProcessHeap_thunk
HeapAlloc dd rva HeapAlloc_thunk
HeapReAlloc dd rva HeapReAlloc_thunk
HeapFree dd rva HeapFree_thunk
Sleep dd rva Sleep_thunk
GetLocalTime dd rva GetLocalTime_thunk
SetFileTime dd rva SetFileTime_thunk
GetCurrentDirectoryA dd rva GetCurrentDirectoryA_thunk
SetCurrentDirectoryA dd rva SetCurrentDirectoryA_thunk
GetTickCount dd rva GetTickCount_thunk
GetCurrentProcess dd rva GetCurrentProcess_thunk
GetPrivateProfileStringA dd rva GetPrivateProfileStringA_thunk
GetPrivateProfileIntA dd rva GetPrivateProfileIntA_thunk
lstrcpyA dd rva lstrcpyA_thunk
lstrcpynA dd rva lstrcpynA_thunk
lstrcatA dd rva lstrcatA_thunk
lstrlenA dd rva lstrlenA_thunk
lstrcmpA dd rva lstrcmpA_thunk
GetFileAttributesA dd rva GetFileAttributesA_thunk
SetFileAttributesA dd rva SetFileAttributesA_thunk
GetModuleFileNameA dd rva GetModuleFileNameA_thunk
GetLastError dd rva GetLastError_thunk
CreateMutexA dd rva CreateMutexA_thunk
CreateEventA dd rva CreateEventA_thunk
SetEvent dd rva SetEvent_thunk
DuplicateHandle dd rva DuplicateHandle_thunk
WaitForSingleObject dd rva WaitForSingleObject_thunk
ReleaseMutex dd rva ReleaseMutex_thunk
GetVersion dd rva GetVersion_thunk
GetModuleHandleA dd rva GetModuleHandleA_thunk
GetProcAddress dd rva GetProcAddress_thunk
GetCurrentThreadId dd rva GetCurrentThreadId_thunk
GetStartupInfoA dd rva GetStartupInfoA_thunk
FindFirstFileA dd rva FindFirstFileA_thunk
FindNextFileA dd rva FindNextFileA_thunk
FindClose dd rva FindClose_thunk
FileTimeToDosDateTime dd rva FileTimeToDosDateTime_thunk
DeleteFileA dd rva DeleteFileA_thunk
DeviceIoControl dd rva DeviceIoControl_thunk
MultiByteToWideChar dd rva MultiByteToWideChar_thunk
FileTimeToSystemTime dd rva FileTimeToSystemTime_thunk
SystemTimeToFileTime dd rva SystemTimeToFileTime_thunk
GetFullPathNameA dd rva GetFullPathNameA_thunk
CompareStringA dd rva CompareStringA_thunk
GlobalMemoryStatus dd rva GlobalMemoryStatus_thunk
InitializeCriticalSection dd rva InitializeCriticalSection_thunk
EnterCriticalSection dd rva EnterCriticalSection_thunk
LeaveCriticalSection dd rva LeaveCriticalSection_thunk
CreateDirectoryA dd rva CreateDirectoryA_thunk
RemoveDirectoryA dd rva RemoveDirectoryA_thunk
LoadLibraryA dd rva LoadLibraryA_thunk
FreeLibrary dd rva FreeLibrary_thunk
dw 0
thunk CreateFileA
thunk CloseHandle
thunk CreateFileMappingA
thunk OpenFileMappingA
thunk MapViewOfFile
thunk UnmapViewOfFile
thunk ReadFile
thunk WriteFile
thunk GetFileSize
thunk SetEndOfFile
thunk VirtualAlloc
thunk VirtualFree
thunk VirtualProtect
thunk VirtualProtectEx
thunk SetFilePointer
thunk ExitProcess
thunk ExitThread
thunk CreateProcessA
thunk CreateThread
thunk TerminateThread
thunk GetCurrentProcess
thunk GetCommandLineA
thunk ReadProcessMemory
thunk WriteProcessMemory
thunk WaitForDebugEvent
thunk ContinueDebugEvent
thunk SuspendThread
thunk ResumeThread
thunk GetThreadContext
thunk SetThreadContext
thunk GetProcessHeap
thunk HeapAlloc
thunk HeapReAlloc
thunk HeapFree
thunk Sleep
thunk GetLocalTime
thunk SetFileTime
thunk GetCurrentDirectoryA
thunk SetCurrentDirectoryA
thunk GetTickCount
thunk GetPrivateProfileStringA
thunk GetPrivateProfileIntA
thunk lstrcpyA
thunk lstrcpynA
thunk lstrcatA
thunk lstrlenA
thunk lstrcmpA
thunk GetFileAttributesA
thunk SetFileAttributesA
thunk GetModuleFileNameA
thunk GetLastError
thunk CreateMutexA
thunk CreateEventA
thunk SetEvent
thunk DuplicateHandle
thunk WaitForSingleObject
thunk ReleaseMutex
thunk GetVersion
thunk GetModuleHandleA
thunk GetProcAddress
thunk GetCurrentThreadId
thunk GetStartupInfoA
thunk FindFirstFileA
thunk FindNextFileA
thunk FindClose
thunk CharToOemA
thunk OemToCharA
thunk FileTimeToDosDateTime
thunk DeleteFileA
thunk DeviceIoControl
thunk MultiByteToWideChar
thunk FileTimeToSystemTime
thunk SystemTimeToFileTime
thunk GetFullPathNameA
thunk CompareStringA
thunk GlobalMemoryStatus
thunk InitializeCriticalSection
thunk EnterCriticalSection
thunk LeaveCriticalSection
thunk CreateDirectoryA
thunk RemoveDirectoryA
thunk LoadLibraryA
thunk FreeLibrary
aNtSetLdtEntries db 'NtSetLdtEntries',0
if ~driver_via_scm
aNtLoadDriver db 'NtLoadDriver',0
aNtUnloadDriver db 'NtUnloadDriver',0
end if
align 4
advapi32_thunks:
if ~driver_via_scm
RegCreateKeyExA dd rva RegCreateKeyExA_thunk
RegDeleteKeyA dd rva RegDeleteKeyA_thunk
end if
RegOpenKeyExA dd rva RegOpenKeyExA_thunk
RegCloseKey dd rva RegCloseKey_thunk
RegQueryValueExA dd rva RegQueryValueExA_thunk
RegSetValueExA dd rva RegSetValueExA_thunk
OpenSCManagerA dd rva OpenSCManagerA_thunk
CreateServiceA dd rva CreateServiceA_thunk
OpenServiceA dd rva OpenServiceA_thunk
StartServiceA dd rva StartServiceA_thunk
ControlService dd rva ControlService_thunk
DeleteService dd rva DeleteService_thunk
CloseServiceHandle dd rva CloseServiceHandle_thunk
dw 0
if ~driver_via_scm
thunk RegCreateKeyExA
thunk RegDeleteKeyA
end if
thunk RegOpenKeyExA
thunk RegCloseKey
thunk RegQueryValueExA
thunk RegSetValueExA
thunk OpenSCManagerA
thunk CreateServiceA
thunk OpenServiceA
thunk StartServiceA
thunk ControlService
thunk DeleteService
thunk CloseServiceHandle
;winmm_thunks:
;PlaySoundA dd rva PlaySoundA_thunk
; dw 0
;thunk PlaySoundA
end data
 
aGetOpenFileNameA db 'GetOpenFileNameA',0
aPlaySoundA db 'PlaySoundA',0
 
align 4
;data resource from 'klbrico.res'
;end data
data resource
rsrcdata:
; only icon resource from file 'KlbrInWin.ico'
; for graphics thanks to goglus, Leency, Heavyiron
iconfile equ 'KlbrInWin.ico'
 
virtual at 0
; load .ico header
file iconfile:0,6
load .idReserved word from 0
load .idType word from 2
load .idCount word from 4
if (.idReserved <> 0) | (.idType <> 1)
error invalid icon file
end if
end virtual
 
; root resource directory
dd 0, 0, 0
dw 0, 2 ; 2 entries by id
dd 3, (.icon1 - rsrcdata) or 80000000h ; entry 1: RT_ICON
dd 14, (.gicon1 - rsrcdata) or 80000000h ; entry 2: RT_GROUP_ICON
; level-1 resource directory for RT_ICON
.icon1:
dd 0, 0, 0
dw 0, .idCount ; .idCount entries by id
repeat .idCount
dd %, ((.icon2 - rsrcdata) + 18h*(%-1)) or 80000000h
end repeat
; level-1 resource directory for RT_GROUP_ICON
.gicon1:
dd 0, 0, 0
dw 0, 1 ; 1 entry by id
dd 1, (.gicon2 - rsrcdata) or 80000000h
; level-2 resource directories for RT_ICON
.icon2:
repeat .idCount
dd 0, 0, 0
dw 0, 1 ; 1 entry by id
dd 0, (.icon3 - rsrcdata) + 10h*(%-1)
end repeat
; level-2 resource directory for RT_GROUP_ICON
.gicon2:
dd 0, 0, 0
dw 0, 1 ; 1 entry by id
dd 0, (.gicon3 - rsrcdata)
; leaf entries for RT_ICON
.icon3:
.a = rva .icons
repeat .idCount
virtual at 0
file iconfile:6+16*(%-1)+8,4
load .dwBytesInRes dword from 0
end virtual
dd .a, .dwBytesInRes, 0, 0
.a = (.a + .dwBytesInRes + 3) and not 3
end repeat
; leaf entry for RT_GROUP_ICON
.gicon3:
dd rva .gicon, .gicon_end - .gicon, 0, 0
; icon data
.icons:
repeat .idCount
virtual at 0
file iconfile:6+16*(%-1)+8,8
load .dwBytesInRes dword from 0
load .dwImageOffset dword from 4
end virtual
file iconfile:.dwImageOffset,.dwBytesInRes
while .dwBytesInRes and 3
.dwBytesInRes = .dwBytesInRes + 1
db 0
end while
end repeat
.gicon:
dw 0, 1, .idCount ; .idCount images
repeat .idCount
file iconfile:6+16*(%-1),12
dw %
end repeat
.gicon_end:
end data
 
data 9
dd tls_init_start
dd tls_init_end
dd tls_index
dd 0
dd 0
dd 0
end data
 
virtual at 0
tls:
._cs dw ?
._ds dw ?
._esp dd ?
._eip dd ?
._fs dw ?
dw ? ; align
.exc_code dd ?
.exc_data dd ?
.message_mask dd ?
.lpShapeData dd ?
.scale dd ?
.curdraw db ?
 
.uninit_size = .size - $
 
.showwnd db ?
.bFirstMouseMove db ?
.bActive db ?
.hWnd dd ?
.hCursor dd ?
.buttons dd ?
.x_size dw ?
.x_start dw ?
.y_size dw ?
.y_start dw ?
.client_left dd ?
.client_top dd ?
.client_width dd ?
.client_height dd ?
.color_main dd ?
.color_capt dd ?
.color_border dd ?
.caption dd ?
.debuggees dd ?
.translated_msg_code db ?
.usescancode db ?
.keybuflen db ?
.butbuflen db ?
.keybuffer rb 0x100
.butbuffer rd 0x100
.active_button dd ?
.cur_slot dd ?
.saved_fs0 dd ?
.saved_fs4 dd ?
.prev_snd_block dd ?
.cur_dir dd ?
.scroll dd ?
.original_buttons db ?
.current_buttons db ?
dw ?
.size = $
end virtual
 
align 4
ofn_arg_template:
dw 1,-1 ; dlgVer,signature
dd 0 ; helpId
dd 0 ; exStyle
dd 56000444h ; style
dw 2 ; cDlgItems
dw 0,0,275,28 ; x,y,cx,cy
dw 0,0,0 ; menu,windowClass,title
dw 8 ; pointsize
dd 0 ; weight,italic,charset
du 'MS Sans Serif',0
align 4
dd 0 ; helpId
dd 0 ; exStyle
dd 50010000h ; style
dw 5,12,45,9 ; x,y,cx,cy
dw -1 ; id
dw 0
dw -1,82h ; windowClass
du "Parameters:",0
dw 0
align 4
dd 0
dd 204h
dd 50010080h
dw 54,10,218,12
dw 23
dw 0
dw -1,81h
dw 0
dw 0
 
align 4
_1193180 dd 1193180
_100 dd 100
 
kontrOctave:
; note that values 0, D,E,F must not be used, but 0 is used (e.g. by icon2)
dw 0xC3FB, 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562, 0x3264
dw 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF, 0xFDA, 0, 0x19
 
dir0:
db 'HARDDISK ',10h
db 'RAMDISK ',10h
dir1 db 'FIRST ',10h
 
path_begin:
db 1,2,'RD'
db 1,7,'RAMDISK'
db 2,2,'FD'
db 2,11,'FLOPPYDI.SK'
db 4,3,'HD0'
db 5,3,'HD1'
db 6,3,'HD2'
db 7,3,'HD3'
db 3,2,'HD'
db 3,8,'HARDDISK'
db 0
 
 
; align 4
; winsock_imports:
; WSAStartup dd WSAStartup_name
; WSACleanup dd WSACleanup_name
; socket dd socket_name
; closesocket dd closesocket_name
; dd 0
 
; WSAStartup_name db 'WSAStartup',0
; WSACleanup_name db 'WSACleanup',0
; socket_name db 'socket',0
; closesocket_name db 'closesocket',0
 
ofn_title db 'Select KolibriOS executable',0
dd -10
fileopenerr db 'Cannot open input file',0
dd -31
filereaderr db 'Input file read error',0
dd -31
notexe db 'Not KolibriOS executable!',0
dd -7
params_err db 'Parameters pointer is outside used memory!',0
dd -30
memerr db 'Not enough memory',0
dd -30
ldterr db 'Cannot allocate LDT selectors',0
idt_err db 'IDT limit too small',0
exceptionstr db 'Exception',0
excstr db 'Emulated process has caused an exception and will be terminated.',13,10
db 'Registers:',13,10
db 'EAX=%08X EBX=%08X ECX=%08X EDX=%08X',13,10
db 'ESI=%08X EDI=%08X ESP=%08X EBP=%08X',13,10
db 'EIP=%08X EFLAGS=%08X',0
nsm db 'Unsupported system function',0
notsupportedmsg db 'Emulated process has called unknown system function and will be terminated.',13,10
db 'Registers:',13,10
db 'EAX=%08X EBX=%08X ECX=%08X EDX=%08X',13,10
db 'ESI=%08X EDI=%08X ESP=%08X EBP=%08X',13,10
db 'EIP=%08X EFLAGS=%08X',0
cpe db 'Cannot create process',0
aConfirm db 'Ïîäòâåðæäåíèå',0
BgrQuestionText db 'Ïðîãðàììà õî÷åò óñòàíîâèòü ôîí ðàáî÷åãî ñòîëà.',13,10
db 'Óñòàíîâèòü êàê ïîñòîÿííûé?',0
BgrFileErrorMsg db 'Cannot create background image file',0
dd -1
skinfileerr db 'Invalid skin file',0
vkerr db 'A running instance of KlbrInWin already exists, cannot continue',0
dd -1
no_partition db 'Partition is not defined',0
EnablePortsSyntaxErr db 'EnablePorts parameter: syntax error',0
DrvLoadErr db 'Cannot load driver',0
DrvOpenErr db 'Cannot send command to driver',0
PortsRangeErr db 'Sysfunction 46: invalid ports range',0
PortsNotEnabledErr db 'Sysfunction 46: attempt to allocate not enabled ports',0
PortsUsedErr db 'Sysfunction 46: attempt to allocate already used ports',0
PortsNotUsedErr db 'Sysfunction 46: attempt to free ports which were not allocated',0
 
;aPathInvalid db 'Path pointer is outside used memory and will be ignored',0
dd -2
aPathUnknown db 'Win32 path to program cannot be written as Kolibri path!',0
 
aReadMSRDisabled db 'Emulated process tries to read MSR, and this is disabled in ini-file.',0
aNoMsr db 'Emulated process has tried to read invalid MSR and will be terminated',0
aInvFn64Call db 'Function 64 has been called after heap initialization, will fail.',0
aHeapNotInited db 'Attempt to work with uninitialized heap!',0
aInternalError db 'Internal error',0
aMallocFailed db 'Memory request failed!',0
aFreeInvalid db 'Attempt to free/realloc not allocated block!',0
aCannotLoadDll db 'Cannot load DLL',0
aUnknownReloc db 'Unknown relocation type',0
aExportsNotFound db 'DLL export table was not found!',0
aInvCursorData db 'Invalid cursor data',0
aOnlyOneCursor db 'Cursor data must contain only one cursor',0
aInvCursorDim db 'Cursor must be of size 32*32 pixels',0
aCursorFailed db 'Cursor creation failed',0
aCursorLimitExceeded db 'Cursors limit exceeded',0
aInvalidCursor db 'Invalid handle for delete_cursor!',0
aSound db 'SOUND',0
aInfinity db 'INFINITY',0
aUnknownDriver db 'Attempt to load unknown driver will fail',0
aCannotGetPci db 'Cannot get PCI BIOS parameters',0
;aPciDisabled db 'Emulated process tries to enable PCI access, and this is disabled in ini-file.',0
dd -1
aInvalidColorDepth db 'Invalid ColorDepth parameter in ini-file',0
DSAErr db 'Access to DirectScreenArea outside real screen data causes an exception...',0
DSADisabled db 'The program has called sysfunction 61 (Direct Screen Access parameters),',10
db 'but Direct Screen Access is disabled in ini-file. The program will be terminated :(',0
aFailedToDeliverDebugMessage db 'Failed to deliver debug message',0
aInvalidDataForDR db 'Invalid data for 69.9, returning an error',0
aCannotDestroyShMem db 'Attempt to close not opened shared memory area',0
;aWinsockInitErr db 'Cannot initialize Winsock DLL!',0
;aSocketErr db 'Cannot allocate socket!',0
 
inifilename db 'KlbrInWin.ini'
null_string db 0
inifilenamesize = $ - inifilename
kiw0filename db 'kiw0.sys',0
kiw0filenamesize = $ - kiw0filename
kiw0_username db 'KlbrInWin ring-0 component',0
kiw0_drivername db 'kiw0',0
kiw0 db '\\.\kiw0',0
if ~driver_via_scm
DrvKey db 'SYSTEM\CurrentControlSet\Services\kiw0',0
DrvKeyEnum db 'SYSTEM\CurrentControlSet\Services\kiw0\Enum',0
align 4
DrvKeySys:
dw DrvKeySysLen-2, DrvKeySysLen
dd @f
@@ du '\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\kiw0',0
DrvKeySysLen = $ - @b
aDisplayName db 'DisplayName',0
aType db 'Type',0
aStart db 'Start',0
addr3 dd 3 ; SERVICE_DEMAND_START
aErrorControl db 'ErrorControl',0
aImagePath db 'ImagePath',0
 
umpnpmgr_name db 'umpnpmgr.dll',0
umpnpmgr_uninst db 'DeleteServicePlugPlayRegKeys',0
kiw0_unicode du 'kiw0',0
end if
 
default_ramdisk db 'A:\',0
ramdisk_keyname db 'RamDisk',0
aDisk db 'Disk',0
aMain db 'Main',0
aFont1 db 'Font1',0
aFont2 db 'Font2',0
aSkin db 'Skin',0
aQuestions db 'Questions',0
aSetBgr db 'SetBgr',0
aSetup db 'sys_setup',0
aSoundFlag db 'sound_flag',0
aSoundVol db 'sound_vol',0
aSysLang db 'syslang',0
aKeyboard db 'keyboard',0
aEnablePorts db 'EnablePorts',0
aAllowReadMSR db 'AllowReadMSR',0
aAllowReadPCI db 'AllowReadPCI',0
aKeepLoadedDriver db 'KeepLoadedDriver',0
aDirectScreenAccess db 'DirectScreenAccess',0
aColorDepth db 'ColorDepth',0
aInvalidateTime db 'DSAInvalidateTime',0
 
classname db 'KolibriInWin_WndClass',0
dd -30
createwnderr db 'Cannot create window!',0
 
dd -30
shared_section_size = 8000h
shared_section_create_err db 'Cannot create section for shared data!',0
shared_mutex_create_err db 'Cannot create mutex for shared data!',0
virtual at 0
shared_data_struc:
.alloc_threads dd ?
.num_threads dd ?
.vk db ?
.bAllowReadMSR db ?
.b9xPerfInited db ?
if idletime_via_ring0
.idlecount dd ?
end if
; \begin{sys_setup}
.sound_flag db ?
.syslang dd ?
.midi_base dw ?
.cd_base db ?
.hd_base db ?
.sb16 dd ?
.wss dd ?
.fat32part dd ?
.sound_dma dd ?
.lba_read_enabled dd ?
.pci_access_enabled dd ?
.keyboard dw ?
.mouse_speed_factor dw ?
.mouse_delay dd ?
; \end{sys_setup}
.pci_data_init db ? ; initialized?
.bAllowReadPCI db ?
.curport dw ?
.cursocket dd ?
.pci_bios_mj db ? ; major PCI BIOS version
.pci_bios_mn db ? ; minor PCI BIOS version
.pci_bios_lb db ? ; last PCI bus
.pci_bios_pc db ? ; PCI characteristics
.workarea_left dd ?
.workarea_top dd ?
.workarea_right dd ?
.workarea_bottom dd ?
.dwNewBgrTime dd ?
.msg_board_count dd ?
.msg_board_data rb 512
.active_process dd ?
.cpuspeed dd ?
.DisabledPorts rb 2000h
.UsedIoMap rb 2000h
num_cursors = 63 ; exclude standard arrow cursor, it is handled separately
.cursors rd num_cursors*2
.threads:
; rept .alloc_threads
.thread_id dd ? ; 0 for free slot
.thread_ipc_mem dd ?
.thread_ipc_size dd ?
.win32_hBaseProcess dd ? ; this is handle for debugger!
.win32_dwThreadId dd ?
.hWnd dd ?
.limit dd ?
.name rb 12
.win32_hThread dd ? ; this is handle for debugger!
.debugger_mem dd ?
.win32_stack dd ?
.shmem_list dd ? ; head of L1-list of shmem_proc_descr
rd 2
end virtual
 
bgr_section_name db 'KolibriInWin_background',0
bgr_section_size = 0x160000+0x10
bgr_mutex_name db 'KolibriInWin_bgrmtx',0
bgrkeyname db 'Control Panel\Desktop',0
bgrstylevalue db 'WallpaperStyle',0
bgrtilevalue db 'TileWallpaper',0
bgrtempfilename db 'klbrbgr.bmp',0
bgrfilename db 'klbr_bgr.bmp',0
 
newprg_section_name db 'KolibriInWin_newprg',0
 
keycpu db 'HARDWARE\DESCRIPTION\System\CentralProcessor\0',0
keymhz db '~MHz',0
 
aIdentifier db 'Identifier',0
aConfigurationData db 'Configuration Data',0
 
perfstart db 'PerfStats\StartStat',0
perfget db 'PerfStats\StatData',0
perfend db 'PerfStats\StopStat',0
perfval db 'KERNEL\CPUUsage',0
aPerfInitFailed db 'Failed to init performance counter',0
 
exccode2number:
dd 0xC0000094 ; EXCEPTION_INT_DIVIDE_BY_ZERO
db 0 ; #DE
; dd 0x80000004 ; EXCEPTION_SINGLE_STEP (handled separately)
; db 1 ; #DB
dd 0x80000003 ; EXCEPTION_BREAKPOINT
db 0xD ; #GP (yes, in Kolibri it's #GP, not #BP)
dd 0xC0000095 ; EXCEPTION_INT_OVERFLOW
db 4 ; #OF
dd 0xC000008C ; EXCEPTION_ARRAY_BOUNDS_EXCEEDED
db 5 ; #BR
dd 0xC000001D ; EXCEPTION_ILLEGAL_INSTRUCTION
db 6 ; #UD
dd 0xC0000096 ; EXCEPTION_PRIV_INSTRUCTION
db 0xD ; #GP
dd 0xC0000005 ; EXCEPTION_ACCESS_VIOLATION
db 0xE ; #PF
dd 0x80000002 ; EXCEPTION_DATATYPE_MISALIGNMENT
db 0x11 ; #AC
dd 0xC000008D ; EXCEPTION_FLT_DENORMAL_OPERAND
db 0x10 ; #MF
dd 0xC000008E ; EXCEPTION_FLT_DIVIDE_BY_ZERO
db 0x10 ; #MF
dd 0xC000008F ; EXCEPTION_FLT_INEXACT_RESULT
db 0x10 ; #MF
dd 0xC0000090 ; EXCEPTION_FLT_INVALID_OPERATION
db 0x10 ; #MF
dd 0xC0000091 ; EXCEPTION_FLT_OVERFLOW
db 0x10 ; #MF
dd 0xC0000092 ; EXCEPTION_FLT_STACK_CHECK
db 0x10 ; #MF
dd 0xC0000093 ; EXCEPTION_FLT_UNDERFLOW
db 0x10 ; #MF
dd 0
 
section '.data' data readable writable
 
user32_thunks:
MessageBoxA dd rva MessageBoxA_thunk
wsprintfA dd rva wsprintfA_thunk
GetDC dd rva GetDC_thunk
ReleaseDC dd rva ReleaseDC_thunk
LoadIconA dd rva LoadIconA_thunk
LoadCursorA dd rva LoadCursorA_thunk
LoadImageA dd rva LoadImageA_thunk
RegisterClassExA dd rva RegisterClassExA_thunk
CreateWindowExA dd rva CreateWindowExA_thunk
MoveWindow dd rva MoveWindow_thunk
ShowWindow dd rva ShowWindow_thunk
DefWindowProcA dd rva DefWindowProcA_thunk
BeginPaint dd rva BeginPaint_thunk
EndPaint dd rva EndPaint_thunk
GetMessageA dd rva GetMessageA_thunk
PeekMessageA dd rva PeekMessageA_thunk
TranslateMessage dd rva TranslateMessage_thunk
DispatchMessageA dd rva DispatchMessageA_thunk
FillRect dd rva FillRect_thunk
PostQuitMessage dd rva PostQuitMessage_thunk
GetDesktopWindow dd rva GetDesktopWindow_thunk
GetAsyncKeyState dd rva GetAsyncKeyState_thunk
GetKeyboardState dd rva GetKeyboardState_thunk
SetCapture dd rva SetCapture_thunk
ReleaseCapture dd rva ReleaseCapture_thunk
GetCursorPos dd rva GetCursorPos_thunk
SetCursorPos dd rva SetCursorPos_thunk
InvalidateRect dd rva InvalidateRect_thunk
ValidateRect dd rva ValidateRect_thunk
SetWindowRgn dd rva SetWindowRgn_thunk
EnumThreadWindows dd rva EnumThreadWindows_thunk
PostMessageA dd rva PostMessageA_thunk
SendMessageTimeoutA dd rva SendMessageTimeoutA_thunk
GetDlgItemTextA dd rva GetDlgItemTextA_thunk
PaintDesktop dd rva PaintDesktop_thunk
SystemParametersInfoA dd rva SystemParametersInfoA_thunk
GetWindowRect dd rva GetWindowRect_thunk
GetWindowPlacement dd rva GetWindowPlacement_thunk
;BringWindowToTop dd rva BringWindowToTop_thunk
PostThreadMessageA dd rva PostThreadMessageA_thunk
CharToOemA dd rva CharToOemA_thunk
OemToCharA dd rva OemToCharA_thunk
IsWindowVisible dd rva IsWindowVisible_thunk
CreateIconFromResourceEx dd rva CreateIconFromResourceEx_thunk
CreateIconIndirect dd rva CreateIconIndirect_thunk
SetCursor dd rva SetCursor_thunk
DestroyCursor dd rva DestroyCursor_thunk
SetForegroundWindow dd rva SetForegroundWindow_thunk
dw 0
thunk MessageBoxA
thunk wsprintfA
thunk GetDC
thunk ReleaseDC
thunk CreateCompatibleDC
thunk LoadIconA
thunk LoadCursorA
thunk LoadImageA
thunk RegisterClassExA
thunk CreateWindowExA
thunk MoveWindow
thunk ShowWindow
thunk DefWindowProcA
thunk BeginPaint
thunk EndPaint
thunk GetMessageA
thunk PeekMessageA
thunk TranslateMessage
thunk DispatchMessageA
thunk PostQuitMessage
thunk GetDesktopWindow
thunk GetPixel
thunk SetPixel
thunk GetAsyncKeyState
thunk GetKeyboardState
thunk SetCapture
thunk ReleaseCapture
thunk GetCursorPos
thunk SetCursorPos
thunk InvalidateRect
thunk ValidateRect
thunk SetWindowRgn
thunk PostMessageA
thunk SendMessageTimeoutA
thunk EnumThreadWindows
thunk GetDlgItemTextA
thunk PaintDesktop
thunk SystemParametersInfoA
thunk GetWindowRect
thunk GetWindowPlacement
;thunk BringWindowToTop
thunk PostThreadMessageA
thunk IsWindowVisible
thunk CreateIconFromResourceEx
thunk CreateIconIndirect
thunk SetCursor
thunk DestroyCursor
thunk SetForegroundWindow
gdi32_thunks:
SetDIBitsToDevice dd rva SetDIBitsToDevice_thunk
GetDIBits dd rva GetDIBits_thunk
CreatePen dd rva CreatePen_thunk
SelectObject dd rva SelectObject_thunk
DeleteObject dd rva DeleteObject_thunk
CreateSolidBrush dd rva CreateSolidBrush_thunk
CreateBitmap dd rva CreateBitmap_thunk
CreateCompatibleDC dd rva CreateCompatibleDC_thunk
CreateCompatibleBitmap dd rva CreateCompatibleBitmap_thunk
BitBlt dd rva BitBlt_thunk
MoveToEx dd rva MoveToEx_thunk
LineTo dd rva LineTo_thunk
GetDeviceCaps dd rva GetDeviceCaps_thunk
GetPixel dd rva GetPixel_thunk
SetPixel dd rva SetPixel_thunk
SetROP2 dd rva SetROP2_thunk
Polyline dd rva Polyline_thunk
ExtCreateRegion dd rva ExtCreateRegion_thunk
DeleteDC dd rva DeleteDC_thunk
dw 0
thunk SetDIBitsToDevice
thunk GetDIBits
thunk CreatePen
thunk SelectObject
thunk DeleteObject
thunk CreateSolidBrush
thunk FillRect
thunk BitBlt
thunk CreateBitmap
thunk CreateCompatibleBitmap
thunk MoveToEx
thunk LineTo
thunk GetDeviceCaps
thunk SetROP2
thunk Polyline
thunk ExtCreateRegion
thunk DeleteDC
;comdlg32_thunks:
;GetOpenFileNameA dd rva GetOpenFileNameA_thunk
; dw 0
;thunk GetOpenFileNameA
 
align 4
ofn:
dd 76 ; lStructSize
dd 0 ; hWndOwner
dd ofn_arg_template ; hInstance
dd 0 ; lpstrFilter
dd 0 ; lpstrCustomFilter
dd 0 ; nMaxCustFilter
dd 0 ; nFilterIndex
dd inname ; lpstrFile
dd 100h ; nMaxFile
dd 0 ; lpstrFileTitle
dd 0 ; nMaxFileTitle
dd 0 ; lpstrInitialDir
dd ofn_title ; lpstrTitle
dd 818A4h ; flags
dw 0 ; nFileOffset
dw 0 ; nFileExtension
dd 0 ; lpstrDefExt
dd 0 ; lCustData
dd ofn_hook ; lpfnHook
dd 0 ; lpTemplateName
 
align 4
PlaySoundA dd PlaySoundA_delayed_imp
 
NumThreads dd 1
 
virtual at 0
shmem_item:
.name rb 32
.next dd ?
.prev dd ?
.refs dd ?
.ptr dd ?
.size dd ?
.access dd ?
.hOwner dd ?
.pOwner dd ?
.sizeof = $
end virtual
 
virtual at 0
shmem_proc_descr:
.next dd ?
.item dd ?
.ptr dd ?
.end dd ?
.access dd ?
.sizeof = $
end virtual
 
shmem_list dd shmem_list - shmem_item.next
dd shmem_list - shmem_item.next
 
DrvKeyValues:
dd aDisplayName, 1, kiw0_username, kiw0_drivername-kiw0_username-1
dd aType, 4, DrvKeyValues+4, 4
dd aStart, 4, addr3, 4
dd aErrorControl, 4, DrvKeyValues+4, 4
dd aImagePath, 1, win32_path, ?
drvpathlen = $-4
dd 0
 
keymfa db 'HARDWARE\DESCRIPTION\System\MultifunctionAdapter\'
idxmfa db '0'
db 0
 
hdxn db 'hd0n',0
hdpart db 'hd0_%d',0
hdxy_str db '/hd%d/%d/',0
 
bInitialized db 0
bCaptured db 0
 
label jmp_klbr fword
jmp_klbr_eip dd 0
klbr_cs dw 0Fh
klbr_ds dw 17h
klbr_null dw 0
label jmp_temp_int33 fword
dd 0
temp_cs dw 0
label jmp_temp_int1A fword
dd temp_code_int1A - temp_code
temp_cs2 dw 0
 
eee db 'exception in debuggee at '
eeeeip db '00000000'
db 0
 
; data for int40 emulating code - initialized
; from kernel.asm
keymap:
db '6',27,'1234567890-=',8,9 ; 0x00
db 'qwertyuiop[]',13,'~as' ; 0x10
db 'dfghjkl;',39,96,0,'\zxcv' ; 0x20
db 'bnm,./',0,'45 @23456' ; 0x30
db '7890123',180,178,184,'6',176,'7',179,'8',181 ; 0x40
db 177,183,185,182,'AB<D',255,'FGHIJKL' ; 0x50
db 'MNOPQRSTUVWXYZAB' ; 0x60
db 'CDEFGHIJKLMNOPQR' ; 0x70
keymap_shift:
db '6',27,'!@#$%^&*()_+',8,9 ; 0x00
db 'QWERTYUIOP{}',13,'~AS' ; 0x10
db 'DFGHJKL:"~',0,'|ZXCV' ; 0x20
db 'BNM<>?',0,'45 @23456' ; 0x30
db '7890123',180,178,184,'6',176,'7',179,'8',181 ; 0x40
db 177,183,185,182,'AB>D',255,'FGHIJKL' ; 0x50
db 'MNOPQRSTUVWXYZAB' ; 0x60
db 'CDEFGHIJKLMNOPQR' ; 0x70
keymap_alt:
db ' ',27,' @ $ {[]}\ ',8,9 ; 0x00
db ' ',13,' ' ; 0x10
db ' ',0,' ' ; 0x20
db ' ',0,'4',0,' ' ; 0x30
db ' ',180,178,184,'6',176,'7',179,'8',181 ; 0x40
db 177,183,185,182,'ABCD',255,'FGHIJKL' ; 0x50
db 'MNOPQRSTUVWXYZAB' ; 0x60
db 'CDEFGHIJKLMNOPQR' ; 0x70
 
numlock_map db '789-456+1230.'
 
version_inf:
db 0,7,1,0 ; emulate Kolibri 0.7.1.0
db 3 ; UID_KlbrInWin
dd 945 ; emulate revision 945
; (last change: functions 68.22 and 68.23)
version_end:
 
bCommonColorsSet db 0
 
bHaveDSA db 0
 
vk db 0
 
tls_index dd -1
 
max_pid dd 1
num_kolibri_proc dd 0
 
window_topleft:
dd 1, 21 ; type 1
dd 0, 0 ; no drawn window
dd 5, 20 ; type 2
dd 5, ? ; skinned
dd 5, ? ; skinned fixed-size
 
buttontype db 1
 
bgr_bmp_header:
db 'B','M'
dd ? ; size
dd 0
dd 36h
dd 28h
dd ? ; width
dd ? ; height
dw 1
dw 24
dd 0
dd ? ; size
dd 0,0
dd 0,0
 
wave_block_begin:
db 'RIFF'
dd ?
db 'WAVEfmt '
dd 10h
dw 1,1
wave_r dd 22050
dd 22050
dw 1,8
db 'data'
; dd ?
wbb_size = $ - wave_block_begin
 
; note that all uninitialized variables are set to 0 by Windows
sinfo dd 44h
rb 28h
dd 80h
rb 14h
 
tls_init_start:
times 24 db 0
dd 7 ; message_mask
dd 0 ; lpShapeData
dd 1 ; scale
db 1 ; curdraw
times tls.uninit_size db ?
tls_init_end:
 
bDontDebug db ?
keep_loaded_driver db ?
 
align 4
bgr_section dd ?
hBgrMutex dd ?
;dwNewBgrTime dd ?
 
SetBgrQuestion dd ?
 
newprg_section dd ?
 
hArrow dd ?
 
bIs9x db ?
bDriverLoaded db ?
heap_status db ?
 
align 4
inname rb 256
header rd 9
base dd ?
limit dd ?
fn9limit dd ?
heap_start dd ?
heap_control_block dd ?
heap_region_size dd ?
heap_critical_sec rb 0x18
DSACritSect rb 0x18
selector_data rb 8
selector_code rb 8
NtSetLdtEntries dd ?
idtr dp ?
pinfo:
hProcess dd ?
hThread dd ?
dwProcessId dd ?
dwThreadId dd ?
cur_slot dd ?
cur_tid_ptr dd ?
parent_tid_ptr dd ?
 
debugevent rd 18h
tids dd ?
pids dd ?
 
_cs dw ?
_ds dw ?
_esp dd ?
_eip dd ?
_fs dw ?
_gs dw ?
exc_code dd ?
exc_data dd ?
klbr_esp dd ?
 
temp_ss dw ?
temp_stack_size = 0x1000
temp_stack rb temp_stack_size
 
parameters dd ?
 
startcurdir rb 261
 
sound_vol db ?
 
align 4
context rd 0xB3
 
; data for int40 emulating code - uninitialized
hHeap dd ?
 
hSharedData dd ?
hSharedMutex dd ?
shared_data dd ?
 
_skinh dd ?
margins rw 4 ; right:left:bottom:top
skin_active_inner dd ?
skin_active_outer dd ?
skin_active_frame dd ?
skin_passive_inner dd ?
skin_passive_outer dd ?
skin_passive_frame dd ?
 
common_colors rb 128
 
left_bmp dd ?
oper_bmp dd ?
base_bmp dd ?
left1_bmp dd ?
oper1_bmp dd ?
base1_bmp dd ?
 
skin_btn_close:
.left dd ?
.top dd ?
.width dd ?
.height dd ?
skin_btn_minimize:
.left dd ?
.top dd ?
.width dd ?
.height dd ?
 
char_mt dd ?
char2_mt dd ?
 
process_name dd ?
 
ramdisk_path rb 512
converted_path rb 512
win32_path rb 512
 
hd_partitions_num rd 4
hd_partitions_array rd 4
 
cmdline rb 2000
process_curdir rb 4096 ; protected by the same mutex as for shared data
 
if driver_via_scm
hSCManager dd ?
hService dd ?
end if
 
ColorDepth dd ?
InvalidateTime dd ?
DSA dd ?
 
;WinSockDLL dd ?
 
align 4
unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp))
unpack.code_ dd ?
unpack.range dd ?
unpack.rep0 dd ?
unpack.rep1 dd ?
unpack.rep2 dd ?
unpack.rep3 dd ?
unpack.previousByte db ?
/programs/emulator/KlbrInWin/KlbrInWin.ico
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/emulator/KlbrInWin/config.RES
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/emulator/KlbrInWin/config.asm
0,0 → 1,1509
format PE GUI 4.0 at 400000h
section '.text' code readable executable
entry start
 
include 'config_resource.inc'
 
start:
call [GetProcessHeap]
mov [hHeap], eax
xor ebx, ebx
; SHBrowseForFolder requires CoInitialize (according to docs)
push 2
push ebx
call [CoInitializeEx]
mov edi, full_ini_name
push 1000
push edi
push ebx
call [GetModuleFileNameA]
@@:
inc edi
cmp byte [edi-1], 0
jnz @b
@@:
dec edi
cmp byte [edi-1], '\'
jnz @b
mov [pathzeroptr], edi
mov esi, IniFileName
@@:
lodsb
stosb
test al, al
jnz @b
push ebx ; hTemplateFile
push 80h ; dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL
push 1 ; dwCreationDisposition = CREATE_NEW
push ebx ; lpSecurityAttributes
push ebx ; dwShareMode
push 40000000h ; dwDesiredAccess = GENERIC_WRITE
push full_ini_name ; lpFileName
call [CreateFileA]
mov esi, eax
inc eax
jz .ini_exists
push eax
mov eax, esp
push ebx ; lpOverlapped
push eax ; lpNumberOfBytesWritten
push ini_size ; nNumberOfBytesToWrite
push ini ; lpBuffer
push esi ; hFile
call [WriteFile]
pop eax
push esi
call [CloseHandle]
.ini_exists:
push ebx
push DlgProc
push ebx
push IDD_DIALOG1
push 400000h
call [DialogBoxParamA]
push eax
call [CoUninitialize]
call [ExitProcess]
 
DlgProc:
push ebx
mov ebx, [esp+8]
mov eax, [esp+12]
cmp eax, 10h ; WM_CLOSE
jz .close
sub eax, 110h ; WM_INITDIALOG
jz .init
dec eax ; WM_COMMAND
jz .command
pop ebx
xor eax, eax
ret 16
.close:
push 0
push ebx
call [EndDialog]
.true:
pop ebx
xor eax, eax
inc eax
ret 16
.command:
cmp word [esp+16], 2 ; IDCANCEL
jz .close
cmp word [esp+16], IDC_HD_DEV
jnz .no_hd_dev
cmp word [esp+18], 1 ; LBN_SELCHANGE
jnz .true
.lastdel:
call OnSelectHdDev
jmp .true
.no_hd_dev:
cmp word [esp+16], IDC_HD_PART
jnz .no_hd_part
cmp word [esp+18], 1
jnz .true
cmp [cur_hd_dev], -1
jz .true
call OnSelectHdPart
jmp .true
.no_hd_part:
mov eax, IDC_SKIN
mov [filter], skn_filter
cmp word [esp+16], IDC_SKIN_BROWSE
jz @f
mov eax, IDC_FONT1
mov [filter], mt_filter
cmp word [esp+16], IDC_FONT1_BROWSE
jz @f
mov eax, IDC_FONT2
cmp word [esp+16], IDC_FONT2_BROWSE
jnz .nofilebrowse
@@:
push eax
push 512
push cur_ini_param
push eax
push ebx
call [GetDlgItemTextA]
push ofn
call [GetOpenFileNameA]
test eax, eax
pop eax
jz .true
push cur_ini_param
push eax
push ebx
call [SetDlgItemTextA]
jmp .true
.nofilebrowse:
mov eax, IDC_RAMDISK
cmp word [esp+16], IDC_RAMDISK_BROWSE
jz @f
mov eax, IDC_PARTITION
cmp word [esp+16], IDC_PARTITION_BROWSE
jnz .nodirbrowse
@@:
push eax
push 512
push cur_ini_param
push eax
push ebx
call [GetDlgItemTextA]
push bi
call [SHBrowseForFolder]
test eax, eax
pop ecx
jz .true
push ecx eax
push cur_ini_param
push eax
call [SHGetPathFromIDList]
test eax, eax
pop eax ecx
jz .nodir
push eax
push cur_ini_param
push ecx
push ebx
call [SetDlgItemTextA]
pop eax
.nodir:
push eax
push eax
push esp
call [SHGetMalloc]
pop eax
pop edx
push eax
push edx
push eax
mov eax, [eax]
call dword [eax+20]
pop eax
push eax
mov eax, [eax]
call dword [eax+8]
jmp .true
.nodirbrowse:
cmp word [esp+16], IDC_ADD_PARTITION
jnz .noadd
cmp [cur_hd_dev], -1
jz .true
push eax
call set_cur_part
pop eax
mov eax, [cur_hd_dev]
mov ecx, [hdns+eax*4]
inc cl
jnz @f
push 10h
push 0
push aTooManyPartitions
push ebx
call [MessageBoxA]
jmp .true
@@:
mov [hdns+eax*4], ecx
push eax
shl ecx, 9
mov edx, [hdpart+eax*4]
test edx, edx
jz .alloc
push ecx
push [hdpart+eax*4]
push 0
push [hHeap]
call [HeapReAlloc]
jmp @f
.alloc:
push ecx
push 0
push [hHeap]
call [HeapAlloc]
@@:
pop ecx
mov [hdpart+ecx*4], eax
call OnSelectHdDev
mov eax, [cur_hd_dev]
mov ecx, [hdns+eax*4]
dec ecx
mov eax, [hdpart+eax*4]
push 0
push ecx
shl ecx, 9
mov byte [eax+ecx], 0
mov byte [eax+ecx+511], 0
push 186h ; LB_SETCURSEL
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
call OnSelectHdPart
jmp .true
.noadd:
cmp word [esp+16], IDC_DEL_PARTITION
jnz .nodel
mov eax, [cur_hd_dev]
cmp eax, -1
jz .true
mov ecx, [hdns+eax*4]
dec ecx
js .true
mov [hdns+eax*4], ecx
push eax ecx
push 0
push ecx
push 182h ; LB_DELETESTRING
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
pop ecx eax
push eax
shl ecx, 9
push ecx
push [hdpart+eax*4]
push 0
push [hHeap]
call [HeapReAlloc]
pop ecx
mov [hdpart+ecx*4], eax
mov eax, [hdns+ecx*4]
test eax, eax
jz .lastdel
cmp [cur_hd_part], eax
jnz @f
or [cur_hd_part], -1
push 0
push eax
push 186h
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
@@:
call OnSelectHdPart
jmp .true
.nodel:
cmp word [esp+16], IDC_NOTEMPTY_EXT
jnz .noassoc
push 0
push 0
push 0F0h ; BM_GETCHECK
push IDC_NOTEMPTY_EXT
push ebx
call [SendDlgItemMessageA]
push eax
mov ecx, IDC_EXTENSIONS
call enable_part_items.1
pop eax
jmp .true
.noassoc:
cmp word [esp+16], 1 ; IDOK
jnz .true
call set_cur_part
; check input parameters
push esi
mov esi, [pathzeroptr]
mov byte [esi-1], 0
push full_ini_name
call [SetCurrentDirectoryA]
mov byte [esi-1], '\'
pop esi
mov ecx, IDC_RAMDISK
call check_file_exists
mov ecx, IDC_SKIN
call check_file_exists
mov ecx, IDC_FONT1
call check_file_exists
mov ecx, IDC_FONT2
call check_file_exists
; ramdisk
push 512
push cur_ini_param
push IDC_RAMDISK
push ebx
call [GetDlgItemTextA]
mov ecx, cur_ini_param
call add_trailing_slash
push full_ini_name
push cur_ini_param
push ramdisk_keyname
push aDisk
call [WritePrivateProfileStringA]
; hard disks - delete old values
push esi
xor esi, esi
mov [aHdNn+2], '0'
.readhd_del:
push full_ini_name ; lpFileName
push 0 ; nDefault
push aHdNn ; lpKeyName
push aDisk ; lpAppName
call [GetPrivateProfileIntA]
push eax
push full_ini_name
push 0
push aHdNn
push aDisk
call [WritePrivateProfileStringA]
pop eax
inc [aHdNn+2]
test eax, eax
jz .3
push eax
push 1
.2:
push dword [esp]
push esi
push aHdNM
push cur_ini_name
call [wsprintfA]
add esp, 10h
push full_ini_name
push 0
push cur_ini_name
push aDisk
call [WritePrivateProfileStringA]
pop ecx
inc ecx
cmp ecx, [esp]
ja @f
push ecx
jmp .2
@@:
pop eax
.3:
inc esi
cmp esi, 4
jb .readhd_del
; hard disks - write new values
xor esi, esi
mov [aHdNn+2], '0'
.writehd:
mov eax, [hdns+esi*4]
test eax, eax
jz .writehd_next
push edi
push -'0'
@@:
xor edx, edx
mov ecx, 10
div ecx
push edx
test eax, eax
jnz @b
@@:
mov edi, cur_ini_param
@@:
pop eax
add al, '0'
stosb
jnz @b
pop edi
push full_ini_name
push cur_ini_param
push aHdNn
push aDisk
call [WritePrivateProfileStringA]
push 1
.4:
push dword [esp]
push esi
push aHdNM
push cur_ini_name
call [wsprintfA]
add esp, 10h
pop eax
push eax
dec eax
shl eax, 9
push esi edi
mov esi, [hdpart+esi*4]
add esi, eax
mov edi, cur_ini_param
push esi
@@:
lodsb
stosb
test al, al
jnz @b
pop esi
cmp byte [esi+511], 0
jz @f
mov byte [edi-1], ','
mov dword [edi], 'read'
mov dword [edi+4], 'only'
mov byte [edi+8], 0
@@:
pop edi esi
push full_ini_name
push cur_ini_param
push cur_ini_name
push aDisk
call [WritePrivateProfileStringA]
pop ecx
inc ecx
cmp ecx, [hdns+esi*4]
ja .writehd_next
push ecx
jmp .4
.writehd_next:
inc [aHdNn+2]
inc esi
cmp esi, 4
jb .writehd
; skin file
push 512
push cur_ini_param
push IDC_SKIN
push ebx
call [GetDlgItemTextA]
push full_ini_name
push cur_ini_param
push aSkin
push aMain
call [WritePrivateProfileStringA]
; system fonts
push 512
push cur_ini_param
push IDC_FONT1
push ebx
call [GetDlgItemTextA]
push full_ini_name
push cur_ini_param
push aFont1
push aMain
call [WritePrivateProfileStringA]
push 512
push cur_ini_param
push IDC_FONT2
push ebx
call [GetDlgItemTextA]
push full_ini_name
push cur_ini_param
push aFont2
push aMain
call [WritePrivateProfileStringA]
; associations
push 0
push 0
push 0F0h
push IDC_EMPTY_EXT
push ebx
call [SendDlgItemMessageA]
cmp eax, [bWasEmptyAssoc]
jz .nomodify_empty_assoc
test eax, eax
jz .del_empty_assoc
mov esi, null
call add_assoc
jmp .nomodify_empty_assoc
.del_empty_assoc:
mov esi, null
call del_assoc
.nomodify_empty_assoc:
push edi
mov esi, cur_ext
mov byte [esi], 0
push 0
push 0
push 0F0h
push IDC_NOTEMPTY_EXT
push ebx
call [SendDlgItemMessageA]
test eax, eax
jz @f
push 1024
push esi
push IDC_EXTENSIONS
push ebx
call [GetDlgItemTextA]
@@:
.scan1loop:
mov edi, assoc_ext
call find_ext
jz @f
call add_assoc
@@:
lodsb
call is_ext_delim
jnz @b
test al, al
jz @f
cmp byte [esi], 0
jnz .scan1loop
@@:
mov esi, assoc_ext
cmp byte [esi], 0
jz .scan2done
.scan2loop:
mov edi, cur_ext
call find_ext
jz @f
call del_assoc
@@:
lodsb
call is_ext_delim
jnz @b
test al, al
jz @f
cmp byte [esi], 0
jnz .scan2loop
@@:
.scan2done:
pop edi
.nomodify_notempty_assoc:
pop esi
jmp .close
 
.init:
; window icons
push 0
push 16
push 16
push 1
push IDI_ICON1
push 400000h
call [LoadImageA]
push eax
push 0
push 80h
push ebx
call [SendMessageA]
push 0
push 32
push 32
push 1
push IDI_ICON1
push 400000h
call [LoadImageA]
push eax
push 1
push 80h
push ebx
call [SendMessageA]
; ramdisk
push full_ini_name ; lpFileName
push 512 ; nSize
push cur_ini_param ; lpReturnedString
push null ; lpDefault
push ramdisk_keyname ; lpKeyName
push aDisk ; lpAppName
call [GetPrivateProfileStringA]
push cur_ini_param
push IDC_RAMDISK
push ebx
call [SetDlgItemTextA]
; hard disks
push 4
pop ecx
@@:
push ecx
push aHdN
push 0
push 180h ; LB_ADDSTRING
push IDC_HD_DEV
push ebx
call [SendDlgItemMessageA]
inc [aHdN+3]
pop ecx
loop @b
push esi
xor esi, esi
.readhd:
push full_ini_name ; lpFileName
push 0 ; nDefault
push aHdNn ; lpKeyName
push aDisk ; lpAppName
call [GetPrivateProfileIntA]
inc [aHdNn+2]
mov [hdns+esi*4], eax
and [hdpart+esi*4], 0
push edi
test eax, eax
jz .nopart
shl eax, 9
push eax
push 0
push [hHeap]
call [HeapAlloc]
mov edi, eax
mov [hdpart+esi*4], eax
push 1
.1:
push dword [esp]
push esi
push aHdNM
push cur_ini_name
call [wsprintfA]
add esp, 10h
mov byte [edi+511], 0
push full_ini_name
push 511
push edi
push null
push cur_ini_name
push aDisk
call [GetPrivateProfileStringA]
mov eax, edi
@@:
inc eax
cmp byte [eax], 0
jnz @b
sub eax, 9
cmp eax, edi
jbe @f
cmp byte [eax], ','
jnz @f
cmp dword [eax+1], 'read'
jnz @f
cmp dword [eax+5], 'only'
jnz @f
mov byte [eax], 0
mov byte [edi+511], 1
@@:
add edi, 512
pop ecx
inc ecx
cmp ecx, [hdns+esi*4]
ja .nopart
push ecx
jmp .1
.nopart:
pop edi
inc esi
cmp esi, 4
jb .readhd
pop esi
push 0
push 0
push 186h ; LB_SETCURSEL
push IDC_HD_DEV
push ebx
call [SendDlgItemMessageA]
call OnSelectHdDev
; skin
push full_ini_name ; lpFileName
push 512 ; nSize
push cur_ini_param ; lpReturnedString
push null ; lpDefault
push aSkin ; lpKeyName
push aMain ; lpAppName
call [GetPrivateProfileStringA]
push cur_ini_param
push IDC_SKIN
push ebx
call [SetDlgItemTextA]
; fonts
push full_ini_name ; lpFileName
push 512 ; nSize
push cur_ini_param ; lpReturnedString
push null ; lpDefault
push aFont1 ; lpKeyName
push aMain ; lpAppName
call [GetPrivateProfileStringA]
push cur_ini_param
push IDC_FONT1
push ebx
call [SetDlgItemTextA]
push full_ini_name ; lpFileName
push 512 ; nSize
push cur_ini_param ; lpReturnedString
push null ; lpDefault
push aFont2 ; lpKeyName
push aMain ; lpAppName
call [GetPrivateProfileStringA]
push cur_ini_param
push IDC_FONT2
push ebx
call [SetDlgItemTextA]
push emptyExt
call check_association
mov [bWasEmptyAssoc], eax
push 0
push eax
push 0F1h ; BM_SETCHECK
push IDC_EMPTY_EXT
push ebx
call [SendDlgItemMessageA]
push esi edi
xor esi, esi
mov edi, assoc_ext
.enum:
push 1024
mov eax, esp
push 0
push 0
push 0
push 0
push eax
push cur_ext
push esi
push 80000000h
call [RegEnumKeyExA]
test eax, eax
pop eax
jnz .enum_done
cmp byte [cur_ext], '.'
jnz .next
cmp byte [cur_ext+1], 0
jz .next
push cur_ext
call check_association
jz .next
push esi
mov esi, cur_ext+1
@@:
lodsb
stosb
test al, al
jnz @b
mov byte [edi-1], ';'
pop esi
.next:
inc esi
jmp .enum
.enum_done:
mov byte [edi], 0
pop edi esi
xor eax, eax
cmp byte [assoc_ext], 0
setnz al
push 0
push eax
push 0F1h
push IDC_NOTEMPTY_EXT
push ebx
call [SendDlgItemMessageA]
cmp byte [assoc_ext], 0
jz .no_custom
push assoc_ext
push IDC_EXTENSIONS
push ebx
call [SetDlgItemTextA]
jmp .assoc_done
.no_custom:
push def_custom_assoc
push IDC_EXTENSIONS
push ebx
call [SetDlgItemTextA]
push 0
mov ecx, IDC_EXTENSIONS
call enable_part_items.1
pop eax
.assoc_done:
pop ebx
xor eax, eax
ret 16
 
set_cur_part:
cmp [cur_hd_dev], -1
jz .ret
cmp [cur_hd_part], -1
jnz @f
.ret:
ret
@@:
push eax ecx
mov ecx, [cur_hd_part]
mov eax, [cur_hd_dev]
shl ecx, 9
add ecx, [hdpart+eax*4]
push ecx
push 510
push ecx
push IDC_PARTITION
push ebx
call [GetDlgItemTextA]
push dword [esp]
call [GetFileAttributesA]
cmp eax, -1
jz .err
test al, 10h
jz .err
push 0
push 0
push 0F0h ; BM_GETCHECK
push IDC_CHECK1
push ebx
call [SendDlgItemMessageA]
pop ecx
mov [ecx+511], al
call add_trailing_slash
pop ecx eax
ret
.err:
push 10h
push 0
push aInvalidPath
push ebx
call [MessageBoxA]
pop ecx
pop ecx eax
pop eax eax
push 0
push [cur_hd_dev]
push 186h
push IDC_HD_DEV
push ebx
call [SendDlgItemMessageA]
push 0
push [cur_hd_part]
push 186h
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
call focus_on_path
jmp DlgProc.true
 
focus_on_path:
push IDC_PARTITION
push ebx
call [GetDlgItem]
push eax
call [SetFocus]
ret
 
add_trailing_slash:
inc ecx
cmp byte [ecx], 0
jnz add_trailing_slash
cmp byte [ecx-1], '\'
jz @f
mov word [ecx], '\'
@@:
ret
 
enable_part_items:
push eax
mov ecx, IDC_PATH_STRING
call .1
mov ecx, IDC_PARTITION
call .1
mov ecx, IDC_PARTITION_BROWSE
call .1
mov ecx, IDC_CHECK1
call .1
pop eax
ret
 
.1:
push ecx
push ebx
call [GetDlgItem]
push dword [esp+4]
push eax
call [EnableWindow]
ret
 
OnSelectHdDev:
push 0
push 0
push 188h ; LB_GETCURSEL
push IDC_HD_DEV
push ebx
call [SendDlgItemMessageA]
cmp eax, 4
jae .ret
call set_cur_part
mov [cur_hd_dev], eax
or [cur_hd_part], -1
push eax
xor eax, eax
call enable_part_items
push null
push IDC_PARTITION
push ebx
call [SetDlgItemTextA]
push 0
push 0
push 0F1h ; BM_SETCHECK
push IDC_CHECK1
push ebx
call [SendDlgItemMessageA]
push 0
push 0
push 184h ; LB_RESETCONTENT
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
pop eax
cmp dword [hdns+eax*4], 0
jnz .haspart
push aNone
push 0
push 180h ; LB_ADDSTRING
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
push 0
.done:
mov ecx, IDC_HD_PART
call enable_part_items.1
mov ecx, IDC_DEL_PARTITION
call enable_part_items.1
pop eax
.ret:
ret
.haspart:
push esi
mov esi, eax
push 1
@@:
push dword [esp]
push esi
push aHdNM2
push cur_ini_name
call [wsprintfA]
add esp, 10h
push cur_ini_name
push 0
push 180h
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
pop ecx
inc ecx
cmp ecx, [hdns+esi*4]
ja @f
push ecx
jmp @b
@@:
pop esi
push 1
jmp .done
 
OnSelectHdPart:
push 0
push 0
push 188h
push IDC_HD_PART
push ebx
call [SendDlgItemMessageA]
mov ecx, [cur_hd_dev]
cmp eax, [hdns+ecx*4]
jae .ret
call set_cur_part
mov [cur_hd_part], eax
mov ecx, [hdpart+ecx*4]
shl eax, 9
add ecx, eax
push ecx
movzx eax, byte [ecx+511]
push 0
push eax
push 0F1h ; BM_SETCHECK
push IDC_CHECK1
push ebx
call [SendDlgItemMessageA]
push IDC_PARTITION
push ebx
call [SetDlgItemTextA]
xor eax, eax
inc eax
call enable_part_items
call focus_on_path
.ret:
ret
 
check_association:
push hkey
push 1 ; KEY_QUERY_VALUE
push 0
push dword [esp+16]
push 80000000h ; HKEY_CLASSES_ROOT
call [RegOpenKeyExA]
test eax, eax
jnz .not
push 1000
push esp
push cur_ini_param
push 0
push 0
push 0
push [hkey]
call [RegQueryValueExA]
mov [esp], eax
push [hkey]
call [RegCloseKey]
pop eax
test eax, eax
jnz .not
push esi edi
mov edi, cur_ini_param
@@:
inc edi
cmp byte [edi-1], 0
jnz @b
dec edi
mov esi, aShellOpenCommand
@@:
lodsb
stosb
test al, al
jnz @b
pop edi esi
push hkey
push 1
push 0
push cur_ini_param
push 80000000h
call [RegOpenKeyExA]
test eax, eax
jnz .not
push 1024
push esp
push cur_ini_param
push 0
push 0
push 0
push [hkey]
call [RegQueryValueExA]
mov [esp], eax
push [hkey]
call [RegCloseKey]
pop eax
test eax, eax
jnz .not
push esi edi
mov edi, cur_ini_param
.scan:
cmp byte [edi], 0
jz .scanno
mov esi, ExeFileName
mov ecx, ExeFileNameLen
push edi
repz cmpsb
pop edi
jz .scanok
inc edi
jmp .scan
.scanno:
pop edi esi
.not:
xor eax, eax
ret 4
.scanok:
pop edi esi
xor eax, eax
inc eax
ret 4
 
add_assoc:
call form_ext_name
push ebx
xor ebx, ebx
push ebx
push hkey
push ebx
push 2 ; KEY_SET_VALUE
push ebx
push ebx
push ebx
push edi
push 80000000h
call [RegCreateKeyExA]
test eax, eax
jnz .ret
push aKolibriExecutable.size
push aKolibriExecutable
push 1 ; REG_SZ
push ebx
push ebx
push [hkey]
call [RegSetValueExA]
push eax
push [hkey]
call [RegCloseKey]
pop eax
test eax, eax
jnz .ret
push ebx
push hkey
push ebx
push 6 ; KEY_SET_VALUE + KEY_CREATE_SUB_KEY
push ebx
push ebx
push ebx
push aKolibriExecutable
push 80000000h
call [RegCreateKeyExA]
test eax, eax
jnz .ret
push edi
mov edi, cur_ini_param
mov al, '"'
stosb
call get_exe_name
mov al, '"'
stosb
mov eax, ' "%1'
stosd
mov al, '"'
stosb
mov al, 0
stosb
push [hkey]
push ebx
push hkey
push ebx
push 2 ; KEY_SET_VALUE
push ebx
push ebx
push ebx
push aShellOpenCommand2
push [hkey]
call [RegCreateKeyExA]
test eax, eax
jnz .ret2
mov eax, cur_ini_param
sub edi, eax
push edi
push eax
push 1
push ebx
push ebx
push [hkey]
call [RegSetValueExA]
push [hkey]
call [RegCloseKey]
mov edi, cur_ini_param
call get_exe_name
mov al, 0
stosb
pop eax
push eax
push ebx
push hkey
push ebx
push 2
push ebx
push ebx
push ebx
push aDefaultIcon
push eax
call [RegCreateKeyExA]
test eax, eax
jnz .ret2
mov eax, cur_ini_param
sub edi, eax
push edi
push eax
push 1
push ebx
push ebx
push [hkey]
call [RegSetValueExA]
push [hkey]
call [RegCloseKey]
.ret2:
call [RegCloseKey]
pop edi
.ret:
pop ebx
ret
 
del_assoc:
call form_ext_name
push edi
push 80000000h
call [RegDeleteKeyA]
ret
 
form_ext_name:
push esi
mov edi, cur_ini_param
push edi
mov al, '.'
stosb
@@:
lodsb
stosb
call is_ext_delim
jnz @b
mov byte [edi-1], 0
pop edi esi
ret
 
get_exe_name:
push esi
mov esi, full_ini_name
@@:
lodsb
stosb
test al, al
jnz @b
@@:
dec edi
cmp byte [edi-1], '\'
jnz @b
mov esi, ExeFileName
mov ecx, ExeFileNameLen
rep movsb
pop esi
ret
 
check_file_exists:
push ecx
push 512
push cur_ini_param
push ecx
push ebx
call [GetDlgItemTextA]
push cur_ini_param
call [GetFileAttributesA]
inc eax
jz .err
pop ecx
ret
.err:
push 10h
push 0
push aInvalidFile
push ebx
call [MessageBoxA]
push ebx
call [GetDlgItem]
push eax
call [SetFocus]
pop eax
jmp DlgProc.true
 
find_ext:
push esi
@@:
lodsb
scasb
jnz @f
call is_ext_delim
jnz @b
.ret:
pop esi
ret
@@:
call is_ext_delim
jnz .next
mov al, byte [edi-1]
call is_ext_delim
jz .ret
.next:
pop esi
dec edi
@@:
inc edi
mov al, byte [edi-1]
call is_ext_delim
jnz @b
test al, al
jz @f
cmp byte [edi], 0
jnz find_ext
@@:
inc edi
ret
 
is_ext_delim:
test al, al
jz @f
cmp al, ','
jz @f
cmp al, ';'
@@: ret
 
align 4
data import
macro thunk a {
a#_thunk:dw 0
db `a,0}
dd 0,0,0, rva kernel32_name, rva kernel32_thunks
dd 0,0,0, rva user32_name, rva user32_thunks
dd 0,0,0, rva advapi32_name, rva advapi32_thunks
dd 0,0,0, rva shell32_name, rva shell32_thunks
dd 0,0,0, rva ole32_name, rva ole32_thunks
dd 0,0,0, rva comdlg32_name, rva comdlg32_thunks
dd 0,0,0,0,0
kernel32_name db 'kernel32.dll',0
user32_name db 'user32.dll',0
advapi32_name db 'advapi32.dll',0
comdlg32_name db 'comdlg32.dll',0
shell32_name db 'shell32.dll',0
ole32_name db 'ole32.dll',0
kernel32_thunks:
GetFileAttributesA dd rva GetFileAttributesA_thunk
CreateFileA dd rva CreateFileA_thunk
WriteFile dd rva WriteFile_thunk
CloseHandle dd rva CloseHandle_thunk
SetCurrentDirectoryA dd rva SetCurrentDirectoryA_thunk
GetPrivateProfileIntA dd rva GetPrivateProfileIntA_thunk
GetPrivateProfileStringA dd rva GetPrivateProfileStringA_thunk
WritePrivateProfileStringA dd rva WritePrivateProfileStringA_thunk
GetModuleFileNameA dd rva GetModuleFileNameA_thunk
GetProcessHeap dd rva GetProcessHeap_thunk
HeapAlloc dd rva HeapAlloc_thunk
HeapReAlloc dd rva HeapReAlloc_thunk
ExitProcess dd rva ExitProcess_thunk
dw 0
thunk GetFileAttributesA
thunk CreateFileA
thunk WriteFile
thunk CloseHandle
thunk SetCurrentDirectoryA
thunk GetPrivateProfileIntA
thunk GetPrivateProfileStringA
thunk WritePrivateProfileStringA
thunk GetModuleFileNameA
thunk GetProcessHeap
thunk HeapAlloc
thunk HeapReAlloc
thunk ExitProcess
user32_thunks:
DialogBoxParamA dd rva DialogBoxParamA_thunk
EndDialog dd rva EndDialog_thunk
GetDlgItem dd rva GetDlgItem_thunk
GetDlgItemTextA dd rva GetDlgItemTextA_thunk
SetDlgItemTextA dd rva SetDlgItemTextA_thunk
EnableWindow dd rva EnableWindow_thunk
SendDlgItemMessageA dd rva SendDlgItemMessageA_thunk
wsprintfA dd rva wsprintfA_thunk
MessageBoxA dd rva MessageBoxA_thunk
SetFocus dd rva SetFocus_thunk
LoadImageA dd rva LoadImageA_thunk
SendMessageA dd rva SendMessageA_thunk
dw 0
thunk DialogBoxParamA
thunk EndDialog
thunk GetDlgItem
thunk GetDlgItemTextA
thunk SetDlgItemTextA
thunk EnableWindow
thunk SendDlgItemMessageA
thunk wsprintfA
thunk MessageBoxA
thunk SetFocus
thunk LoadImageA
thunk SendMessageA
advapi32_thunks:
RegOpenKeyExA dd rva RegOpenKeyExA_thunk
RegQueryValueExA dd rva RegQueryValueExA_thunk
RegCloseKey dd rva RegCloseKey_thunk
RegEnumKeyExA dd rva RegEnumKeyExA_thunk
RegDeleteKeyA dd rva RegDeleteKeyA_thunk
RegCreateKeyExA dd rva RegCreateKeyExA_thunk
RegSetValueExA dd rva RegSetValueExA_thunk
dw 0
thunk RegOpenKeyExA
thunk RegQueryValueExA
thunk RegCloseKey
thunk RegEnumKeyExA
thunk RegDeleteKeyA
thunk RegCreateKeyExA
thunk RegSetValueExA
comdlg32_thunks:
GetOpenFileNameA dd rva GetOpenFileNameA_thunk
dw 0
thunk GetOpenFileNameA
ole32_thunks:
CoInitializeEx dd rva CoInitializeEx_thunk
CoUninitialize dd rva CoUninitialize_thunk
dw 0
thunk CoInitializeEx
thunk CoUninitialize
shell32_thunks:
SHGetMalloc dd rva SHGetMalloc_thunk
SHBrowseForFolder dd rva SHBrowseForFolder_thunk
SHGetPathFromIDList dd rva SHGetPathFromIDList_thunk
dw 0
thunk SHGetMalloc
thunk SHBrowseForFolder
thunk SHGetPathFromIDList
end data
 
align 10h
data resource from 'config.res'
end data
 
section '.data' data readable writable
 
IniFileName db 'KlbrInWin.ini',0
ExeFileName db 'KlbrInWin.exe'
ExeFileNameLen = $ - ExeFileName
null db 0
aDisk db 'Disk',0
aMain db 'Main',0
ramdisk_keyname db 'RamDisk',0
aSkin db 'Skin',0
aFont1 db 'Font1',0
aFont2 db 'Font2',0
aHdN db '/hd0',0
aHdNn db 'hd0n',0
aHdNM db 'hd%d_%d',0
aHdNM2 db '/hd%d/%d',0
aNone db '(none)',0
emptyExt db '.',0
def_custom_assoc db 'kex;',0
aShellOpenCommand db '\'
aShellOpenCommand2 db 'shell\open\command',0
aKolibriExecutable db 'KolibriExecutable',0
.size = $ - aKolibriExecutable
aDefaultIcon db 'DefaultIcon',0
ini:
file 'config.ini'
ini_size = $ - ini
 
align 4
ofn:
dd 76 ; lStructSize
dd 0 ; hWndOwner
dd 0 ; hInstance
filter dd 0 ; lpstrFilter
dd 0 ; lpstrCustomFilter
dd 0 ; nMaxCustFilter
dd 0 ; nFilterIndex
dd cur_ini_param ; lpstrFile
dd 512 ; nMaxFile
dd 0 ; lpstrFileTitle
dd 0 ; nMaxFileTitle
dd 0 ; lpstrInitialDir
; dd ofn_title ; lpstrTitle
dd 0
dd 81804h ; flags
dw 0 ; nFileOffset
dw 0 ; nFileExtension
dd 0 ; lpstrDefExt
dd 0 ; lCustData
dd 0 ; lpfnHook
dd 0 ; lpTemplateName
 
bi:
dd 0 ; hwndOwner
dd 0 ; pidlRoot
dd cur_ini_param ; pszDisplayName
dd bi_title; lpszTitle
dd 1 ; BIF_RETURNONLYFSDIRS
dd 0 ; lpfn
dd 0 ; lParam
dd 0 ; iImage
 
cur_hd_dev dd -1
cur_hd_part dd -1
 
bWasEmptyAssoc dd 0
 
skn_filter db 'Skin files (*.skn)',0,'*.skn',0,'All files (*.*',0,'*.*',0,0
mt_filter db 'Files *.mt',0,'*.mt',0,'All files (*.*)',0,'*.*',0,0
 
bi_title db 'Select folder for root of emulated file system:',0
 
aInvalidPath db 'Entered path is invalid or does not specify a directory',0
aInvalidFile db 'The mentioned file does not exist',0
aTooManyPartitions db 'Too many partitions! (maximum 255 per device is allowed)',0
 
align 4
hHeap dd ?
hkey dd ?
pathzeroptr dd ?
full_ini_name rb 1024
cur_ini_param rb 1024
cur_ini_name rb 32
hdns rd 4
hdpart rd 4
cur_ext rb 1024
assoc_ext rb 1024
/programs/emulator/KlbrInWin/config.ini
0,0 → 1,80
[Disk]
# path to ramdisk, must end with '\'
RamDisk=
 
# hard disks:
# there may be up to 4 physical harddisks,
# each may contain 1 or more partitions (but no more than 255)
# (sysfunction 18::11 returns this number as byte)
# 255 should be enough :-)
# Syntax:
# hd<i>n = number of partitions for /hd<i>, 0 <= i <= 3
# hd<i>_<j> = Win32 path for /hd<i>/<j>, 0 <= i <= 3, 1 <= j <= hd<i>n
# must end with '\'; ',readonly' string may follow
# (j is represented in decimal system)
# (if harddisk /hd<i> is used, all partitions /hd<i>/<j> must be defined)
 
[Main]
# skin file name
Skin=orqua.skn
 
# first font must be 9*0x100 bytes, second 10*0x100 bytes
Font1=char.mt
Font2=char2.mt
 
# DO NOT MODIFY THIS PARAMETER UNLESS YOU KNOW WHAT ARE YOU DOING!!!
# if this parameter is not empty,
# on NT/2k/XP+ administrator rights are required
# enables i/o ports for function 46
# all ports from this parameter can be reserved with fn46,
# and (after reservation) may be accessed via in/out.
# DO NOT ADD SYSTEM CRITICAL PORTS!!!
# USE THIS PARAMETER ONLY AT YOUR OWN RISK!!!
# note that Menuet/Kolibri reserves ports 0-FF for system use
# syntax: EnablePorts=port1 port2beg-port2end port3 ...
# (when range is used, both begin and end are included)
# example (only for syntax demonstration!!!): EnablePorts=A3 B1 92-9f 70-74 269
# total length of parameter string is limited to 1024 chars (must be enough :) )
EnablePorts=
 
# boolean parameters (true/false)
# if at least one of these parameters is true,
# on NT/2k/XP+ administrator rights are required
 
# enables function 68.3
AllowReadMSR=false
# enables function 62
AllowReadPCI=false
 
# do not unload driver when exiting
KeepLoadedDriver=false
 
[Questions]
# on set background question
# 0=ask, 1=set permanently, 2=set temporarily, 3=don't set
SetBgr=0
 
[sys_setup]
# kernel global variable sound_flag
# 0=playnote sound on, 1=off (it is for 55::55 function only)
sound_flag=0
# 0=min (no sound), 127=max
sound_vol=10
 
# kernel global variable syslang (see functions 21::5, 26::5)
# 1=eng 2=fi 3=ger 4=ru
syslang=1
 
# kernel global variable keyboard (see functions 21::2::9, 26::2::9)
# 1=eng 2=fi 3=ger 4=ru
# Note that this definition doesn't affect keymap tables,
# it only sets variable for functions above
# (in Kolibri application @panel/setup changes keymap tables)
keyboard=1
 
[DirectScreenAccess]
# bits per pixel, currently supported 0 (=disable), 24, 32
ColorDepth=32
# When the program first accesses [gs:N] data, the snapshot is created.
# Other accesses within InvalidateTime milliseconds use this snapshot.
DSAInvalidateTime=200
/programs/emulator/KlbrInWin/config_resource.inc
0,0 → 1,21
IDD_DIALOG1 = 101
IDI_ICON1 = 103
IDC_RAMDISK = 1001
IDC_RAMDISK_BROWSE = 1002
IDC_PARTITION = 1003
IDC_HD_DEV = 1004
IDC_HD_PART = 1005
IDC_ADD_PARTITION = 1006
IDC_DEL_PARTITION = 1007
IDC_PARTITION_BROWSE = 1008
IDC_CHECK1 = 1009
IDC_SKIN = 1010
IDC_SKIN_BROWSE = 1011
IDC_FONT1 = 1012
IDC_FONT1_BROWSE = 1013
IDC_FONT2 = 1014
IDC_FONT2_BROWSE = 1015
IDC_EMPTY_EXT = 1016
IDC_NOTEMPTY_EXT = 1017
IDC_EXTENSIONS = 1018
IDC_PATH_STRING = 1019
/programs/emulator/KlbrInWin/kiw0.asm
0,0 → 1,238
; kiw0.sys - KlbrInWin ring-0 component
; (c) diamond, 2006, 2007, 2008
; Cb-n#%li.-# @l$i Lkbnbe
DRIVER_VERSION = 1
format PE native
section '.text' code data readable writable executable
;section '.text' code readable executable
entry start
start:
push eax
push esp
push 0
push 0
push 22h ; FILE_DEVICE_UNKNOWN
push devname
push 0
push dword [esp+20h]
call [IoCreateDevice]
pop ecx
test eax, eax
js .ret
push ecx
push devname
push symlinkname
call [IoCreateSymbolicLink]
pop ecx
test eax, eax
jns @f
push eax
push ecx
call [IoDeleteDevice]
pop eax
jmp .ret
@@:
mov eax, [esp+4]
mov dword [eax+38h], DispatchCreateClose
mov dword [eax+40h], DispatchCreateClose
mov dword [eax+70h], DispatchControl
mov dword [eax+34h], DriverUnload
push 'kiw0'
push 2000h
push 0
call [ExAllocatePoolWithTag]
mov [oldiomap], eax
push eax
push 1
call [Ke386QueryIoAccessMap]
xor eax, eax
.ret:
ret 8
 
DriverUnload:
push symlinkname
call [IoDeleteSymbolicLink]
mov eax, [esp+4]
push dword [eax+4]
call [IoDeleteDevice]
push [oldiomap]
push 1
call [Ke386SetIoAccessMap]
push [oldiomap]
call [ExFreePool]
ret 4
 
DispatchCreateClose:
mov ecx, [esp+8]
xor edx, edx
mov [ecx+18h], edx
mov [ecx+1Ch], edx
call [IofCompleteRequest]
xor eax, eax
ret 8
 
DispatchControl:
mov ecx, [esp+8]
mov eax, [ecx+60h]
cmp dword [eax+0Ch], 0x222000
jz .readmsr
cmp dword [eax+0Ch], 0x222004
jz .readpci
cmp dword [eax+0Ch], 0x222008
jz .getversion
cmp dword [eax+0Ch], 0x22203C
jnz .invreq
cmp dword [eax+8], 2000h
jnz .invreq
push ecx
push dword [ecx+0Ch]
push 1
call [Ke386SetIoAccessMap]
push 1
call [IoGetCurrentProcess]
push eax
call [Ke386IoSetAccessProcess]
str ax
sub esp, 6
sgdt [esp]
pop cx
pop ecx
movzx eax, ax
mov dh, [eax+ecx+7]
mov dl, [eax+ecx+4]
shl edx, 16
mov dx, [eax+ecx+2]
mov word [edx+66h], 88h
pop ecx
xor eax, eax
mov [ecx+1Ch], eax
jmp .ret
.getversion:
cmp dword [eax+4], 4
jnz .invreq
mov eax, [ecx+0Ch]
mov dword [eax], DRIVER_VERSION
mov dword [ecx+1Ch], 4
jmp .ret0
.readmsr:
cmp dword [eax+8], 4
jnz .invreq
cmp dword [eax+4], 9
jnz .invreq
push ecx
mov ecx, [ecx+0Ch]
mov byte [ecx+8], 0 ; assume OK
; rdmsr may throw exception
push .exception_handler
push dword [fs:0]
mov [fs:0], esp
push ecx
mov ecx, [ecx]
rdmsr
pop ecx
mov [ecx], eax
mov [ecx+4], edx
.msr_common:
pop dword [fs:0]
pop ecx
pop ecx
mov dword [ecx+1Ch], 9
.ret0:
xor eax, eax
jmp .ret
.invreq2:
pop ecx
.invreq:
mov eax, 0xC0000010 ; STATUS_INVALID_DEVICE_REQUEST
.ret:
push eax
mov [ecx+18h], eax
xor edx, edx
call [IofCompleteRequest]
pop eax
ret 8
.exception_handler:
mov eax, [esp+12]
mov dword [eax+0xB8], .no_msr
xor eax, eax
ret
.no_msr:
pop ecx
mov byte [ecx+8], 1
jmp .msr_common
.readpci:
cmp dword [eax+8], 4
jnz .invreq
cmp dword [eax+4], 4
jnz .invreq
push ecx
mov ecx, [ecx+0Ch]
movzx eax, byte [ecx]
cmp al, 2
ja .invreq2
jb @f
inc eax
@@:
test byte [ecx+2], al
jnz .readpci.unaligned
inc eax
push eax
push eax ; Length
movzx eax, byte [ecx+2]
push eax ; Offset
push ecx ; Buffer
movzx eax, byte [ecx+3]
ror al, 3
push eax ; SlotNumber
movzx eax, byte [ecx+1]
push eax ; BusNumber
push 4 ; PCIConfiguration
or dword [ecx], -1
call [HalGetBusDataByOffset]
pop edx
pop ecx
mov dword [ecx+1Ch], edx
jmp .ret0
.readpci.unaligned:
or dword [ecx], -1
pop ecx
mov dword [ecx+1Ch], 4
jmp .ret0
 
include 'd:\program files\fasm\fasmw16723\include\win32a.inc'
data import
library ntoskrnl,'ntoskrnl.exe',hal,'hal.dll'
import ntoskrnl, \
IoCreateDevice, 'IoCreateDevice', \
IoCreateSymbolicLink, 'IoCreateSymbolicLink', \
IoDeleteDevice, 'IoDeleteDevice', \
IoDeleteSymbolicLink, 'IoDeleteSymbolicLink', \
IoGetCurrentProcess, 'IoGetCurrentProcess', \
Ke386QueryIoAccessMap, 'Ke386QueryIoAccessMap', \
Ke386SetIoAccessMap, 'Ke386SetIoAccessMap', \
Ke386IoSetAccessProcess, 'Ke386IoSetAccessProcess', \
IofCompleteRequest, 'IofCompleteRequest', \
ExAllocatePoolWithTag, 'ExAllocatePoolWithTag', \
ExFreePool, 'ExFreePool'
import hal, HalGetBusDataByOffset, 'HalGetBusDataByOffset'
end data
 
str1 db 'control code 0x%X',13,10,0
str2 db 'kiw0 loaded',13,10,0
 
devname:
dw 12*2
dw 13*2
dd @f
@@ du '\Device\kiw0',0
symlinkname:
dw 16*2
dw 17*2
dd @f
@@ du '\DosDevices\kiw0',0
 
data fixups
end data
 
;section '.data' data readable writable
oldiomap dd ?
/programs/emulator/KlbrInWin/unpacker.inc
0,0 → 1,492
; void __stdcall unpack(void* packed_data, void* unpacked_data);
unpack:
pushad
mov esi, [esp+32+4]
mov edi, [esp+32+8]
mov eax, [esi+8]
and al, 0xC0
cmp al, 0xC0
jz .failed
mov eax, [esi+8]
push eax
add esi, 12
and al, not 0xC0
dec eax
jz .lzma
.failed:
pop eax
popad
ret 8
.lzma:
call .lzma_unpack
.common:
pop eax
test al, 0x80
jnz .ctr1
test al, 0x40
jz .ok
lodsd
mov ecx, eax
jecxz .ok
mov dl, [esi]
mov esi, [esp+32+8]
.c1:
lodsb
sub al, 0E8h
cmp al, 1
ja .c1
cmp byte [esi], dl
jnz .c1
lodsd
; "bswap eax" is not supported on i386
shr ax, 8
ror eax, 16
xchg al, ah
sub eax, esi
add eax, [esp+32+8]
mov [esi-4], eax
loop .c1
.ok:
popad
ret 8
.ctr1:
lodsd
mov ecx, eax
jecxz .ok
mov dl, [esi]
mov esi, [esp+32+8]
.c2:
lodsb
@@:
cmp al, 0xF
jnz .f
lodsb
cmp al, 80h
jb @b
cmp al, 90h
jb @f
.f:
sub al, 0E8h
cmp al, 1
ja .c2
@@:
cmp byte [esi], dl
jnz .c2
lodsd
shr ax, 8
ror eax, 16
xchg al, ah
sub eax, esi
add eax, [esp+32+8]
mov [esi-4], eax
loop .c2
jmp .ok
 
.lzma_unpack:
 
.pb = 2 ; pos state bits
.lp = 0 ; literal pos state bits
.lc = 3 ; literal context bits
.posStateMask = ((1 shl .pb)-1)
.literalPosMask = ((1 shl .lp)-1)
 
.kNumPosBitsMax = 4
.kNumPosStatesMax = (1 shl .kNumPosBitsMax)
 
.kLenNumLowBits = 3
.kLenNumLowSymbols = (1 shl .kLenNumLowBits)
.kLenNumMidBits = 3
.kLenNumMidSymbols = (1 shl .kLenNumMidBits)
.kLenNumHighBits = 8
.kLenNumHighSymbols = (1 shl .kLenNumHighBits)
 
.LenChoice = 0
.LenChoice2 = 1
.LenLow = 2
.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols)
 
.kNumStates = 12
.kNumLitStates = 7
.kStartPosModelIndex = 4
.kEndPosModelIndex = 14
.kNumFullDistances = (1 shl (.kEndPosModelIndex/2))
.kNumPosSlotBits = 6
.kNumLenToPosStates = 4
.kNumAlignBits = 4
.kAlignTableSize = (1 shl .kNumAlignBits)
.kMatchMinLen = 2
 
.IsMatch = 0
.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax))
.IsRepG0 = (.IsRep + .kNumStates)
.IsRepG1 = (.IsRepG0 + .kNumStates)
.IsRepG2 = (.IsRepG1 + .kNumStates)
.IsRep0Long = (.IsRepG2 + .kNumStates)
.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
.Lencoder = (.Align_ + .kAlignTableSize)
.RepLencoder = (.Lencoder + .kNumLenProbs)
.Literal = (.RepLencoder + .kNumLenProbs)
 
.LZMA_BASE_SIZE = 1846 ; must be ==Literal
.LZMA_LIT_SIZE = 768
 
.kNumTopBits = 24
.kTopValue = (1 shl .kNumTopBits)
 
.kNumBitModelTotalBits = 11
.kBitModelTotal = (1 shl .kNumBitModelTotalBits)
.kNumMoveBits = 5
 
push edi
; int state=0;
xor ebx, ebx
mov [.previousByte], bl
; unsigned rep0=1,rep1=1,rep2=1,rep3=1;
mov eax, 1
mov edi, .rep0
stosd
stosd
stosd
stosd
; int len=0;
; result=0;
mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp))
mov eax, .kBitModelTotal/2
mov edi, .p
rep stosd
; RangeDecoderInit
; rd->ExtraBytes = 0
; rd->Buffer = stream
; rd->BufferLim = stream+bufferSize
; rd->Range = 0xFFFFFFFF
pop edi
mov ebp, [esi-8] ; dest_length
add ebp, edi ; ebp = destination limit
lodsd
; rd->code_ = eax
mov [.code_], eax
or [.range], -1
.main_loop:
cmp edi, ebp
jae .main_loop_done
mov edx, edi
and edx, .posStateMask
mov eax, ebx
shl eax, .kNumPosBitsMax+2
lea eax, [.p + .IsMatch*4 + eax + edx*4]
call .RangeDecoderBitDecode
jc .1
movzx eax, [.previousByte]
if .literalPosMask
mov ah, dl
and ah, .literalPosMask
end if
shr eax, 8-.lc
imul eax, .LZMA_LIT_SIZE*4
add eax, .p+.Literal*4
cmp ebx, .kNumLitStates
jb .literal
xor edx, edx
sub edx, [.rep0]
mov dl, [edi + edx]
call .LzmaLiteralDecodeMatch
jmp @f
.literal:
call .LzmaLiteralDecode
@@:
mov [.previousByte], al
stosb
mov al, bl
cmp bl, 4
jb @f
mov al, 3
cmp bl, 10
jb @f
mov al, 6
@@: sub bl, al
jmp .main_loop
.1:
lea eax, [.p + .IsRep*4 + ebx*4]
call .RangeDecoderBitDecode
jnc .10
lea eax, [.p + .IsRepG0*4 + ebx*4]
call .RangeDecoderBitDecode
jc .111
mov eax, ebx
shl eax, .kNumPosBitsMax+2
lea eax, [.p + .IsRep0Long*4 + eax + edx*4]
call .RangeDecoderBitDecode
jc .1101
cmp bl, 7
setae bl
lea ebx, [9 + ebx + ebx]
xor edx, edx
sub edx, [.rep0]
mov al, [edi + edx]
stosb
mov [.previousByte], al
jmp .main_loop
.111:
lea eax, [.p + .IsRepG1*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [.rep1]
jnc .l3
.l1:
lea eax, [.p + .IsRepG2*4 + ebx*4]
call .RangeDecoderBitDecode
mov eax, [.rep2]
jnc .l2
xchg [.rep3], eax
.l2:
push [.rep1]
pop [.rep2]
.l3:
xchg eax, [.rep0]
mov [.rep1], eax
.1101:
mov eax, .p + .RepLencoder*4
call .LzmaLenDecode
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 8
jmp .repmovsb
.10:
mov eax, [.rep0]
xchg eax, [.rep1]
xchg eax, [.rep2]
xchg eax, [.rep3]
cmp bl, 7
setc bl
adc bl, bl
xor bl, 3
add bl, 7
mov eax, .p + .Lencoder*4
call .LzmaLenDecode
mov eax, .kNumLenToPosStates-1
cmp eax, ecx
jb @f
mov eax, ecx
@@:
push ecx
mov ecx, .kNumPosSlotBits
shl eax, cl
shl eax, 2
add eax, .p+.PosSlot*4
call .RangeDecoderBitTreeDecode
mov [.rep0], ecx
cmp ecx, .kStartPosModelIndex
jb .l6
push ecx
mov eax, ecx
and eax, 1
shr ecx, 1
or eax, 2
dec ecx
shl eax, cl
mov [.rep0], eax
pop edx
cmp edx, .kEndPosModelIndex
jae .l5
sub eax, edx
shl eax, 2
add eax, .p + (.SpecPos - 1)*4
call .RangeDecoderReverseBitTreeDecode
add [.rep0], ecx
jmp .l6
.l5:
sub ecx, .kNumAlignBits
call .RangeDecoderDecodeDirectBits
mov ecx, .kNumAlignBits
shl eax, cl
add [.rep0], eax
mov eax, .p+.Align_*4
call .RangeDecoderReverseBitTreeDecode
add [.rep0], ecx
.l6:
pop ecx
inc [.rep0]
jz .main_loop_done
.repmovsb:
add ecx, .kMatchMinLen
push esi
mov esi, edi
sub esi, [.rep0]
rep movsb
pop esi
mov al, [edi-1]
mov [.previousByte], al
jmp .main_loop
.main_loop_done:
ret
 
.RangeDecoderBitDecode:
; in: eax->prob
; out: CF=bit; destroys eax
push edx
mov edx, [.range]
shr edx, .kNumBitModelTotalBits
imul edx, [eax]
cmp [.code_], edx
jae .ae
mov [.range], edx
mov edx, .kBitModelTotal
sub edx, [eax]
shr edx, .kNumMoveBits
add [eax], edx
clc
.n:
lahf
cmp [.range], .kTopValue
jae @f
shl [.range], 8
shl [.code_], 8
lodsb
mov byte [.code_], al
@@:
sahf
pop edx
ret
.ae:
sub [.range], edx
sub [.code_], edx
mov edx, [eax]
shr edx, .kNumMoveBits
sub [eax], edx
stc
jmp .n
 
.RangeDecoderDecodeDirectBits:
; in: ecx=numTotalBits
; out: eax=result; destroys edx
xor eax, eax
.l:
shr [.range], 1
shl eax, 1
mov edx, [.code_]
sub edx, [.range]
jb @f
mov [.code_], edx
or eax, 1
@@:
cmp [.range], .kTopValue
jae @f
shl [.range], 8
shl [.code_], 8
push eax
lodsb
mov byte [.code_], al
pop eax
@@:
loop .l
ret
 
.LzmaLiteralDecode:
; in: eax->probs
; out: al=byte; destroys edx
push ecx
mov ecx, 1
@@:
push eax
lea eax, [eax+ecx*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jnc @b
.LzmaLiteralDecode.ret:
mov al, cl
pop ecx
ret
.LzmaLiteralDecodeMatch:
; in: eax->probs, dl=matchByte
; out: al=byte; destroys edx
push ecx
mov ecx, 1
.LzmaLiteralDecodeMatch.1:
add dl, dl
setc ch
push eax
lea eax, [eax+ecx*4+0x100*4]
call .RangeDecoderBitDecode
pop eax
adc cl, cl
jc .LzmaLiteralDecode.ret
xor ch, cl
test ch, 1
mov ch, 0
jnz @b
jmp .LzmaLiteralDecodeMatch.1
 
.LzmaLenDecode:
; in: eax->prob, edx=posState
; out: ecx=len
push eax
add eax, .LenChoice*4
call .RangeDecoderBitDecode
pop eax
jnc .0
push eax
add eax, .LenChoice2*4
call .RangeDecoderBitDecode
pop eax
jc @f
mov ecx, .kLenNumMidBits
shl edx, cl
lea eax, [eax + .LenMid*4 + edx*4]
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols
ret
@@:
add eax, .LenHigh*4
mov ecx, .kLenNumHighBits
call .RangeDecoderBitTreeDecode
add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
ret
.0:
mov ecx, .kLenNumLowBits
shl edx, cl
lea eax, [eax + .LenLow*4 + edx*4]
.RangeDecoderBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx
mov edx, 1
mov ebx, edx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
pop eax
adc dl, dl
add bl, bl
loop @b
sub dl, bl
pop ebx
mov ecx, edx
ret
.RangeDecoderReverseBitTreeDecode:
; in: eax->probs,ecx=numLevels
; out: ecx=length; destroys edx
push ebx ecx
mov edx, 1
xor ebx, ebx
@@:
push eax
lea eax, [eax+edx*4]
call .RangeDecoderBitDecode
lahf
adc edx, edx
sahf
rcr ebx, 1
pop eax
loop @b
pop ecx
rol ebx, cl
mov ecx, ebx
pop ebx
ret
/programs/emulator/KlbrInWin
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property