forked from KolibriOS/kolibrios
6cfca28b78
git-svn-id: svn://kolibrios.org@2292 a494cfbc-eb01-0410-851d-a64ba20cac60
7835 lines
146 KiB
Plaintext
7835 lines
146 KiB
Plaintext
; 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
|