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