From 6cfca28b784ebd76a937dcc171bfd1974494d4ba Mon Sep 17 00:00:00 2001 From: "Kirill Lipatov (Leency)" Date: Sat, 15 Oct 2011 10:20:45 +0000 Subject: [PATCH] KlbrInWin src uploaded git-svn-id: svn://kolibrios.org@2292 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/emulator/KlbrInWin/I40EMUL.INC | 7834 +++++++++++++++++ programs/emulator/KlbrInWin/KlbrInWin.asm | 6359 +++++++++++++ programs/emulator/KlbrInWin/KlbrInWin.ico | Bin 0 -> 19790 bytes programs/emulator/KlbrInWin/config.RES | Bin 0 -> 2872 bytes programs/emulator/KlbrInWin/config.asm | 1509 ++++ programs/emulator/KlbrInWin/config.ini | 80 + .../emulator/KlbrInWin/config_resource.inc | 21 + programs/emulator/KlbrInWin/kiw0.asm | 238 + programs/emulator/KlbrInWin/unpacker.inc | 492 ++ 9 files changed, 16533 insertions(+) create mode 100644 programs/emulator/KlbrInWin/I40EMUL.INC create mode 100644 programs/emulator/KlbrInWin/KlbrInWin.asm create mode 100644 programs/emulator/KlbrInWin/KlbrInWin.ico create mode 100644 programs/emulator/KlbrInWin/config.RES create mode 100644 programs/emulator/KlbrInWin/config.asm create mode 100644 programs/emulator/KlbrInWin/config.ini create mode 100644 programs/emulator/KlbrInWin/config_resource.inc create mode 100644 programs/emulator/KlbrInWin/kiw0.asm create mode 100644 programs/emulator/KlbrInWin/unpacker.inc diff --git a/programs/emulator/KlbrInWin/I40EMUL.INC b/programs/emulator/KlbrInWin/I40EMUL.INC new file mode 100644 index 0000000000..430bd55e8c --- /dev/null +++ b/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 flag + mov [edi+4+ecx*2], esi ; set DR + 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 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 diff --git a/programs/emulator/KlbrInWin/KlbrInWin.asm b/programs/emulator/KlbrInWin/KlbrInWin.asm new file mode 100644 index 0000000000..9af5a74f79 --- /dev/null +++ b/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 ; +@@: + 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\) +; 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?',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 ? diff --git a/programs/emulator/KlbrInWin/KlbrInWin.ico b/programs/emulator/KlbrInWin/KlbrInWin.ico new file mode 100644 index 0000000000000000000000000000000000000000..97ab395705b9926b54e1eccc076347ce217ae3ea GIT binary patch literal 19790 zcmeHvcYIY3UF(5PJ_{v|u{b6OFea^o7thLKp zYk${12r)<8DIR#>0pz!fC*}yTPY9F+%JanLxk3cup1!<5Y`$HHJMI)>!2*5#o}US^ z;~p;S>qpKLV%2?y@&XZwc67fK;xB*U=O{le#IZjK@dUpEgrDI)8by*xe}DK#x{p7y z=?fXxL?Jsn8<|XyK*ArIzM$y>>2L5;ec~7LTRCTe@NW*w&E+|Bq08PagBSN&zUasHM2l1LX3hmAfF&1`alnXT0z$z)6*pKR*<+K z^%sDY`rqEzPv~4u7>`?}__vpegcWay#CP8mN$6kg?Pnrm-De{6>n}vchA+kG zjcdf|O<#<i1%yU#}Bco7aiV%^N|RMCNzjh^%ejimdIMMb5U3B75fsk+c09k-dG3 z$lkG4QY9Ew6b#vrosX-~`Y46k z*F`i1%0=T5XVDyl`@Zg?&d*)c2Y8CcKyQ$bPzU%6b&$Vk2(}YVp?0D%*j3bpxQoV6 zH_;N|E}BEUaNk>KLIXt8QD4y<;U}77gG76blW2=kiq05k(HZ9~+G0ILTXcYEjSdu@ z@d2VMQ6;)T9f|&;JK0}cNC_1ErvgQLdJ9$*}Wrm8*6H%f& zJr)!vdQQiQ-qZ1-`%I$fIh81S&m@bBIT4~aCteH`B;Yzp^yQ|B%Y~_8pfp2VI)7U9 z7iEfpl1wpJkSK-Qxodvh%423Vz@S6T&XP*SJmgm zHFdEVt}7BF^~GYe5#_ovalNTT3^!GX@wN(ay|r3gZ_|kD?P_togLADI>#P%FU3Fqy zq6RU3p;1IHeM!70e)BWg5hxiX&Y^-td8^E#WL}I|`5T!oXysf>4Cdr z1Z{ms$d*6Mt0bFmPU3g7>+rMKYx&~2@7@vjas?!={Q3)P%6O??rZsPG+__`Vnv%;s zYgTOAu>0*DtGDcU`pGRDcXHL4wCt`J{k7S{b9y#BJcoK!7QejD%D~@DJvrAy9oDOy z7NQPc|0j6m{GmO|rJSE}c`xeQf|lUj8GrCjQDrXo8A$U{L}4e4LtCVU-<0H zHJ`uBS5o@ofVG2-`Ie8D>x)}$-2=md4$F6cw2W_jtFT(+mY5V3>|*@k+d{m#@x9G| z{OZrK36V$azF8^6rWKDZ_}2w%{~Qq>;JW97)CJ|91;5e7rr(R=*{F^KVc6 z$9)goci+GK`-_&QpS~|%`O|H;-!bp*yYISl?mbIay(3=VyW{C!{_5us&cF9($#eem z4e`u2ll@+vzj)x`-@f$h6Te?9gwakXU%yWtef%$fc=@>{;OEKpjv=9;_V!1=+y0uw z@PDmSM#sg+96R``RK%aZe(kI}wBdO}adysnbP!Xf^)?JT22;j_3b!JDo{f5~sDGXH zE!}L77T}lQ@OCNtyMHR>HuIp9K7($^gg)qkUbqY$(FENRUgPTcY>kT}-gfI$<7D>? zbV(D|v<~Z*uuchUm$1GGx`LpCrl7A9)NanOs5hn>7rQ0UCBsm6V^4_sUxg+f{q~QAc77g=-5fMO7YhkSNnO; zjeXF;1iL}78w9%{<J(&el&sS589T5p*NLCK2ot z!G;lR8^K->bR$7$5p)+pml1R)L5CCUfVR@{&|9!!I@lwF3AUV|4+(aiU@sxR;u6j5cD)bUlZ&#!HyGbH^Dv=>?6UB5^OKQF6&@JKjc|dW?}La?BzJ@4#5@> zbUQ(}6YL$qwiE0&!5$NAIKjT69}W=gZC#b4wO%Qs4cP62uy;Dx6oSqt=zNJ_Z-@!D zfMDkcHjZGEuU0E;pPW5|OD#-(2K#>qc5@u|2lGZvum=QtK(G%4yFsvT1e<=bT46J@ z=1ULkV^uDt(gS~Jsq1?Nf!>sj8I;g>h&r3X#s zlv$e2$Jj2eR#?7K?P&F1l@69Ovd*r3gO0%i+3bfmUGp=8u35*r20H2q+*<%L0vY^X z$vB~WbCU55{E2}5;beZ5^$83jXm6!(q4FI#f8`6$ol3qyM3k=bSA z`Nof#&L1^AL_UB1V>i^tjT@d@O66I<7@9wy^hN0}9?ySlbd;|_##}@NLQ&#(6gGMO z(ERz2pp5PyOO%K392Ev3KNt0hJLpbRLkZ8h%V(E)1V$|l6-K##XI0?tMY?~w!l*PH zGdE_6sKG7hpGs}D-U-t-hjc<%UKipqJh{JBPj_YuahnWN&_LqHrJ4HK_sr9wd7kUvC!KyO_3#BD2jRZ|^S9UhFe=i4rD@y&~JpOypUZi4xg1 z&|Xm_!?mp$atl!*-vu%g70yih{YQ<;Ow_1w?P(#jxGu4ki4td9Q6!h6t_=0C9|2XM zT%(eq9+R!mGWp7c7JHBi6+Z)Euc77K7kdp~{9dIJ6~0WKD62%x5nt>ZY(--vC=C0J zFlSt&ZmIb84u;@RH{B#)ZMWT#4>DWtTM~Z%? zqF7v`oR=v2^HNbx72Ua~a4%i-6s3#)l5{bM{lj2MD)Mx3tpeqW)5uRtdx-AB9MNBq zjeFVRS`G4=JaJ8%hjNh^)E42IsYG0BWa9k;Qw>Nfu6KfZ8bPh%dVeeC&a*$*w>+`^ z(K$=t_rH0+n*}c?E(@_pEZD+1w*K&&&E_nUa<}{3Eau&@NNk_$X2CxB6R5+)^?2XH zzu~&PZ{hofeG6aneJj*k=lJNH+546S#*faKi~Iar-nVSV^Ld#6^Ux~i(r@2bB=PXW zeZwOBa*>$FJfe;vExeCG3L!p5d!K@q;Q6mEt1NbbZ(i@rf6#9B_VvFB!!^reggg8` zra#~}Pk?xDVWC(qRKHmX|CfmCwvH^F;j70hU+^A@f6oS&>o6~y(FTfo2nG295Vy;G ziCOFW0Th{74{*K!#P|;z0ihmUD#{Z>X@?Xv3DRJB>|DjE#40-GUm6Z)jri@=aTJ?w8rx+1c4zn(W-V z@x}^^mw&y}SZ3#-a6)plLyb)p7I^z3{X4&&Zs5tc-um4`zxj_vFTe8Y+O@BKr$Cb1+nA$)CC@Vl zPkpd``=%#!+uDc$1|J(Q9;OFA6um9WKbLZYU@5Xe; zyysTGv5=oX{`%@wf4t|8+wQnyrp}#r+;PX;xevdy@EJUR?6sAvRh`Zz5n^AFanP+U5N@` zn3|d$_)KyD9@=cW?VUgV_P%@Wl{{K~1KanRAwBtvN6-gGn>Ky;?|*#axu^9W@9$rG zcjYQmb8`y|tBt=~fb`_sE8hO?zy9lA@pewX`qR>PKi+3;ZEa&?zV4M*UfpDFV{Nwb z^@Y#>MgLs<`iZ6Q?y~13ms?xg%k8bLH@~*FgE@vGlI_vUVeQmIn9y2_2;eC~xCoOQ18>)$`|#@EI&neo@l zo_l(B+x$>Uzy6os{|V{wKm6dgh8nlXS+B6azu)UBN2$C#PDK0%(RlRoYtKTkT}GPV4RN2TY=>&d+n8&fk;j z{5*gsxD9B$R8?wEr62av>uOyc4e*yxd$`WDVQA|gavVjf-4Sci7`{ zW3Uf3g&wBn@BnHFKZ5)SHHG*S->*LcK73WA_H@Ob()BX14F&Rt4DD!r^%#Sp{A2PO zXNR?QzHWU@q5jko89?m`p_82{5#wEH(UYCWqo+DjqjjB05xVx+kg1l4z{#c%pYeKs z_eqVn3)Ol6+i-L4gZyiM%)7WwjkEoX+`xW<>W_E=YYCu^l<|T*OeZlYfn6;Yl%3bYYg(9()zegsNEHeZIH&zCD_0Nu4mq1 zxOa12>*^5K0Bof_=_vNRQBxOlQs`1q1`U*F>jo?H=}OHxx&j>MYHcwMRu$6a(zDcG zc#1A&rP77t(Ym(S5R8it<_2&kclnfB=?I+1IqBy2+^Ssd>JZo%>P;PKM<=?^#Of{= zrPCnZdsTBzceTEZMw%*Vw7G^xTWTd5X|ASg^%W8?1EsmtpPxb9r{Z<(31PbCP+#Uj zr*?OoP%Gu&!6ook@6@_EOY5XYZvR<*fIGD(AD!sQik<2&OrxRlEL~e#99=9p0~|pE z3_(j{9d$I`+e~A?w8lE?C2Wd$x(5EPpnonGW>C-RL~2hA)d3F!4=%vl>?dkf=m&S# z&zJ|S7yUa`j?&t$bg+F`J4)JP;dCMQG~Nds z>_P)|<(!dtU_KaI8v|e0TdIMXl+sXDzBFEp;kCyF>zaZ+bsBGH;AD1;w_Q?uC?94X zfF;hU3sg$FquRy6t|i6~7)!)NTXHb91M6x7cG#F0P1Qlb>Y|R3CNhG0in6I8Dv~Z1 z=h6u9yq>}w8t-YOaqxA$oyVjS7!9z(3e1VTH0nMcNo`Swso}7SaWeFQ1M^@n^?|#S zq#M-!@_Dshj{RrNcGAgjH%{i5?$PDT%ys7+Y^g-$O4Ubv(Feg)7a1P9g@b0m;YT$#FG}3^%35@XadCbX7V3A27I$(u5t&bD>z#eNt(XW=<&to1q zLC1d980Jn5VeV7;hxSdK+P0OlO@QIqSyP$Hi7GtZsLJ1mYJnqaj|Pz@?5Onaj`Sp& zx}c`s+Uxm#1n~n2YW%tMqRd z0yva+OSC6l%sV!Ixgb{8o)SQ%E;f{JVMc|rgH)ohr&3o1mAko874zcdPF3EXRPL^# zmbfsQY%8aUX5eJ?g*2kcqhWO}aJL+~QhJgu;r%`7$EZE#Ff|3MbXqU@xY`Y4;O^qd z@28&Pd(@uxnQaN4)RPf3aq)Bru)7$#TAl{HIDm42z2+U*N9SY~!0xQ*oShZ0P#Ze$ zpr>=zmQ?HKP9xP>G*O>N*EP9xwemDwEj>X)#i?{TH-Rpm45y9+=<5(SV0MlZ8h7A_ zN<{&`|05w@tUs)%ZB6t5P8~3HIVW5;`rya0KD*&fQ-wVjF%nNqE{f`)PvX-os$5&RDoCeWpvD7ttmggO&|wT7v5^?uMt z?sf#**2eEwJKBC;YELevHmN{*}0iYY)z>n&X=whL5{pA>OB!aU5UQbdQ6FR z;5e!Eu*DisT&r>OxU+P>$?6(6%g&U~-=~0QpP39_@&d)a`5GlGf0Gj4eVdX$0Okw) z_5|=(#$ZnX!(|+oapjCJS4+g#621$JmvQFg_ur%Bk5)1^OI;Y(%fPfd<2J*OZ%llRd;Bbo@oCgcM*X-qUZuo$-bAdxih7UxP-~cruHN5v zir-)3?$FBpKR{V`Rm#oJv_v>zo_J3HTc8>@GxX(06#eQFigOTfWdW9=01-dtv^$JG<-OF2s4W-5+bw zN3Ai6sg8Kpsm?f8JqCZ$mj+Jz(?B-HFUgNu!co z+RrI-D`E`0w_wh^PhpGxN`X&5MMoDtL&sivfg)deaq7%BUruSgod~|o2Zr~noe$2f zax(92I%ZGpu}+hn@vgcHpze4Vx_H8m2F@kY)sj@YR(71m)Tf}+gDLAf#8gq@t09cjC`Ua)*15^eSr60%8RDK66liiX>{dW8eKhq9PyWQDs!@>vwL<@KGuIO z^Z@IGT<8b&VI{RC1;K`gAjaeaUB3^y&YU#fmQ;7dW}-%ELsbfU2??!K*xXinaIeHi z(O%;RD;@TCH-y^Yck)T_pu3RZrW-t;N<)>WVAm1%sW>CiNNoDA(cuop-b$O|Susao7Zqb$58|x|*#*=CT+4nj-Bc+oBz(I^&gyxn-~)fcP8qD)MWr+qLk)pl=(ZgQ>~~w!p`O zY65+zIX)D2FPlai^647t43(zqF2uQD928Rx0k)GG4@at0$f0s!bCmL1?hVQg?)6mr z9-^iw`-#>_yQx0JxkegGbl0?ny5WX%u&p52w~^)&_#0(-PZ9Xam+oJO4Z4QsDC@3h zigZ0$5!7(hda5oEYtGw_YFr#7o5Sz_d#Ti7Z)mOeA!>}Uo@!52O(ojYNl{xU8ohR#qtlsk%npRu5@Je-G3iFzYIUO>b-K~cdfiZM zKKS;Ws6T?a-~}7vWao2p`#+{!Y-0RLmHa@b*4u)bqn+qdaT<+u)Q*k!cTP@T>YAFk z47$`gHQv`gHP+WQIow<|cCjFZnt9#%T4CPXbyhjreDY)7^|$I2@7{4=iNzj^N=LI^ zjVI=2sDipu1L5PszE00H1>Kc`KM~%|Fqt?y5y4uD3bfx1#JhNF< zVPiG3AFg(`ooU0+?mv?wE_!?M?%gx(@o$43{$gICvB|=Mz56~XGBy9Cc;BIgNlU|L z{7J4;W^V(XYV(7AJ3pJ9Xvq@NW#48wAw&z~6#W2M4LC)x5Oa-i424NH3!@OrilNSG0!YLRJS_d-VsItdV`2XpaJy2mQ`$d)9dV^Z2 zP-;9}Q?;J%XSKfWYOSw_TDta7rfS@jO0}zEL$%!Y7q@KW|M+Hwt<@i(2b?vYuJsK8 zzEe#>@Wqb;HwpCBQ;-jG_&Z0uss6A#{9a%wz;!gf9`Mza^%{34XT;h6@PEv<0N)E? zE7R%^drdWm`Qz*g@E!^OVeBUW{`6sq7zb(&^~3&#iDmMH94hEQH`sk8bTG)nZA#;= zN~>{}FZ|z@qr%SWLG*Ww#5b^`Ch*o8c^G@JAnJhM(4G*E{Rs9%iP)DhC4l0?sU7EP zT7fe)1Jh~>f*e7R!$(DR%)ckjnRvJ$S7HC6iotkDKE(gDER}XvpJ?1&hMGgrmtlwD z3k8Dbqu9S41GW=|b3`~#l#u|8B|*YCx=-UeBc8fX#?ghe82G7?k}Pe}Y!5JAIB(Pt z-~kK-=Y_mL9tz+9z@)rXL%;$4Tej(D*{kF>o;-h>La^70Izk=E;5#(}yn*L4*oS7P zNSH)_0sPZK?2QY~=<~dj)PME_^<}3qmL|!<=a+b#+M)t6x3E@%ur_97a3qZqa`1S# zyL#Qs$3I)Hv^jWNwWDol{SojUb_D&0K2HVSla9S>W(xJ?VIK|r?eh84@P)I1hn=Ot zO5h8?d4_;D4OZlV&caX6hCIL=a!*LV<8kUrjF85!_1N@Sz&~b;lzl-BFfk4A4ULB~ z0^|OZ?Id^)X$bJ5X5dHdNx{^W9*J{e@zj@}BJn*?at8e70yiw6A@w=sl9L~?_$AibOJ0p%dk|Ll3zL!Dk!}EtRT6?_=Zmu(X!XG0`wWH0u zYT$a!*lToRzteRJyyxk8A1K3qr6wPk;RzaREQfy#zTrcUw!vp@XS@s;W=B16JAKY& zzR&WEGyzA%Z+JY0stPcMXQ)35YXfV(BRK+Rucl>S9qS{Ve*>NY8QhhVYNgYAKZbYc z$oU#qML*6OVy_lN7r5W^fY+ek2TC#|{H`18vG%Y(wWcM3pGpaP9q$7E$vgvh9q(-d z_6YowsTp_cih#JNP zSq3jvKkW8D)UDO7@~{T{p7)v;fN%9=#Xz56z89aQp^7Z*hl;54R5JF0LBK7KQA=tf z^_S(*-tOF&+z)Lv^{qoq2 z+#^P%v_DvX6m@+Rl=9{0l>W^|$^`z(IB|icIThJjQK_>dl>w`kaC09|s%Gpw(4RC% zac(#qazuqw6VE5$`Sr)bXsD);CVO~Y*Ge?j0lwR-LBQ1+Q*Y+DPcex`>8S$V4vfXmi)s;zPzN1G8~|sBA&WMMZ3f2yYH6~g zk|uD*c)YEW#-(^bIe0I{+&PE-2WFxHF2i;Z{0|ht-^hvwHVd3?R7%FmlB5lhg99-)brQkrNjr*YsoV@)8O zy&XeL;d)&@jRH>^uK7N$FbFK7KPL`z=oowqoX5rbYYtYyM*{ZXf%t+nhg6f;E6qf` zs}xr6*Lf-6OZvg42f#-Nq5kX$x{P?k(D?+qQl1JsA3!;KjHzJ%KFDB2#kMj@7LGTR z$RQ76A!W`ilOvULOoYb>V^!+pNZJ4&@O+LY8;fX6n2b?z?_5gTc4EPUn1Lo@tf7?Mn2JlyblYVFzgG#w0=KnP2 zP-Y0)feiUEGo0D4=m|E?t*+&!my6)8IW_imO~fT!qhNUxLl)%Lv07z`i2Z7x=In zH3oox;9VLw%ps0JD-{Q3@gL9>>O$?QKGciz-4{;>(k12}XRR;iM@cg9SX=`C{n;^y zZ{U14;x1=_tL7ozlFxA$Ug!HU$FNqI3U8tUJkQ;WGv&}FjiFvNQJY0$z)r8090zur zN>|UN0LM+Df&4hSjMz*cVlx+jCmHx}!g>07A35fbt=_+LcM34@U*#x^ZH{om_#@T> zY^^O;MLns0@ax0TA6N%@m`BC&G+dSp9Qqiray!IjHd5BsZz*TT7SLA2XTHN3{B3$N z-bT5=tZ%05orwRTeiq_76^>SjABEC*bq0-KeqK8lFTHCJykE*XhJHK>I}m_1?1M82 zD%fN2?+gCj!9VLF50_X2|CJ7h3W_X^DI8dQ1mY42IOCs+^Y|w>eM)C{ZlofM9aNz( zqw})8=+|AyO(=iQR(y-_6`f&1jOom`uou&miTqY%czznPpW3*NG7uL?|9mx7xyk5C zek@%rjHiLK%>Pm9OAn&%6!-ygUa$j7iT?&)2dn`b{Qy^eqSu@u)TIk=k!bHiyM3%<+oK`O$^71mcKy>Z@(_ZtvG&_!ttz+-jgWx{0Pqqb4(KGzpn)@{dIl%W*BBl&GB59Q#W_o`QJdj6BSvAqHv4`5t7I_~p9%+qd74+Ay@oZ8OE8 zzi=)bvE+@2HQ}sHm-yt;(ANP9A^f$K_B9K zCe|y^KN;)S{7vFICpe}Kd5=Txr1zHVv0NfHlEuyB2+4=gV{7 zv1m5$d|hg8vPa`#Nm8seiq|r}*Mbb)2^a%h_hKAaj=tlbG;ro9zQKy8tHt=1>OA6b zB}p_|jg2p@4}KW-_GLP0KPS(Do3k5H}hX+vG37xJJX5APzP#Z{$mwVtoA|z z;dXa7HoC4@pc-i zNJGpuorX(O;Wxu~C{3n*#KilL!w19oYdrT;(ZMa0x#e?=(?`;`ZW-&oGw5OM$H`!J4=>`#N9^&|~xJIwfFIL#%n9ch z!ejYqAiDI78T7&*qkAcG6_!afWYqtEf3;uZL# zSMXkb_i&k>MytRF{K=*$KlpPdRA_;7Mz^5+1Ex4{1Ap$I85P;{-qezcB99He=~ zqv)=*mEE8-4Sjxd zUTU^yX}R6LiN>Qgl0IS?x^P~g1MA>&Ir>~vD4jLn^9I9pxCV{X6#%o<({|vowX-Q9}s$=f3x4U*Cyst01HTJWfFh72Kwxnxgm7=x?Y0>}XD1{esRZICcr#&RUWIar)|VB#~6OosAk3(iC| zqy99F)Zv?FEigpQd5mioFe?RcbbCGTd`1D-8{+2waL)fN{_)N2Z6zj<0pm~?VvDh` zqvm6_*dzO)zrhD^z)^g+eI1zW4FsI$`Ynj-&Jbjg&UMrSk5(699eYFXq3?q+Z;r5^ z;3V;0X=U+~;}-_GcrIZ*Kwm(H5XcY)8BQLNu<)@iobzQ&P$FQ=dYN$9tH#+^Q#($GRI(2j__)?G8ajavY_!Q;~V%wpP&@&E_52#k!Pt>^D`Bd5-`cXRazatNPy+4;6*d0`1 zV>+Ssv_c#da|&ytHCzr^jsR~-mh{P0tdVORZvnn`sUVp;@vJ?Hb-N?gVSmNGuv%$5 zQKPa8s<5;E^H1Rk=WOozDZk_2K#oU2d*FK)RydeVYE*|v?In|JPQAYk;&HIChpng{ z=Oyb8^O+}n+YcYOT49BFkZobLlkFaS$8k$v?5FbdQ-8;MAo#E=%B@WIRM?vP0uzV? zWmh;H%&u}c6j|vY^R1Ly?SU>|QE6xSzdlEPsvQ5q~X7=?|3*WY*gSUWbruQ|QvJKuMH z-}?{|S+GnqxvE$Tz#`%rEcL@!$5+slUFWM1MD3I{iD=QMz&^E`dxlZWz@jJ`1+I z@+mg$et)1fWX3xJK2M;%IMtbf&L{FB4ZOypw48PM4&ObNM>0pI$$10=8kt86&K|-_=h2%~!^tqMwUkqT zm!FOvXrm+F?x7Ps@6qvJ_tEKtofHippmTjc(b<3gpbN(i(S_JiN(`K!%R}esviYwB zK|oj2#YR=tcV*5$)2zZOwCdDBTnODR3_W#_&~?Kw99UvMYrJl_9bg@f1;#?K3B&L} zWY-OMvmN{ZSX~HJ;DURmX+l*Os%q7y=(uDiG!|-Bt5wq&aX^4HAu5E`ie2?t6;#2z zsH`lzqkJ2)6+*WGrBYQV&Qn#5Y=%L&EGDbBT2)o(1qBZ9hOnv{#1*uv$U{EE&>@6n z-5@F=kK1i9f~wh#W~9dFZZ>pC%Y<$$WPZ!`X1mbll?lV)d5y^L^BD7mzD?5&4`;H- z=i6?#-}a@Z+n6Ql@Oun#UtH)f?QCsrr+%VBLsTcU8UC$-_Rfze6!g21v5hmf27{r_ za5xkUIA@^G^k93aD;)0nF%)c^i-gT?@9aF((;MjwcgzQC?tZ5CP+u$>>FwIPn0fQ* zp5AB#-5OaSS#xMPIM6%0lDs+e{O6HK_}w&%ngsm**8M3dKK+FlcZECR#X+L-Geo6u zmsepoQN9-~m|k>al+o|T{eIvuCa=pxGue*mRixd?z_VbP=6I~7*b!A^y(irLd6!kB@>=d5FJm`hg}%W{L8#{LZ0zdX`qxW3+-C zREK{HHIkFo;K$rja6~st-6zQoshw(Y-Y9oY+^i#)l&1d_Qfw#b4XUK^@Rnoq(p;L8 z7N@?7?M@}B!!fYV!xDE1Y}e=L;>oZTPyuz&TIex(=@DumH}q=YrITvmiwl0#W6$2N z!{YOX92{iQR!pTdg-TL58|Wz@G~j+6ZYpF^Ix41OTLJkj#1l)!G7EX(%&vfs9(-3_Wh2`H?-`>?Vw_H4 zaGYEfu7*X{iz{<|EUr~4Ek=wbl#o~(h+|ws%W{k+YqUt#=%mzJpCf0Vg23S#ok{sL zT8+5Jiec?TT9oOrM`gU6fpmZ5Rw^IZ(~#{dV4qE4uST3T(4Qu2P>)W$fmrkM(BEF% z8SYCvx-mJ6>Aubli{qY-JKUS+#)$h9$V>1WxJKNHwB0ho_VE1hTyZyX&8)dD$oZH~ zEz*bcWBSk{eTZMzhqfE?p>k9o+N2K`#`K|0`f%|YK5+fN!yB`c?$6ZUj$Y&Ltw-!N zn9@dMVhO6kT{zl|aX<88ezu_>22-|Xjkw2CFxrdj0V4Od1r{4HX=`NXIPv1~n = number of partitions for /hd, 0 <= i <= 3 +# hd_ = Win32 path for /hd/, 0 <= i <= 3, 1 <= j <= hdn +# must end with '\'; ',readonly' string may follow +# (j is represented in decimal system) +# (if harddisk /hd is used, all partitions /hd/ 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 diff --git a/programs/emulator/KlbrInWin/config_resource.inc b/programs/emulator/KlbrInWin/config_resource.inc new file mode 100644 index 0000000000..77db5b3b3d --- /dev/null +++ b/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 diff --git a/programs/emulator/KlbrInWin/kiw0.asm b/programs/emulator/KlbrInWin/kiw0.asm new file mode 100644 index 0000000000..a5e395a235 --- /dev/null +++ b/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 ? diff --git a/programs/emulator/KlbrInWin/unpacker.inc b/programs/emulator/KlbrInWin/unpacker.inc new file mode 100644 index 0000000000..fdc370697f --- /dev/null +++ b/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