; 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 ?