├── README.md ├── k_event.c ├── k_event.h ├── k_file.c ├── k_file.h ├── k_gui.c ├── k_gui.h ├── k_iconv.c ├── k_iconv.h ├── k_ipc.c ├── k_ipc.h ├── k_mem.c ├── k_mem.h ├── k_net.c ├── k_net.h ├── k_proc.c ├── k_proc.h ├── k_syscall.c ├── k_syscall.h ├── kex.project └── main.c /README.md: -------------------------------------------------------------------------------- 1 | # kex 2 | 3 | This project lets you to run [Kolibri OS][1] programs on your Linux host without installing Kolibri OS 4 | 5 | ---------- 6 | How to build 7 | ---- 8 | 9 | Install the build essential environment and LZMA library. 10 | 11 | Ubuntu: 12 | 13 | sudo apt-get install ubuntu build-essential liblzma-dev 14 | 15 | Fedora: 16 | 17 | sudo yum install liblzma-devel 18 | 19 | or 20 | 21 | sudo yum install lzma-sdk457 22 | 23 | Then use your gcc to build `kex` by entering the following command at your terminal window: 24 | 25 | gcc -o kex main.c k_*.c -lX11 -lXrender -lrt -llzma -ldl -D_GNU_SOURCE 26 | 27 | Alternatively, if you have [CodeLite][2] you could simply add the project file into your existing (or new empty) workspace and build it 28 | 29 | ---------- 30 | How to setup 31 | ---- 32 | 33 | Create `~/.kex/` inside your home directory: 34 | 35 | mkdir ~/.kex/ 36 | 37 | Then you should place the following files to `~/.kex/`: 38 | 39 | - ~/.kex/[char.mt][3] 40 | - ~/.kex/[charUni.mt][4] 41 | 42 | If you have `wget` - you could quickly wget them with the following commands: 43 | 44 | wget http://websvn.kolibrios.org/dl.php?repname=Kolibri+OS&path=%2Fkernel%2Ftrunk%2Fgui%2Fchar.mt 45 | wget http://websvn.kolibrios.org/dl.php?repname=Kolibri+OS&path=%2Fkernel%2Ftrunk%2Fgui%2FcharUni.mt 46 | 47 | then 48 | 49 | mv ./char.mt ~/.kex/ 50 | mv ./charUni.mt ~/.kex/ 51 | 52 | The only remaining file you need is 53 | 54 | - ~/.kex/root/RD/1/DEFAULT.SKN 55 | 56 | Create the supporting directory tree: 57 | 58 | mkdir ~/.kex/ 59 | mkdir ~/.kex/root/ 60 | mkdir ~/.kex/root/RD/ 61 | mkdir ~/.kex/root/RD/1/ 62 | 63 | Then you could obtain this DEFAULT.SKN file in the following way: 64 | 65 | 1) download the [latest Kolibri OS floppy image][5] or just wget it: 66 | 67 | wget http://builds.kolibrios.org/eng/latest-img.7z 68 | 69 | 2) extract it with 7zip if you have it installed: 70 | 71 | 7za x latest-img.7z 72 | 73 | 3) mount it to your empty `~/.kex/root/RD/1` directory: 74 | 75 | sudo mount -o loop kolibri.img ~/.kex/root/RD/1 76 | 77 | Alternatively, you could get the latest [kolibri.iso][6] and mount it to `~/.kex/root/CD0/1` directory 78 | 79 | ---------- 80 | How to use 81 | ---- 82 | 83 | Run any KolibriOS program with `kex` ! 84 | 85 | Usage: 86 | 87 | $PATH_TO_KEX/kex kolibriapp args 88 | 89 | Example: 90 | 91 | ~/kex-master/kex ~/.kex/root/RD/1/GAMES/XONIX 92 | 93 | [1]: http://www.kolibrios.org 94 | [2]: http://codelite.org 95 | [3]: http://websvn.kolibrios.org/dl.php?repname=Kolibri+OS&path=%2Fkernel%2Ftrunk%2Fgui%2Fchar.mt 96 | [4]: http://websvn.kolibrios.org/dl.php?repname=Kolibri+OS&path=%2Fkernel%2Ftrunk%2Fgui%2FcharUni.mt 97 | [5]: http://builds.kolibrios.org/eng/latest-img.7z 98 | [6]: http://builds.kolibrios.org/eng/latest-iso.7z 99 | -------------------------------------------------------------------------------- /k_event.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | 4 | #include 5 | #include 6 | 7 | #define MAX_BUTTONS 256 8 | 9 | #define g_mouse_x kernel_mem()->mouse_x 10 | #define g_mouse_y kernel_mem()->mouse_y 11 | #define g_mouse_t kernel_mem()->mouse_dbl_click_timeout 12 | 13 | #define g_modifiers kernel_mem()->keyboard_modifiers 14 | #define g_keys kernel_mem()->keyboard_buffer 15 | #define g_in_pos kernel_mem()->keyboard_in_pos 16 | #define g_out_pos kernel_mem()->keyboard_out_pos 17 | #define g_hotkeys kernel_mem()->hotkey_buffer 18 | #define g_hot_in_pos kernel_mem()->hotkey_in_pos 19 | #define g_layout kernel_mem()->keyboard_layout 20 | #define g_language kernel_mem()->keyboard_language 21 | #define g_country kernel_mem()->keyboard_country 22 | 23 | k_button button_list[MAX_BUTTONS]; 24 | 25 | DWORD k_check_event(k_context* ctx) 26 | { 27 | DWORD bit = ctx->event_pending & ctx->event_mask,m,i; if (bit==0) return 0; 28 | for(m=i=1; i<32; ++i,m<<=1) if((bit&m)!=0) 29 | { 30 | if((K_EVMASK_AUTORESET&m)!=0) ctx->event_pending &= ~m; 31 | return i; 32 | } 33 | return 0; 34 | } 35 | 36 | void k_event_redraw(k_context* ctx) 37 | { 38 | ctx->event_pending |= K_EVMASK_REDRAW; 39 | } 40 | 41 | void k_clear_redraw(k_context* ctx) 42 | { 43 | ctx->event_pending &= ~K_EVMASK_REDRAW; 44 | } 45 | 46 | void k_event_keypress(k_context* ctx, DWORD key) 47 | { 48 | ctx->event_pending |= K_EVMASK_KEY; 49 | g_keys[g_in_pos++] = key; g_in_pos %= MAX_KEYS; 50 | } 51 | 52 | DWORD k_define_hotkey(k_context* ctx, DWORD def) 53 | { 54 | if(ctx->hotkey_count>=MAX_HOTKEYS) return 1; 55 | ctx->hotkey_def[ctx->hotkey_count++] = def; 56 | return 0; 57 | } 58 | 59 | DWORD k_remove_hotkey(k_context* ctx, DWORD def) 60 | { 61 | int i; 62 | for(i=0; ihotkey_count; ++i) if(ctx->hotkey_def[i]==def) 63 | { 64 | if(i<--ctx->hotkey_count) memmove(ctx->hotkey_def, ctx->hotkey_def+1, sizeof(DWORD)*(ctx->hotkey_count-i)); 65 | return 0; 66 | } 67 | return 1; 68 | } 69 | 70 | int k_is_hotkey(DWORD key, DWORD def) 71 | { 72 | static DWORD m1[]={0,1,3,1,2},m2[]={0,2,3,1,2}; 73 | if((key&0xFF)!=(def&0xFF)) return 0; 74 | DWORD i; key>>=8; def>>=8; 75 | for(i=0; i<3; ++i,key>>=2,def>>=4) 76 | { 77 | DWORD m=key&3, z=def&15; if(z>4) z=0; 78 | if(m!=m1[z] && m!=m2[z]) return 0; 79 | } 80 | return 1; 81 | } 82 | 83 | int k_check_hotkey(DWORD scancode) 84 | { 85 | k_context* ctx; int i,is_hot=0; scancode |= (g_modifiers&KMOD_CTRALTSH)<<8; 86 | for(ctx = g_slot; ctxtid) 87 | { 88 | for(i=0; ihotkey_count; ++i) 89 | { 90 | if(k_is_hotkey(scancode, ctx->hotkey_def[i])) 91 | { 92 | is_hot = 1; ctx->event_pending |= K_EVMASK_KEY; 93 | break; 94 | } 95 | } 96 | } 97 | if(is_hot) 98 | { 99 | g_hotkeys[g_hot_in_pos++] = scancode; g_hot_in_pos %= MAX_KEYS; 100 | } 101 | return is_hot; 102 | } 103 | 104 | DWORD k_get_key(k_context* ctx) 105 | { 106 | if(g_hot_in_poshotkey_out_pos) 107 | { 108 | DWORD i,key = g_hotkeys[ctx->hotkey_out_pos++]; ctx->hotkey_out_pos %= MAX_KEYS; 109 | for(i=0; ihotkey_count; ++i) if(k_is_hotkey(key, ctx->hotkey_def[i])) 110 | { 111 | if (g_hot_in_pos != ctx->hotkey_out_pos) ctx->event_pending |= K_EVMASK_KEY; 112 | return (key<<8)|2; 113 | } 114 | } 115 | if (g_in_pos == g_out_pos) return 1; 116 | DWORD key = g_keys[g_out_pos++]; g_out_pos %= MAX_KEYS; 117 | if (g_in_pos != g_out_pos) ctx->event_pending |= K_EVMASK_KEY; 118 | return key; 119 | } 120 | 121 | void k_clear_buttons(k_context* ctx) 122 | { 123 | int i; 124 | for(i=0; imouse_x-1,y=ctx->mouse_y-1; 172 | for(i=0; ibutton_list[i].x 176 | && y>button_list[i].y 177 | && x<=button_list[i].x+button_list[i].w 178 | && y<=button_list[i].y+button_list[i].h 179 | ) return button_list+i; 180 | } 181 | return NULL; 182 | } 183 | 184 | void k_event_mouse(k_context* ctx) 185 | { 186 | DWORD m = ctx->event_mask>>30; 187 | if((m&2)!=0 && ctx->focused==0) return; 188 | if((m&1)!=0 && (ctx->mouse_x<0||ctx->mouse_y<0||ctx->mouse_x>=ctx->window_w||ctx->mouse_y>=ctx->window_h)) return; 189 | ctx->event_pending |= K_EVMASK_MOUSE; 190 | } 191 | 192 | void k_event_mousemove(k_context* ctx, int x, int y) 193 | { 194 | g_mouse_x = x; g_mouse_y = y; 195 | for(ctx = g_slot; ctxtid) 196 | { 197 | ctx->mouse_x = x - ctx->window_x; 198 | ctx->mouse_y = y - ctx->window_y; 199 | k_event_mouse(ctx); 200 | } 201 | } 202 | 203 | void k_event_mousepress(k_context* ctx, DWORD button, int wheel) 204 | { 205 | k_event_mouse(ctx); 206 | ctx->mouse_state |= (button<<8)|button|(wheel!=0?0x8000:0); 207 | ctx->mouse_last_pressed = button&0xFE; 208 | ctx->mouse_wheel_y += wheel; 209 | k_button* b = k_find_button(ctx); 210 | if(b!=NULL) ctx->button_id_pressed = b->id; 211 | int dbl = k_is_dblclick(ctx); 212 | k_time_get(&g_mouse_t); 213 | if(!dbl) k_time_add_ms(&g_mouse_t, kernel_mem()->mouse_dbl_click_delay*10); 214 | } 215 | 216 | void k_event_mouserelease(k_context* ctx, DWORD button) 217 | { 218 | k_event_mouse(ctx); 219 | ctx->mouse_state |= button<<16; 220 | ctx->mouse_state &= ~button; 221 | k_button* b = k_find_button(ctx); 222 | if(b!=NULL && ctx->button_id_pressed == b->id && b->id!=0xFFFF) 223 | { 224 | ctx->event_pending |= K_EVMASK_BUTTON; 225 | ctx->button_id = b->id; 226 | } 227 | ctx->button_id_pressed = 0; 228 | } 229 | 230 | DWORD k_get_mousewheel(k_context* ctx) 231 | { 232 | int y = ctx->mouse_wheel_y; ctx->mouse_wheel_y = 0; 233 | return y; 234 | } 235 | 236 | DWORD k_get_mousepos(k_context* ctx, int* x, int* y) 237 | { 238 | int mx = ctx->mouse_x - ctx->client_x; 239 | int my = ctx->mouse_y - ctx->client_y; 240 | ctx->event_pending &= ~K_EVMASK_MOUSE; 241 | if(x) *x = mx; 242 | if(y) *y = my; 243 | return (mx<<16) + my; 244 | } 245 | 246 | DWORD k_get_mouse(int* x, int* y) 247 | { 248 | if(x) *x = g_mouse_x; 249 | if(y) *y = g_mouse_y; 250 | return (g_mouse_x<<16) + g_mouse_y; 251 | } 252 | 253 | DWORD k_get_mousestate(k_context* ctx) 254 | { 255 | DWORD ret = ctx->mouse_state; 256 | ctx->event_pending &= ~K_EVMASK_MOUSE; 257 | ctx->mouse_state &= 0xFF; 258 | return ret; 259 | } 260 | 261 | int k_is_dblclick(k_context* ctx) 262 | { 263 | k_timespec now; k_time_get(&now); 264 | return k_time_gt(&g_mouse_t, &now); 265 | } 266 | 267 | DWORD k_get_button(k_context* ctx) 268 | { 269 | if((ctx->event_pending&K_EVMASK_BUTTON)==0) return 1; 270 | ctx->event_pending &= ~K_EVMASK_BUTTON; 271 | return (ctx->button_id<<8)|ctx->mouse_last_pressed; 272 | } 273 | 274 | void k_set_keyboard_modifiers(DWORD modifiers, int reset) 275 | { 276 | if(reset) g_modifiers &= ~modifiers; else g_modifiers |= modifiers; 277 | } 278 | 279 | DWORD k_get_keyboard_modifiers() 280 | { 281 | return g_modifiers; 282 | } 283 | 284 | DWORD k_get_keyboard_layout(DWORD id, DWORD data) 285 | { 286 | if(id>0 && id<4) 287 | { 288 | memcpy(user_mem(data), g_layout[id-1], 128); 289 | } 290 | return g_country; 291 | } 292 | 293 | DWORD k_set_keyboard_layout(DWORD id, DWORD data) 294 | { 295 | if(id>0 && id<4) 296 | { 297 | memcpy(g_layout[id-1], user_mem(data), 128); 298 | return 0; 299 | } 300 | else if(id==9) 301 | { 302 | g_country = data; 303 | return 0; 304 | } 305 | return 1; 306 | } 307 | 308 | DWORD k_get_keyboard_lang() 309 | { 310 | return g_language; 311 | } 312 | 313 | DWORD k_set_keyboard_lang(DWORD id) 314 | { 315 | g_language = id; 316 | return 0; 317 | } 318 | 319 | void k_event_ipc(k_context* ctx) 320 | { 321 | ctx->event_pending |= K_EVMASK_IPC; 322 | } 323 | 324 | void k_clear_ipc(k_context* ctx) 325 | { 326 | ctx->event_pending &= ~K_EVMASK_IPC; 327 | } 328 | 329 | void k_event_network(k_context* ctx) 330 | { 331 | ctx->event_pending |= K_EVMASK_NETWORK; 332 | } 333 | 334 | void k_time_get(k_timespec* time) 335 | { 336 | struct timespec ts; 337 | clock_gettime(CLOCK_MONOTONIC, &ts); 338 | time->tv_sec = ts.tv_sec; 339 | time->tv_nsec = ts.tv_nsec; 340 | } 341 | 342 | void k_time_add_ms(k_timespec* time, int ms) 343 | { 344 | ms += time->tv_nsec/1000000; 345 | time->tv_sec += ms/1000; ms %= 1000; 346 | time->tv_nsec = time->tv_nsec%1000000 + ms*1000000; 347 | } 348 | 349 | int k_time_gt(k_timespec* a, k_timespec* b) 350 | { 351 | return a->tv_sec > b->tv_sec || (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec); 352 | } 353 | 354 | DWORD bcd(DWORD n) 355 | { 356 | return n<10 ? n : (bcd(n/10)<<4)|(n%10); 357 | } 358 | 359 | DWORD k_bcd_time() 360 | { 361 | time_t ltime; struct tm* ltm; 362 | ltime = time(NULL); ltm = localtime(<ime); 363 | return (((bcd(ltm->tm_sec)<<8)|bcd(ltm->tm_min))<<8)|bcd(ltm->tm_hour); 364 | } 365 | 366 | DWORD k_bcd_date() 367 | { 368 | time_t ltime; struct tm* ltm; 369 | ltime = time(NULL); ltm = localtime(<ime); 370 | return (((bcd(ltm->tm_mday)<<8)|bcd(ltm->tm_mon+1))<<8)|bcd(ltm->tm_year%100); 371 | } 372 | -------------------------------------------------------------------------------- /k_event.h: -------------------------------------------------------------------------------- 1 | #define K_EVENT_REDRAW 1 2 | #define K_EVENT_KEY 2 3 | #define K_EVENT_BUTTON 3 4 | #define K_EVENT_DESKTOP 5 5 | #define K_EVENT_MOUSE 6 6 | #define K_EVENT_IPC 7 7 | #define K_EVENT_NETWORK 8 8 | #define K_EVENT_DEBUG 9 9 | 10 | #define K_EVMASK_REDRAW 1 11 | #define K_EVMASK_KEY 2 12 | #define K_EVMASK_BUTTON 4 13 | #define K_EVMASK_DESKTOP 0x10 14 | #define K_EVMASK_MOUSE 0x20 15 | #define K_EVMASK_IPC 0x40 16 | #define K_EVMASK_NETWORK 0x80 17 | #define K_EVMASK_DEBUG 0x100 18 | #define K_EVMASK_AUTORESET (K_EVMASK_KEY|K_EVMASK_MOUSE|K_EVMASK_IPC|K_EVMASK_NETWORK|K_EVMASK_DEBUG) 19 | 20 | #define KBS_NO_PRESS 0x20000000 21 | #define KBS_NO_DRAW 0x40000000 22 | 23 | #define KMOD_LSHIFT 1 24 | #define KMOD_RSHIFT 2 25 | #define KMOD_LCTRL 4 26 | #define KMOD_RCTRL 8 27 | #define KMOD_LALT 0x10 28 | #define KMOD_RALT 0x20 29 | #define KMOD_CTRALTSH 0x3F 30 | #define KMOD_CAPSLOCK 0x40 31 | #define KMOD_NUMLOCK 0x80 32 | #define KMOD_SCROLL 0x100 33 | #define KMOD_LOCKMASK 0x1C0 34 | #define KMOD_LWIN 0x200 35 | #define KMOD_RWIN 0x400 36 | 37 | typedef struct 38 | { 39 | k_context* ctx; 40 | int x,y,w,h,id; 41 | } k_button; 42 | 43 | DWORD k_check_event(k_context* ctx); 44 | 45 | void k_event_redraw(k_context* ctx); 46 | void k_event_mousemove(k_context* ctx, int x, int y); 47 | void k_event_mousepress(k_context* ctx, DWORD button, int wheel); 48 | void k_event_mouserelease(k_context* ctx, DWORD button); 49 | void k_event_keypress(k_context* ctx, DWORD key); 50 | void k_event_network(k_context* ctx); 51 | 52 | void k_clear_redraw(k_context* ctx); 53 | DWORD k_get_mousepos(k_context* ctx, int* x, int* y); 54 | DWORD k_get_mouse(int* x, int* y); 55 | DWORD k_get_mousestate(k_context* ctx); 56 | DWORD k_get_mousewheel(k_context* ctx); 57 | DWORD k_define_hotkey(k_context* ctx, DWORD def); 58 | DWORD k_remove_hotkey(k_context* ctx, DWORD def); 59 | DWORD k_get_key(k_context* ctx); 60 | DWORD k_get_button(k_context* ctx); 61 | int k_is_dblclick(k_context* ctx); 62 | int k_check_hotkey(DWORD scancode); 63 | 64 | void k_clear_buttons(k_context* ctx); 65 | void k_define_button(k_context* ctx, int x, int y, int w, int h, int id); 66 | void k_remove_button(k_context* ctx, int id); 67 | 68 | k_button* k_find_button(k_context* ctx); 69 | k_button* k_find_button_by_id(k_context* ctx, int id); 70 | 71 | void k_set_keyboard_modifiers(DWORD modifiers, int reset); 72 | DWORD k_get_keyboard_modifiers(); 73 | DWORD k_get_keyboard_layout(DWORD id, DWORD data); 74 | DWORD k_set_keyboard_layout(DWORD id, DWORD data); 75 | DWORD k_get_keyboard_lang(); 76 | DWORD k_set_keyboard_lang(DWORD id); 77 | 78 | void k_event_ipc(k_context* ctx); 79 | void k_clear_ipc(k_context* ctx); 80 | 81 | void k_time_get(k_timespec* time); 82 | void k_time_add_ms(k_timespec* time, int ms); 83 | int k_time_gt(k_timespec* a, k_timespec* b); 84 | DWORD k_bcd_time(); 85 | DWORD k_bcd_date(); 86 | -------------------------------------------------------------------------------- /k_file.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_iconv.h" 4 | #include "k_ipc.h" 5 | #include "k_file.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #pragma pack(push,1) 17 | typedef struct 18 | { 19 | DWORD func; 20 | DWORD offset; 21 | DWORD extra; 22 | DWORD len; 23 | DWORD addr; 24 | BYTE name[4]; 25 | } k_fcb; 26 | 27 | typedef struct 28 | { 29 | BYTE sec; 30 | BYTE min; 31 | BYTE hour; 32 | BYTE reserved; 33 | BYTE day; 34 | BYTE mon; 35 | WORD year; 36 | } k_time; 37 | 38 | typedef struct 39 | { 40 | DWORD attr; 41 | DWORD cp; 42 | k_time ctime; 43 | k_time atime; 44 | k_time mtime; 45 | QWORD size; 46 | } k_folder_item_base; 47 | 48 | typedef struct 49 | { 50 | k_folder_item_base f; 51 | char fname[264]; 52 | } k_folder_item; 53 | 54 | typedef struct 55 | { 56 | k_folder_item_base f; 57 | char fname[520]; 58 | } k_folder_item2; 59 | 60 | typedef struct 61 | { 62 | DWORD version; 63 | DWORD count; 64 | DWORD total; 65 | DWORD reserved[5]; 66 | k_folder_item items[1]; 67 | } k_folder; 68 | #pragma pack(pop) 69 | 70 | char k_root[1024]; 71 | 72 | int is_dev_name(BYTE* name) 73 | { 74 | int i; 75 | for(i=0; *name; ++name) if(*name=='/' && name[1]!=0) ++i; 76 | return i<=2; 77 | } 78 | 79 | int is_key(BYTE** p) 80 | { 81 | char* key = kernel_mem()->extfs_key; int len = strlen(key); 82 | if(len>0 && strncasecmp((char*)*p, key, len)==0 && (p[0][len]=='/'||p[0][len]==0)) 83 | { 84 | *p += len; return 2; 85 | } 86 | else if(strncasecmp((char*)*p, "sys", 3)==0 && (p[0][3]=='/'||p[0][3]==0)) 87 | { 88 | *p += 3; return 1; 89 | } 90 | return 0; 91 | } 92 | 93 | char* k_parse_item(k_context* ctx, BYTE* name, int cp, char* buf, char* ebuf) 94 | { 95 | if(*name=='/') 96 | { 97 | if(name[1]>=1 && name[1]<=3) { cp = name[1]; name+=2; } 98 | if(*name=='/') name += cp==2?2:1; 99 | switch(is_key(&name)) 100 | { 101 | case 1: buf = k_parse_item(ctx, (BYTE*)"/RD/1/", cp, buf, ebuf); break; 102 | case 2: buf = k_parse_item(ctx, (BYTE*)kernel_mem()->extfs_path, cp, buf, ebuf); break; 103 | default: strcpy(buf, k_root); buf = strchr(buf,0); break; 104 | } 105 | } 106 | else 107 | { 108 | buf = k_parse_item(ctx, ctx==NULL?(BYTE*)"/RD/1/":ctx->curpath, cp, buf, ebuf); 109 | } 110 | if (buf[-1]!='/') *buf++='/'; 111 | if(k_strsize(name,cp,3)<=ebuf-buf) k_strcpy((BYTE*)buf,3,name,cp); else *buf = 0; 112 | return strchr(buf,0); 113 | } 114 | 115 | void k_check_exists(char* fname) 116 | { 117 | if(access(fname,F_OK)==0) return; 118 | char* p = strchr(fname,0); 119 | if(p==fname) return; else --p; 120 | while(p!=fname && *p!='/') --p; 121 | if(p==fname) return; else *p = 0; 122 | k_check_exists(fname); 123 | if(p[1]!=0) 124 | { 125 | struct dirent* e; DIR* d = opendir(fname); 126 | if(d!=NULL) 127 | { 128 | while((e=readdir(d))!=NULL) 129 | { 130 | if(strcasecmp(p+1, e->d_name)==0) 131 | { 132 | strcpy(p+1, e->d_name); 133 | break; 134 | } 135 | } 136 | closedir(d); 137 | } 138 | } 139 | *p = '/'; 140 | } 141 | 142 | void k_parse_name(k_context* ctx, BYTE* name, int cp, char* buf, int buflen) 143 | { 144 | if(cp==0 && *name>0 && *name<4) cp = *name++; 145 | k_parse_item(ctx, name, cp, buf, buf+buflen); 146 | k_check_exists(buf); 147 | } 148 | 149 | DWORD k_path_len(BYTE* path, int cp) 150 | { 151 | BYTE* p=path; if(cp<0 && *p>0 && *p<4) cp = *p++; 152 | if(cp==2) 153 | { 154 | if(*p=='/' && p[1]==0) { p+=2; is_key(&p); } 155 | while(*(WORD*)p) p+=2; p+=2; 156 | } 157 | else 158 | { 159 | while(*p++); 160 | } 161 | return p-path; 162 | } 163 | 164 | void set_time(k_time* t, time_t* from) 165 | { 166 | struct tm* ft = localtime(from); 167 | t->sec = ft->tm_sec; 168 | t->min = ft->tm_min; 169 | t->hour = ft->tm_hour; 170 | t->reserved = 0; 171 | t->day = ft->tm_mday; 172 | t->mon = ft->tm_mon+1; 173 | t->year = ft->tm_year+1900; 174 | } 175 | 176 | int get_stat(char* fname, k_folder_item_base* f) 177 | { 178 | struct stat st; 179 | if(stat(fname, &st)<0) return -1; 180 | if(f!=NULL) 181 | { 182 | f->attr = S_ISDIR(st.st_mode)?0x10:0; 183 | f->size = st.st_size; 184 | set_time(&f->ctime, &st.st_ctime); 185 | set_time(&f->atime, &st.st_atime); 186 | set_time(&f->mtime, &st.st_mtime); 187 | } 188 | return 0; 189 | } 190 | 191 | DWORD k_read_file(char* fname, k_fcb* fcb, DWORD* count) 192 | { 193 | void* data = user_mem(fcb->addr); 194 | FILE* f = fopen(fname, "r"); if(f==NULL) return 5; 195 | if(fcb->offset>0) fseek(f, fcb->offset, SEEK_SET); 196 | *count = fread(data, 1, fcb->len, f); fclose(f); 197 | return *countlen?6:0; 198 | } 199 | 200 | DWORD k_write_file(char* fname, k_fcb* fcb, DWORD* count, int create) 201 | { 202 | void* data = user_mem(fcb->addr); 203 | FILE* f = fopen(fname, create?"wb":"rb+"); if(f==NULL) return 5; 204 | if(fcb->offset>0 && !create) fseek(f, fcb->offset, SEEK_SET); 205 | *count = fwrite(data, 1, fcb->len, f); fclose(f); 206 | return *countlen?8:0; 207 | } 208 | 209 | DWORD k_truncate_file(char* fname, k_fcb* fcb) 210 | { 211 | FILE* f = fopen(fname, "rb+"); if(f==NULL) return 5; 212 | int err = ftruncate(fileno(f), fcb->offset); fclose(f); 213 | return err?8:0; 214 | } 215 | 216 | #define MAX_DEVICES 15 217 | char k_dev_name[MAX_DEVICES+1][10]; 218 | 219 | char* k_readroot(DIR* d, int i) 220 | { 221 | if(k_dev_name[0][0]==0) 222 | { 223 | static char* tmpl[] = {"RD","FD","HD","HD%d","TMP%d","CD%d"}; 224 | int t,n,dn=0; char* buf = strchr(k_root,0); 225 | for(t=0; td_name : NULL; 243 | } 244 | 245 | DWORD k_read_folder(char* fname, k_fcb* fcb, DWORD* count, int skipdot, int root) 246 | { 247 | union { k_folder_item* item; k_folder_item2* item2; } p; int i; 248 | k_folder* data = (k_folder*)user_mem(fcb->addr); p.item = data->items; *count = 0; 249 | DIR* d = NULL; char* e,*(*_next)(DIR*,int); 250 | 251 | data->version = 1; 252 | data->count = 0; 253 | data->total = 0; 254 | 255 | _next = root ? k_readroot : k_readdir; 256 | if(root==0 && (d=opendir(fname))==NULL) return 5; 257 | for(i=0;; ++i) 258 | { 259 | e = _next(d,i); if(e==NULL) break; 260 | while(e!=NULL && (strcmp(e,".")==0 || (skipdot && strcmp(e,"..")==0))) e = _next(d,i); 261 | if(e==NULL) break; 262 | if(i>=fcb->offset && ioffset+fcb->len) 263 | { 264 | char buf[1024],*s; sprintf(buf, "%s/%s", fname, e); 265 | get_stat(buf, &p.item->f); 266 | p.item->f.cp = fcb->extra; 267 | strcpy(p.item->fname, e); 268 | if(root) for(s=p.item->fname; *s; ++s) *s = tolower(*s); 269 | ++*count; if(fcb->extra<2) ++p.item; else ++p.item2; 270 | } 271 | data->total++; 272 | } 273 | if(d) closedir(d); 274 | 275 | data->count = *count; 276 | 277 | return *countlen?6:0; 278 | } 279 | 280 | DWORD k_stat(char* fname, k_fcb* fcb) 281 | { 282 | k_folder_item_base* f = (k_folder_item_base*)user_mem(fcb->addr); 283 | f->cp = fcb->extra; 284 | return get_stat(fname, f)<0 ? 5 : 0; 285 | } 286 | 287 | time_t convert_time(k_time* from) 288 | { 289 | struct tm st; 290 | st.tm_sec = from->sec; 291 | st.tm_min = from->min; 292 | st.tm_hour = from->hour; 293 | st.tm_mday = from->day; 294 | st.tm_mon = from->mon-1; 295 | st.tm_year = from->year-1900; 296 | return mktime(&st); 297 | } 298 | 299 | DWORD k_set_attr(char* fname, k_fcb* fcb) 300 | { 301 | k_folder_item_base* f = (k_folder_item_base*)user_mem(fcb->addr); 302 | struct utimbuf tb; 303 | tb.actime = convert_time(&f->atime); 304 | tb.modtime = convert_time(&f->mtime); 305 | utime(fname, &tb); 306 | chmod(fname, f->attr&1?0444:0666); 307 | return 0; 308 | } 309 | 310 | DWORD k_run_app(k_context* ctx, char* fname, char* args) 311 | { 312 | msg_t msg; 313 | if(get_stat(fname,NULL)<0) return -5; 314 | int len = strlen(k_root); 315 | if(strncmp(k_root, fname, len)==0) fname += len-1; 316 | msg_run(&msg, fname, args); 317 | write_msg(ipc_server, &msg); 318 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_REPLY); 319 | return ctx->retcode; 320 | } 321 | 322 | DWORD k_unlink(char* fname) 323 | { 324 | struct stat st; if(stat(fname, &st)<0) return 5; 325 | if(S_ISDIR(st.st_mode)) 326 | { 327 | if(rmdir(fname)==0) return 0; 328 | } 329 | else 330 | { 331 | if(unlink(fname)==0) return 0; 332 | } 333 | return 5; 334 | } 335 | 336 | DWORD k_mkdir(char* fname) 337 | { 338 | return mkdir(fname, 0777)==0 ? 0 : 5; 339 | } 340 | 341 | DWORD k_move(char* fname, char* newname) 342 | { 343 | return rename(fname, newname)==0 ? 0 : 5; 344 | } 345 | 346 | DWORD k_file_syscall(k_context* ctx, DWORD* eax, DWORD* ebx, int f80) 347 | { 348 | int cp = 0; BYTE* name; char fname[1024]; 349 | k_fcb* fcb = (k_fcb*)user_mem(*ebx); 350 | if(f80) 351 | { 352 | DWORD* p = (DWORD*)fcb->name; 353 | cp = *p++; name = user_pb(*p); 354 | } 355 | else 356 | { 357 | name = fcb->name[0]!=0 ? fcb->name : user_pb(*(DWORD*)(fcb->name+1)); 358 | } 359 | if(cp==0 && *name>0 && *name<4) cp = *name++; 360 | k_parse_name(ctx, name, cp, fname, sizeof(fname)); 361 | switch(fcb->func) 362 | { 363 | case 0: *eax = k_read_file(fname, fcb, ebx); break; 364 | case 1: *eax = k_read_folder(fname, fcb, ebx, is_dev_name(name), memcmp(name,"/\x0\x0",cp==2?4:2)==0); break; 365 | case 2: case 3: *eax = k_write_file(fname, fcb, ebx, fcb->func==2); break; 366 | case 4: *eax = k_truncate_file(fname, fcb); break; 367 | case 5: *eax = k_stat(fname, fcb); break; 368 | case 6: *eax = k_set_attr(fname, fcb); break; 369 | case 7: *eax = k_run_app(ctx, fname, fcb->extra==0?NULL:user_mem(fcb->extra)); break; 370 | case 8: *eax = k_unlink(fname); break; 371 | case 9: *eax = k_mkdir(fname); break; 372 | case 10: *eax = k_move(fname, (char*)user_mem(fcb->extra)); break; 373 | default: *eax = 2; return 1; 374 | } 375 | return 0; 376 | } 377 | 378 | void k_copy_path(BYTE* to, BYTE* from) 379 | { 380 | memcpy(to, from, k_path_len(from, -1)); 381 | } 382 | 383 | DWORD k_set_curpath(k_context* ctx, BYTE* path, int cp) 384 | { 385 | DWORD len = k_path_len(path, cp); 386 | BYTE* p = ctx->curpath; if(cp>=0) *p++ = cp; 387 | if(len>254) len = 254; memcpy(p, path, len); 388 | return 0; 389 | } 390 | 391 | DWORD k_get_curpath(k_context* ctx, BYTE* path, int cp, DWORD len) 392 | { 393 | DWORD curlen = k_path_len(ctx->curpath, -1); int curcp = -1; 394 | BYTE* p = ctx->curpath; if(*p>1 && *p<4) curcp = *p++; 395 | if(curcp!=cp) k_panic("Path conversion not supported"); 396 | if(curlen>len) curlen = len; 397 | memcpy(path, p, curlen); 398 | return 0; 399 | } 400 | 401 | DWORD k_set_extfs(BYTE* data) 402 | { 403 | KERNEL_MEM* km = kernel_mem(); 404 | memcpy(km->extfs_key, data, 128); 405 | memmove(km->extfs_path+1, km->extfs_path, 63); 406 | km->extfs_path[0] = '/'; 407 | return 0; 408 | } 409 | 410 | DWORD k_load_skin(k_context* ctx, BYTE* name) 411 | { 412 | char fname[1024]; msg_t msg; 413 | k_parse_name(ctx, name, 0, fname, sizeof(fname)); 414 | msg_load_skin(&msg, fname); 415 | write_msg(ipc_server, &msg); 416 | //for(ctx->retcode = 0; ctx->retcode==0;) k_process_ipc_event(ctx, &msg); 417 | return 0; // ctx->retcode 418 | } 419 | 420 | DWORD k_pci_get_last_bus() 421 | { 422 | DWORD last = 0,n; 423 | struct dirent* e; DIR* d = opendir("/sys/class/pci_bus"); 424 | if(d!=NULL) 425 | { 426 | while((e=readdir(d))!=NULL) 427 | { 428 | if(sscanf(e->d_name,"0000:%x",&n)==1 && n>last) last = n; 429 | } 430 | closedir(d); 431 | } 432 | return last; 433 | } 434 | 435 | DWORD k_pci_read_reg(DWORD ebx, DWORD ecx) 436 | { 437 | DWORD bus = (ebx>>8)&255, dev = (ecx>>11)&31, func = (ecx>>8)&7, reg = ecx&255; 438 | char fname[256]; BYTE data[64]; 439 | sprintf(fname, "/sys/class/pci_bus/0000:%02x/device/0000:%02x:%02x.%d/config", bus, bus, dev, func); 440 | FILE* fp = fopen(fname, "rb"); if(!fp) return -1; 441 | fread(data, 64, 1, fp); fclose(fp); 442 | switch(ebx&3) 443 | { 444 | case 0: return reg<64?data[reg]:-1; 445 | case 1: return reg<64&&(reg&1)==0?*(WORD*)(data+reg):-1; 446 | case 2: return reg<64&&(reg&3)==0?*(DWORD*)(data+reg):-1; 447 | } 448 | return -1; 449 | } 450 | -------------------------------------------------------------------------------- /k_file.h: -------------------------------------------------------------------------------- 1 | extern char k_root[]; 2 | 3 | void k_check_exists(char* fname); 4 | void k_parse_name(k_context* ctx, BYTE* name, int cp, char* buf, int buflen); 5 | DWORD k_file_syscall(k_context* ctx, DWORD* eax, DWORD* ebx, int f80); 6 | 7 | void k_copy_path(BYTE* to, BYTE* from); 8 | DWORD k_set_curpath(k_context* ctx, BYTE* path, int cp); 9 | DWORD k_get_curpath(k_context* ctx, BYTE* path, int cp, DWORD len); 10 | DWORD k_set_extfs(BYTE* data); 11 | DWORD k_load_skin(k_context* ctx, BYTE* name); 12 | 13 | DWORD k_pci_get_last_bus(); 14 | DWORD k_pci_read_reg(DWORD ebx, DWORD ecx); 15 | -------------------------------------------------------------------------------- /k_gui.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_iconv.h" 4 | #include "k_file.h" 5 | #include "k_ipc.h" 6 | #include "k_gui.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #define window_style ((ctx->window_color>>24)&15) 17 | 18 | Display* display; Window win; Picture picture; 19 | GlyphSet gsfont[2][8]; 20 | 21 | K_SKIN_PARAMS skin_params; 22 | K_SKIN_BUTTON skin_button_minimize; 23 | K_SKIN_BUTTON skin_button_close; 24 | 25 | typedef struct 26 | { 27 | DWORD width; 28 | DWORD height; 29 | XImage* img; 30 | } kpixmap; 31 | 32 | kpixmap kpixmaps[2][3]; 33 | 34 | void SetNoBorder() 35 | { 36 | int set = 0; 37 | Atom WM_HINTS; 38 | 39 | /* First try to set MWM hints */ 40 | WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", True); 41 | if(WM_HINTS != None) 42 | { 43 | struct { 44 | unsigned long flags; 45 | unsigned long functions; 46 | unsigned long decorations; 47 | long input_mode; 48 | unsigned long status; 49 | } MWMHints = { (1L << 1), 0, 0, 0, 0 }; 50 | 51 | XChangeProperty(display, win, WM_HINTS, WM_HINTS, 32, 52 | PropModeReplace, (unsigned char *)&MWMHints, 53 | sizeof(MWMHints)/sizeof(long)); 54 | set = 1; 55 | } 56 | 57 | /* Now try to set KWM hints */ 58 | WM_HINTS = XInternAtom(display, "KWM_WIN_DECORATION", True); 59 | if(WM_HINTS != None) 60 | { 61 | long KWMHints = 0; 62 | XChangeProperty(display, win, WM_HINTS, WM_HINTS, 32, 63 | PropModeReplace, (unsigned char *)&KWMHints, 64 | sizeof(KWMHints)/sizeof(long)); 65 | set = 1; 66 | } 67 | 68 | /* Now try to set GNOME hints */ 69 | WM_HINTS = XInternAtom(display, "_WIN_HINTS", True); 70 | if(WM_HINTS != None) 71 | { 72 | long GNOMEHints = 0; 73 | XChangeProperty(display, win, WM_HINTS, WM_HINTS, 32, 74 | PropModeReplace, (unsigned char *)&GNOMEHints, 75 | sizeof(GNOMEHints)/sizeof(long)); 76 | set = 1; 77 | } 78 | 79 | /* Finally set the transient hints if necessary */ 80 | if(!set) XSetTransientForHint(display, win, RootWindow(display, 0)); 81 | } 82 | 83 | void k_gui_init() 84 | { 85 | display = XOpenDisplay(NULL); 86 | if (DefaultDepth(display, 0) < 24) k_panic("Cannot work in non true color mode"); 87 | } 88 | 89 | void k_pixmap_setimage(kpixmap* pm, BYTE* image, int width, int height) 90 | { 91 | DWORD* image32 = (DWORD*)malloc(width*height*4),idx; 92 | 93 | for(idx = 0; idx < width * height; ++idx) 94 | image32[idx] = 0xffffff & *(DWORD*)(image + idx * 3); 95 | 96 | pm->width = width; 97 | pm->height = height; 98 | if(pm->img) XDestroyImage(pm->img); 99 | pm->img = XCreateImage(display, DefaultVisual(display, 0), 24, ZPixmap, 0, (char*)image32, width, height, 32, 0); 100 | } 101 | 102 | void k_set_skin(BYTE* skin) 103 | { 104 | K_SKIN_HDR* header = (K_SKIN_HDR*)skin; 105 | if (header==NULL || header->magic != 0x4e494b53 || header->version!=1) k_panic("Skin loading error"); 106 | 107 | K_SKIN_PARAMS* params = (K_SKIN_PARAMS*)(skin+header->params); 108 | K_SKIN_BUTTON* button = (K_SKIN_BUTTON*)(skin+header->buttons); 109 | K_SKIN_BMPDEF* bitmap = (K_SKIN_BMPDEF*)(skin+header->bitmaps); 110 | 111 | skin_params = *params; 112 | 113 | for(; button->type!=0; ++button) 114 | { 115 | switch(button->type) 116 | { 117 | case 1: skin_button_close = *button; break; 118 | case 2: skin_button_minimize = *button; break; 119 | } 120 | } 121 | 122 | for(; bitmap->kind!=0; ++bitmap) 123 | { 124 | if (bitmap->kind<=3 && bitmap->type<=1) 125 | { 126 | K_SKIN_BITMAP* bmp = (K_SKIN_BITMAP*)(skin+bitmap->offset); 127 | k_pixmap_setimage(&kpixmaps[bitmap->type][bitmap->kind-1], bmp->data, bmp->width, bmp->height); 128 | } 129 | } 130 | } 131 | 132 | void k_define_skin_button(k_context* ctx, K_SKIN_BUTTON* b, DWORD width, DWORD height) 133 | { 134 | int x = b->x, y = b->y; 135 | if (x<0) x += width; 136 | if (y<0) y += height; 137 | k_define_button(ctx, x-1, y-1, b->width+1, b->height+1, b->type==1 ? 1 : 0xFFFF); 138 | } 139 | 140 | DWORD k_get_skin_height() { return skin_params.height; } 141 | 142 | void k_get_skin_colors(BYTE* buf, DWORD size) 143 | { 144 | if (size>skin_params.dtpfsize) size = skin_params.dtpfsize; 145 | memcpy(buf, skin_params.dtp, size); 146 | } 147 | 148 | void k_get_client_rect(k_context* ctx, DWORD* x, DWORD* y, DWORD* w, DWORD* h) 149 | { 150 | *x = 5; 151 | *y = skin_params.height; 152 | *w = ctx->window_w-1-2*5; 153 | *h = ctx->window_h-1-5-skin_params.height; 154 | } 155 | 156 | void k_get_screen_size(DWORD* width, DWORD* height) 157 | { 158 | #ifdef SCREEN_WIDTH 159 | *width = SCREEN_WIDTH; 160 | #else 161 | *width = DisplayWidth(display,0); 162 | #endif 163 | #ifdef SCREEN_HEIGHT 164 | *height = SCREEN_HEIGHT; 165 | #else 166 | *height = DisplayHeight(display,0); 167 | #endif 168 | } 169 | 170 | void k_get_desktop_rect(DWORD* left, DWORD* top, DWORD* right, DWORD* bottom) 171 | { 172 | KERNEL_MEM* km = kernel_mem(); 173 | *left = km->desktop_left; 174 | *top = km->desktop_top; 175 | *right = km->desktop_right; 176 | *bottom = km->desktop_bottom; 177 | } 178 | 179 | void k_set_desktop_rect(WORD left, WORD top, WORD right, WORD bottom) 180 | { 181 | KERNEL_MEM* km = kernel_mem(); DWORD sw,sh; 182 | k_get_screen_size(&sw, &sh); 183 | if(left&0x8000) left = km->desktop_left; 184 | if(top&0x8000) top = km->desktop_top; 185 | if(leftdesktop_left = left; 188 | if(rightdesktop_right = right; 189 | } 190 | if(topdesktop_top = top; 193 | if(bottomdesktop_bottom = bottom; 194 | } 195 | } 196 | 197 | void k_move_mouse(int x, int y) 198 | { 199 | XWarpPointer(display, None, RootWindow(display, 0), 0,0,0,0, x,y); 200 | } 201 | 202 | void k_frame(Window win, GC gc, int x1, int y1, int x2, int y2, int width) 203 | { 204 | XFillRectangle(display, win, gc, x1, y1, width, y2-y1); 205 | XFillRectangle(display, win, gc, x1, y2-width, x2-x1, width); 206 | XFillRectangle(display, win, gc, x2-width, y1, width, y2-y1); 207 | } 208 | 209 | void k_draw_button_pressed(k_button* b) 210 | { 211 | XGCValues val; 212 | val.function = GXxor; 213 | val.foreground = 0xFFFFFF; 214 | GC gc = XCreateGC(display, win, GCFunction|GCForeground, &val); 215 | XFillRectangle(display, win, gc, b->x+1, b->y+1, b->w-1, 1); 216 | XFillRectangle(display, win, gc, b->x+1, b->y+2, 1, b->h-3); 217 | XFillRectangle(display, win, gc, b->x+1, b->y+b->h-1, b->w-1, 1); 218 | XFillRectangle(display, win, gc, b->x+b->w-1, b->y+2, 1, b->h-3); 219 | XFreeGC(display, gc); 220 | } 221 | 222 | XRenderColor xr_convert_color(DWORD color) 223 | { 224 | XRenderColor xrc; 225 | xrc.blue = ((color<<8)&0xFF00)|((color)&0xFF); 226 | xrc.green = ((color)&0xFF00)|((color>>8)&0xFF); 227 | xrc.red = ((color>>8)&0xFF00)|((color>>16)&0xFF); 228 | xrc.alpha = 0xFFFF; 229 | return xrc; 230 | } 231 | 232 | Picture xr_create_picture(int width, int height, int repeat) 233 | { 234 | Pixmap pm = XCreatePixmap(display, RootWindow(display, 0), width, height, 32); 235 | XRenderPictureAttributes attr; attr.repeat = repeat; 236 | Picture p = XRenderCreatePicture(display, pm, XRenderFindStandardFormat(display, PictStandardARGB32), CPRepeat, &attr); 237 | XFreePixmap(display, pm); 238 | return p; 239 | } 240 | 241 | Picture xr_create_pen(DWORD color) 242 | { 243 | XRenderColor xrc = xr_convert_color(color); Picture p = xr_create_picture(1,1,1); 244 | XRenderFillRectangle(display, PictOpOver, p, &xrc, 0, 0, 1, 1); 245 | return p; 246 | } 247 | 248 | void k_pixel8(BYTE* p, int mode, DWORD color) 249 | { 250 | *p = mode==0 ? 0xFF : 0x3F; 251 | } 252 | 253 | void k_pixel32(BYTE* p, int mode, DWORD color) 254 | { 255 | if(mode==0) 256 | { 257 | *(DWORD*)p = color; 258 | } 259 | else 260 | { 261 | *p = (*p>>2)*3+((color>>2)&0x3F); ++p; 262 | *p = (*p>>2)*3+((color>>10)&0x3F); ++p; 263 | *p = (*p>>2)*3+((color>>18)&0x3F); 264 | } 265 | } 266 | 267 | void k_prepare_char(BYTE* ch, int width, int height, BYTE* buf, DWORD stride, DWORD s, void(*putpix)(BYTE*,int,DWORD), DWORD color, DWORD pixsz) 268 | { 269 | DWORD x,y,w,h,b0,b1,b2; BYTE map[16][8],*d; memset(*map,0,sizeof(map)); 270 | for(y=0; y>=1,b1>>=1,b2>>=1) 274 | { 275 | w = (b2&0x700)|(b1&0x70)|(b0&7); 276 | if((w&0x670)==0x240 || (w&0x770)==0x350 || w==0x640) map[y][x] |= 1; 277 | if((w&0x370)==0x210 || (w&0x770)==0x650 || w==0x310) map[y][x] |= 2; 278 | if((w&0x076)==0x042 || (w&0x077)==0x053 || w==0x046) map[y][x] |= 4; 279 | if((w&0x073)==0x012 || (w&0x077)==0x056 || w==0x013) map[y][x] |= 8; 280 | if((w&0x770)==0x250) map[y][x] |= 3; 281 | if((w&0x077)==0x052) map[y][x] |= 12; 282 | if(w&0x20) map[y][x] = 0x10; 283 | } 284 | } 285 | if(s==1) 286 | { 287 | for(y=0; ys-h-1) || 302 | ((m&2)!=0 && wh) || 304 | ((m&8)!=0 && wheight==9 ? 0 : 1; 314 | if(gsfont[size][scale]==0) 315 | { 316 | Glyph i; BYTE* ch; DWORD s=scale+1,stride = ((bf->width*s-1)|3)+1; 317 | XGlyphInfo info = {.width = bf->width*s, .height = bf->height*s, .x = 0, .y = 0, .xOff = bf->width*s, .yOff = 0}; 318 | GlyphSet font = XRenderCreateGlyphSet(display, XRenderFindStandardFormat(display, PictStandardA8)); 319 | for(i=0,ch=bf->bmp; ichars; ++i,ch+=bf->height) 320 | { 321 | static BYTE buf[16*8*8*8]; memset(buf,0,bf->height*s*stride); 322 | k_prepare_char(ch, bf->width, bf->height, buf, stride, s, k_pixel8, 0, 1); 323 | XRenderAddGlyphs(display, font, &i, &info, 1, (char*)buf, bf->height*s*stride); 324 | } 325 | gsfont[size][scale] = font; 326 | } 327 | return gsfont[size][scale]; 328 | } 329 | 330 | void k_draw_text_intern(k_context* ctx, int x, int y, BYTE* text, int len, int fillbg, int cp, int buf, int scale, DWORD color, DWORD extra) 331 | { 332 | if(text==NULL) return; k_bitmap_font* bf = cp==0 ? &font9 : &font16; 333 | if(len<0||len>512) len = k_strlen(text, cp); 334 | if(buf) 335 | { 336 | x -= ctx->client_x; y -= ctx->client_y; 337 | DWORD* data = user_pd(extra), width=*data++, height=*data++; 338 | int maxlen = (width-x)/bf->width,i; 339 | if(len>maxlen) len = maxlen; if(len<=0) return; 340 | if(y+bf->height>height) return; 341 | if(cp==0) 342 | { 343 | for(i=0; ibmp+text[i]*bf->height, bf->width, bf->height, 345 | (BYTE*)(data+y*width+x+i*bf->width*(scale+1)), width*4, scale+1, k_pixel32, color, 4); 346 | } 347 | else 348 | { 349 | WORD wbuf[512]; if(len>511) len=511; k_strncpy((BYTE*)wbuf, 2, text, cp, len); 350 | for(i=0; ibmp+wbuf[i]*bf->height, bf->width, bf->height, 352 | (BYTE*)(data+y*width+x+i*bf->width*(scale+1)), width*4, scale+1, k_pixel32, color, 4); 353 | } 354 | } 355 | else 356 | { 357 | int maxlen = (ctx->window_w-x)/bf->width; 358 | if(len>maxlen) len = maxlen; if(len<=0) return; 359 | int sx = len*(scale+1)*bf->width, sy = (scale+1)*bf->height; 360 | if(fillbg) 361 | { 362 | XRenderColor bgcolor = xr_convert_color(extra); 363 | XRenderFillRectangle(display, PictOpSrc, picture, &bgcolor, x,y, sx,sy); 364 | } 365 | Picture fg_pen = xr_create_pen(color); 366 | if(cp==0) 367 | { 368 | XRenderCompositeString8(display, PictOpOver, fg_pen, picture, NULL, xr_get_font(bf,scale), 0,0, x,y, (char*)text, len); 369 | } 370 | else 371 | { 372 | WORD wbuf[512]; if(len>511) len=511; k_strncpy((BYTE*)wbuf, 2, text, cp, len); 373 | XRenderCompositeString16(display, PictOpOver, fg_pen, picture, NULL, xr_get_font(bf,scale), 0,0, x,y, wbuf, len); 374 | } 375 | XRenderFreePicture(display, fg_pen); 376 | } 377 | } 378 | 379 | void k_fill_rectangle(k_context* ctx, int x, int y, int width, int height, DWORD color) 380 | { 381 | if((color&0x80000000)==0) 382 | { 383 | XGCValues val; val.foreground = color&0xFFFFFF; 384 | GC gc = XCreateGC(display, win, GCForeground, &val); 385 | XFillRectangle(display, win, gc, x, y, width, height); 386 | XFreeGC(display, gc); 387 | } 388 | else 389 | { 390 | XLinearGradient lg = {{0,0},{0,XDoubleToFixed(ctx->window_h/2)}}; XFixed stops[] = {0, XDoubleToFixed(1.0f)}; 391 | XRenderColor cols[] = {xr_convert_color(color&0xFFFFFF), xr_convert_color(0)}; 392 | Picture p = XRenderCreateLinearGradient(display, &lg, stops, cols, 2); 393 | XRenderComposite(display, PictOpSrc, p, 0, picture, 0,0, 0,0, x,y, width,height); 394 | XRenderFreePicture(display, p); 395 | } 396 | } 397 | 398 | void k_draw_window_intern(k_context* ctx, int onlyframe) 399 | { 400 | if(window_style<=1 && (ctx->window_color&0x40000000)==0) 401 | { 402 | if(onlyframe==0) k_fill_rectangle(ctx, 0, 0, ctx->window_w, ctx->window_h, ctx->window_color); 403 | return; 404 | } 405 | if(window_style!=3 && window_style!=4) return; 406 | 407 | int ofs; DWORD width = ctx->window_w, height = ctx->window_h; 408 | 409 | // Title bar 410 | kpixmap* left = kpixmaps[ctx->focused&1]; 411 | kpixmap* oper = left+1; 412 | kpixmap* base = left+2; 413 | XPutImage(display, win, DefaultGC(display, 0), left->img, 0,0, 0,0, left->width,left->height); 414 | if (width > oper->width) 415 | { 416 | for(ofs = left->width; ofs < width - oper->width; ofs += base->width) 417 | { 418 | XPutImage(display, win, DefaultGC(display, 0), base->img, 0,0, ofs,0, base->width,base->height); 419 | } 420 | } 421 | XPutImage(display, win, DefaultGC(display, 0), oper->img, 0,0, width - oper->width,0, oper->width,oper->height); 422 | 423 | K_SKIN_COLORS* col = ctx->focused ? &skin_params.acolor : &skin_params.icolor; 424 | 425 | // Border 426 | XGCValues val; val.foreground = col->outer; 427 | GC gc = XCreateGC(display, win, GCForeground, &val); 428 | k_frame(win, gc, 0, skin_params.height, width, height, 1); 429 | XSetForeground(display, gc, col->frame); 430 | k_frame(win, gc, 1, skin_params.height, width-1, height-1, 3); 431 | XSetForeground(display, gc, col->inner); 432 | k_frame(win, gc, 4, skin_params.height, width-4, height-4, 1); 433 | 434 | // Caption 435 | if(ctx->window_title!=NULL) 436 | { 437 | k_draw_text_intern(ctx, skin_params.lmargin, (skin_params.height-14)/2, (BYTE*)ctx->window_title, -1, 0, 3, 0, 0, 438 | skin_params.dtpfsize<5*sizeof(DWORD)?0:skin_params.dtp[4], 0); 439 | } 440 | 441 | // Client area 442 | if((ctx->window_color&0x40000000)==0 && onlyframe==0) 443 | { 444 | k_fill_rectangle(ctx, skin_params.lmargin, skin_params.height, 445 | width-2*skin_params.lmargin, height-skin_params.height-skin_params.lmargin, ctx->window_color); 446 | } 447 | 448 | XFreeGC(display, gc); 449 | 450 | k_remove_button(ctx, 1); k_remove_button(ctx, 0xFFFF); 451 | k_define_skin_button(ctx, &skin_button_close, width, height); 452 | k_define_skin_button(ctx, &skin_button_minimize, width, height); 453 | 454 | if(ctx->button_id_pressed!=0 && (ctx->button_id_pressed&KBS_NO_PRESS)==0) 455 | { 456 | k_button* b = k_find_button_by_id(ctx, ctx->button_id_pressed); 457 | if (b!=NULL) k_draw_button_pressed(b); 458 | } 459 | } 460 | 461 | void k_move_window(k_context* ctx, int x, int y) 462 | { 463 | if (win==0) return; 464 | if(x!=ctx->window_x || y!=ctx->window_y) 465 | XMoveWindow(display, win, x, y); 466 | ctx->window_x = x; 467 | ctx->window_y = y; 468 | } 469 | 470 | void k_min_size(k_context* ctx, int width, int height, int fix) 471 | { 472 | XSizeHints size; 473 | size.flags = fix ? PMinSize | PMaxSize : PMinSize; 474 | size.max_width = 0; 475 | size.min_width = width; 476 | size.max_height = 0; 477 | size.min_height = height; 478 | XSetWMNormalHints(display, win, &size); 479 | } 480 | 481 | void k_move_size_window(k_context* ctx, int x, int y, int width, int height) 482 | { 483 | if (win==0) return; 484 | if (x==-1) x = ctx->window_x; 485 | if (y==-1) y = ctx->window_y; 486 | if (width==-1) width = ctx->window_w-1; 487 | if (height==-1) height = ctx->window_h-1; 488 | ++width; ++height; 489 | int minw = skin_params.rmargin+5; 490 | int minh = skin_params.height+5; 491 | if(window_style==4) 492 | { 493 | if(widthwindow_w || height!=ctx->window_h) 501 | XMoveResizeWindow(display, win, x, y, width, height); 502 | else if(x!=ctx->window_x || y!=ctx->window_y) 503 | XMoveWindow(display, win, x, y); 504 | ctx->window_x = x; 505 | ctx->window_y = y; 506 | ctx->window_w = width; 507 | ctx->window_h = height; 508 | if(width<=1 && height<=1) return; 509 | k_draw_window_intern(ctx,0); 510 | k_event_redraw(ctx); 511 | usleep(2000); // hack 512 | } 513 | 514 | 515 | void k_wm_state(k_context* ctx, char *atom, char *atom2, int state) 516 | { 517 | if (win==0) return; 518 | XEvent ev; memset(&ev, 0, sizeof(ev)); 519 | ev.xclient.type = ClientMessage; 520 | ev.xclient.window = win; 521 | ev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); 522 | ev.xclient.format = 32; 523 | ev.xclient.data.l[0] = state&1; 524 | ev.xclient.data.l[1] = XInternAtom(display, atom, 0); 525 | ev.xclient.data.l[2] = atom2==NULL ? 0 : XInternAtom(display, atom2, 0); 526 | XSendEvent(display, RootWindow(display, 0), 0, SubstructureNotifyMask, &ev); 527 | } 528 | 529 | void k_raise_window(k_context* ctx) 530 | { 531 | if (win==0) return; 532 | XEvent ev; memset(&ev, 0, sizeof(ev)); 533 | ev.xclient.type = ClientMessage; 534 | ev.xclient.window = win; 535 | ev.xclient.message_type = XInternAtom(display, "_NET_ACTIVE_WINDOW", 0); 536 | ev.xclient.format = 32; 537 | XSendEvent(display, RootWindow(display, 0), 0, SubstructureRedirectMask|SubstructureNotifyMask, &ev); 538 | XMapRaised(display, win); 539 | } 540 | 541 | DWORD k_get_pixel(k_context* ctx, int x, int y) 542 | { 543 | XImage* xim = XGetImage(display, RootWindow(display, 0), x, y, 1, 1, AllPlanes, XYPixmap); 544 | unsigned long xpixel = XGetPixel(xim, 0, 0); XFree(xim); 545 | return xpixel&0xFFFFFF; 546 | } 547 | 548 | void k_get_image(k_context* ctx, int x, int y, DWORD width, DWORD height, BYTE* img) 549 | { 550 | unsigned long w = RootWindow(display, 0); 551 | if(win!=0 && x>=ctx->window_x && y>=ctx->window_y && x+width+1window_x+ctx->window_w && y+height+1window_y+ctx->window_h) 552 | { 553 | XWindowAttributes wa; XGetWindowAttributes(display, win, &wa); 554 | if(wa.map_state==IsViewable) { w = win; x -= ctx->window_x; y -= ctx->window_y; } 555 | } 556 | XImage* xim = XGetImage(display, w, x, y, width, height, AllPlanes, XYPixmap); 557 | for(y = 0; y < height; ++y) for(x = 0; x < width; ++x) 558 | { 559 | unsigned long xpixel = XGetPixel(xim, x, y); 560 | *img++ = xpixel; xpixel>>=8; *img++ = xpixel; xpixel>>=8; *img++ = xpixel; 561 | } 562 | XFree(xim); 563 | } 564 | 565 | static BYTE xscan2kex[256] = { 566 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 567 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 568 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 569 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 570 | 571 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 572 | 0x47,0x4B,0x48,0x4D, 0x50,0x49,0x51,0x4F, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 573 | 0x00,0x00,0x00,0x52, 0x00,0x00,0x00,0x5D, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 574 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x45, 575 | 576 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x1C,0x00,0x00, 577 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 578 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x37,0x00, 0x53,0x4A,0x00,0x35, 579 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 580 | 581 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 582 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 583 | 0x00,0x00,0x00,0x00, 0x1D,0x00,0x00,0x00, 0x00,0x00,0x38,0x5B, 0x5C,0x00,0x00,0x00, 584 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x53 585 | }; 586 | 587 | static WORD xchar2kex[256] = { 588 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 589 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 590 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 591 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 592 | 593 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 594 | 0x1B4,0x1B0,0x1B2,0x1B3, 0x1B1,0x1B8,0x1B7,0x1B5, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 595 | 0x00,0x00,0x00,0x1B9, 0x00,0x00,0x00,0x14A, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 596 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x02, 597 | 598 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x10D,0x00,0x00, 599 | 0x00,0x00,0x00,0x00, 0x00,0xB4,0xB0,0xB2, 0xB3,0xB1,0xB8,0xB7, 0xB5,0x37,0xB9,0xB6, 600 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x2A,0x2B, 0x2C,0x2D,0x00,0x12F, 601 | 0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37, 0x38,0x39,0x00,0x00, 0x00,0x00,0x00,0x00, 602 | 603 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 604 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 605 | 0x00,0x00,0x00,0x00, 0x100,0x00,0x00,0x00, 0x00,0x00,0x100,0x138, 0x138,0x00,0x00,0x00, 606 | 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x1B6 607 | }; 608 | 609 | DWORD k_translate_xkey(XKeyEvent* e, DWORD* ext, DWORD* mod) 610 | { 611 | static KeySym modxlat[] = {XK_Shift_L, XK_Shift_R, XK_Control_L, XK_Control_R, XK_Alt_L, XK_Alt_R, 612 | XK_Caps_Lock, XK_Num_Lock, XK_Scroll_Lock, XK_Super_L, XK_Super_R}; DWORD i,m; 613 | KeySym key; XLookupString(e, NULL, 0, &key, NULL); 614 | if (key==XK_ISO_Level3_Shift) key = XK_Alt_R; 615 | BYTE scancode = e->keycode - 8; 616 | BYTE charcode = key; *ext = *mod = 0; 617 | if ((key>>8)==0xFF) 618 | { 619 | if (xscan2kex[charcode]!=0) scancode = xscan2kex[charcode]; 620 | if (xchar2kex[charcode]!=0) { WORD extcode = xchar2kex[charcode]; charcode = extcode; *ext = extcode>>8; } 621 | } 622 | for(i=0,m=1; i<11; ++i,m<<=1) if(key==modxlat[i]) { *mod = m; break; } 623 | return (scancode<<16)|(charcode<<8); 624 | } 625 | 626 | void k_drag_window(k_context* ctx, int x, int y, int x_root, int y_root) 627 | { 628 | static int x2, y2; if((ctx->window_state&1)!=0) return; 629 | int mode = (x<5 ? 1 : (x>ctx->window_w-5 ? 2 : 0)) | (y<5 ? 4 : (y>ctx->window_h-5 ? 8 : 0)); 630 | if(mode==0 && ywindow_drag_mode==0 && mode>0) 632 | { 633 | ctx->window_drag_mode = mode; 634 | x2 = x<5 ? ctx->window_x+x+ctx->window_w : ctx->window_x+x-ctx->window_w; 635 | y2 = y<5 ? ctx->window_y+y+ctx->window_h : ctx->window_y+y-ctx->window_h; 636 | } 637 | switch(ctx->window_drag_mode) 638 | { 639 | case 1: k_move_size_window(ctx, x_root-x, ctx->window_y, x2-x_root-1, ctx->window_h-1); break; 640 | case 2: k_move_size_window(ctx, ctx->window_x, ctx->window_y, x_root-x2-1, ctx->window_h-1); break; 641 | case 4: k_move_size_window(ctx, ctx->window_x, y_root-y, ctx->window_w-1, y2-y_root-1); break; 642 | case 5: k_move_size_window(ctx, x_root-x, y_root-y, x2-x_root-1, y2-y_root-1); break; 643 | case 6: k_move_size_window(ctx, ctx->window_x, y_root-y, x_root-x2-1, y2-y_root-1); break; 644 | case 8: k_move_size_window(ctx, ctx->window_x, ctx->window_y, ctx->window_w-1, y_root-y2-1); break; 645 | case 9: k_move_size_window(ctx, x_root-x, ctx->window_y, x2-x_root-1, y_root-y2-1); break; 646 | case 10: k_move_size_window(ctx, ctx->window_x, ctx->window_y, x_root-x2-1, y_root-y2-1); break; 647 | case 15: k_move_window(ctx, x_root-x, y_root-y); break; 648 | } 649 | } 650 | 651 | void k_process_event(k_context* ctx) 652 | { 653 | static DWORD btnxlat[] = {0,1,4,2,0,0}; 654 | static int wheel[] = {0,0,0,0,-1,1}; 655 | static int x, y; 656 | 657 | if(XPending(display) == 0) 658 | { 659 | int i,xfd = ConnectionNumber(display),fdcnt = (xfd>ipc_server ? xfd : ipc_server)+1; 660 | fd_set fds; msg_t msg; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1000; 661 | for(;;) 662 | { 663 | FD_ZERO(&fds); FD_SET(xfd, &fds); FD_SET(ipc_server, &fds); 664 | for(i=0; isockets[i]) 665 | { 666 | FD_SET(ctx->sockets[i], &fds); if(ctx->sockets[i]>=fdcnt) fdcnt = ctx->sockets[i]+1; 667 | } 668 | if(select(fdcnt, &fds, NULL, NULL, &tv)<=0) return; 669 | if(FD_ISSET(ipc_server, &fds)) k_process_ipc_event(ctx, &msg); else break; 670 | } 671 | if(!FD_ISSET(xfd, &fds)) k_event_network(ctx); 672 | } 673 | 674 | while(XPending(display) != 0) 675 | { 676 | DWORD button_id,ext,mod; int hot; 677 | XEvent ev; XNextEvent(display, &ev); 678 | 679 | switch(ev.type) 680 | { 681 | case Expose: 682 | k_draw_window_intern(ctx,1); 683 | k_event_redraw(ctx); 684 | break; 685 | 686 | case KeyPress: 687 | button_id = k_translate_xkey(&ev.xkey, &ext, &mod); 688 | if(mod&KMOD_CAPSLOCK) k_set_keyboard_modifiers(KMOD_CAPSLOCK, (ev.xkey.state&LockMask)!=0); 689 | if(mod&KMOD_NUMLOCK) k_set_keyboard_modifiers(KMOD_NUMLOCK, (ev.xkey.state&Mod2Mask)!=0); 690 | if(mod&KMOD_SCROLL) k_set_keyboard_modifiers(KMOD_SCROLL, (k_get_keyboard_modifiers()&KMOD_SCROLL)!=0); 691 | if(mod&~KMOD_LOCKMASK) k_set_keyboard_modifiers(mod,0); 692 | hot = k_check_hotkey(mod&KMOD_CTRALTSH?0:(button_id>>16)); 693 | if(ctx->kbd_mode==1) 694 | { 695 | button_id = (button_id>>8)&0xFF00; 696 | if(ext) k_event_keypress(ctx, 0xE000); 697 | } 698 | if(ctx->kbd_mode==1 || (mod==0&&hot==0)) k_event_keypress(ctx, button_id); 699 | break; 700 | 701 | case KeyRelease: 702 | button_id = k_translate_xkey(&ev.xkey, &ext, &mod); 703 | if(mod&~KMOD_LOCKMASK) k_set_keyboard_modifiers(mod,1); 704 | k_check_hotkey(mod&KMOD_CTRALTSH?0:((button_id>>16)|0x80)); 705 | if(ctx->kbd_mode==1) 706 | { 707 | button_id = (button_id>>8)&0xFF00; 708 | if(ext) k_event_keypress(ctx, 0xE000); 709 | k_event_keypress(ctx, button_id|0x8000); 710 | } 711 | break; 712 | 713 | case ButtonPress: 714 | x = ev.xbutton.x; 715 | y = ev.xbutton.y; 716 | button_id = ctx->button_id_pressed; 717 | if(k_is_dblclick(ctx) && ywindow_state ^= 1; 720 | k_wm_state(ctx, "_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_MAXIMIZED_VERT", ctx->window_state&1); 721 | if ((ctx->window_state&1)==0) 722 | { 723 | k_move_size_window(ctx, ctx->orig_x, ctx->orig_y, ctx->orig_w-1, ctx->orig_h-1); 724 | } 725 | } 726 | k_event_mousepress(ctx, btnxlat[ev.xbutton.button], wheel[ev.xbutton.button]); 727 | if(button_id != ctx->button_id_pressed && (ctx->button_id_pressed&KBS_NO_PRESS)==0) 728 | { 729 | k_button* b = k_find_button_by_id(ctx, ctx->button_id_pressed); 730 | if (b!=NULL) k_draw_button_pressed(b); 731 | } 732 | if((ev.xbutton.button & Button1)!=0 && ctx->button_id_pressed==0) 733 | { 734 | k_drag_window(ctx, x, y, ctx->window_x+x, ctx->window_y+y); 735 | } 736 | break; 737 | 738 | case ButtonRelease: 739 | button_id = ctx->button_id_pressed; 740 | k_event_mouserelease(ctx, btnxlat[ev.xbutton.button]); 741 | if(button_id != ctx->button_id_pressed && (button_id&KBS_NO_PRESS)==0) 742 | { 743 | k_button* b = k_find_button_by_id(ctx, button_id); 744 | if (b!=NULL) k_draw_button_pressed(b); 745 | } 746 | if(button_id==0xFFFF) 747 | { 748 | k_button* b = k_find_button(ctx); 749 | if (b!=NULL && b->id == 0xFFFF) XIconifyWindow(display, win, 0); 750 | } 751 | ctx->window_drag_mode = 0; 752 | break; 753 | 754 | case MotionNotify: 755 | if((ev.xmotion.state & Button1Mask)!=0 && ctx->button_id_pressed==0) 756 | { 757 | k_drag_window(ctx, x, y, ev.xmotion.x_root, ev.xmotion.y_root); 758 | } 759 | k_event_mousemove(ctx, ev.xmotion.x_root, ev.xmotion.y_root); 760 | break; 761 | 762 | case FocusIn: 763 | if (ctx->focused==1) break; 764 | k_focus_in(ctx); 765 | ctx->focused = 1; 766 | if(ctx->window_w<=1 && ctx->window_h<=1) break; 767 | k_draw_window_intern(ctx,1); 768 | k_event_redraw(ctx); 769 | break; 770 | 771 | case FocusOut: 772 | if (ctx->focused==0) break; 773 | ctx->focused = 0; 774 | if(ctx->window_w<=1 && ctx->window_h<=1) break; 775 | k_draw_window_intern(ctx,1); 776 | k_event_redraw(ctx); 777 | break; 778 | 779 | case ConfigureNotify: 780 | if (ev.xconfigure.window == win && (ev.xconfigure.width>1 || ev.xconfigure.height>1)) 781 | { 782 | XTranslateCoordinates(display,win,RootWindow(display,0),0,0,&ctx->window_x,&ctx->window_y,&ev.xconfigure.window); 783 | ctx->window_w = ev.xconfigure.width; 784 | ctx->window_h = ev.xconfigure.height; 785 | ctx->mouse_x = kernel_mem()->mouse_x - ctx->window_x; 786 | ctx->mouse_y = kernel_mem()->mouse_y - ctx->window_y; 787 | if ((ctx->window_state&1)==0) 788 | { 789 | ctx->orig_x = ctx->window_x; 790 | ctx->orig_y = ctx->window_y; 791 | ctx->orig_w = ctx->window_w; 792 | ctx->orig_h = ctx->window_h; 793 | } 794 | } 795 | break; 796 | } 797 | } 798 | } 799 | 800 | void k_window(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color, DWORD titleaddr) 801 | { 802 | ctx->window_color = color; 803 | ctx->client_x = (color&0x20000000)==0 || window_style<3 ? 0 : 5; 804 | ctx->client_y = (color&0x20000000)==0 || window_style<3 ? 0 : skin_params.height; 805 | 806 | if (win==0) 807 | { 808 | ctx->window_x = 0; ctx->window_y = 0; ctx->window_w = 1; ctx->window_h = 1; 809 | 810 | if((window_style==3 || window_style==4) && (color&0x10000000)!=0 && titleaddr!=0) 811 | { 812 | ctx->window_title = (char*)k_strdup(user_pb(titleaddr),-1,3); 813 | } 814 | 815 | win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, 1, 1, 0, 0, color&0xFFFFFF); SetNoBorder(); 816 | if(ctx->window_title) 817 | Xutf8SetWMProperties(display, win, ctx->window_title, NULL, NULL, 0, NULL, NULL, NULL); 818 | XMapWindow(display, win); 819 | XGrabKey(display, AnyKey, AnyModifier, win, True, GrabModeAsync, GrabModeAsync); 820 | XSelectInput(display, win, ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|FocusChangeMask); 821 | picture = XRenderCreatePicture(display, win, XRenderFindStandardFormat(display, PictStandardRGB24), 0, 0); 822 | 823 | if(window_style<=1) 824 | { 825 | k_wm_state(ctx, "_NET_WM_STATE_SKIP_TASKBAR", "_NET_WM_STATE_SKIP_PAGER", 1); 826 | } 827 | 828 | if(window_style!=1) 829 | { 830 | DWORD sx,sy,sw,sh; 831 | k_get_desktop_rect(&sx, &sy, &sw, &sh); 832 | if(x=sw) x = sw-width-1; 834 | if(y+height>=sh) y = sh-height-1; 835 | } 836 | 837 | k_move_size_window(ctx, x, y, width, height); 838 | } 839 | else 840 | { 841 | if(window_style==3 || window_style==4) 842 | { 843 | if((color&0x10000000)!=0 && titleaddr!=0) 844 | { 845 | char* title = (char*)k_strdup(user_pb(titleaddr),-1,3); 846 | if(strcmp(ctx->window_title, title)!=0) 847 | { 848 | if(ctx->window_title) free(ctx->window_title); ctx->window_title = title; 849 | Xutf8SetWMProperties(display, win, ctx->window_title, NULL, NULL, 0, NULL, NULL, NULL); 850 | } 851 | else 852 | { 853 | free(title); 854 | } 855 | } 856 | else 857 | { 858 | if(ctx->window_title) free(ctx->window_title); ctx->window_title = NULL; 859 | Xutf8SetWMProperties(display, win, ctx->window_title, NULL, NULL, 0, NULL, NULL, NULL); 860 | } 861 | } 862 | k_draw_window_intern(ctx,0); 863 | } 864 | } 865 | 866 | void k_set_title(k_context* ctx, DWORD titleaddr, int cp) 867 | { 868 | if(ctx->window_title) free(ctx->window_title); 869 | ctx->window_title = titleaddr==0 ? NULL : (char*)k_strdup(user_pb(titleaddr),-1,3); 870 | if(win!=0) 871 | { 872 | Xutf8SetWMProperties(display, win, ctx->window_title, NULL, NULL, 0, NULL, NULL, NULL); 873 | k_event_redraw(ctx); 874 | } 875 | } 876 | 877 | void k_draw_button(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color) 878 | { 879 | if(win==0) return; k_clear_redraw(ctx); 880 | x += ctx->client_x; y += ctx->client_y; 881 | XGCValues val; val.foreground = (color &= 0xFFFFFF); DWORD color2 = (color>>1)&0x7F7F7F; 882 | GC gc = XCreateGC(display, win, GCForeground, &val); 883 | XFillRectangle(display, win, gc, x+2, y+2, width-3, height-3); 884 | XSetForeground(display, gc, color2); 885 | XFillRectangle(display, win, gc, x+1, y, width-1, 1); 886 | XFillRectangle(display, win, gc, x, y+1, 1, height-1); 887 | XFillRectangle(display, win, gc, x+1, y+height, width-1, 1); 888 | XFillRectangle(display, win, gc, x+width, y+1, 1, height-1); 889 | XSetForeground(display, gc, (color>>1)|0x808080); 890 | XFillRectangle(display, win, gc, x+1, y+1, width-1, 1); 891 | XFillRectangle(display, win, gc, x+1, y+2, 1, height-3); 892 | XSetForeground(display, gc, color2+((color2>>1)&0x7F7F7F)); 893 | XFillRectangle(display, win, gc, x+1, y+height-1, width-1, 1); 894 | XFillRectangle(display, win, gc, x+width-1, y+2, 1, height-3); 895 | XFreeGC(display, gc); 896 | } 897 | 898 | void k_draw_pixel(k_context* ctx, int x, int y, DWORD color) 899 | { 900 | if(win==0) return; k_clear_redraw(ctx); 901 | x += ctx->client_x; y += ctx->client_y; 902 | XGCValues val; 903 | if (((color>>24)&1)==0) 904 | { 905 | val.function = GXcopy; 906 | val.foreground = color; 907 | } 908 | else 909 | { 910 | val.function = GXxor; 911 | val.foreground = 0xFFFFFF; 912 | } 913 | GC gc = XCreateGC(display, win, GCFunction|GCForeground, &val); 914 | XFillRectangle(display, win, gc, x,y, 1,1); 915 | XFreeGC(display, gc); 916 | } 917 | 918 | void k_draw_rect(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color) 919 | { 920 | if(win==0) return; k_clear_redraw(ctx); 921 | x += ctx->client_x; y += ctx->client_y; 922 | k_fill_rectangle(ctx,x,y,width,height,color); 923 | } 924 | 925 | void k_draw_line(k_context* ctx, int x1, int y1, int x2, int y2, DWORD color) 926 | { 927 | if(win==0) return; k_clear_redraw(ctx); 928 | x1 += ctx->client_x; y1 += ctx->client_y; x2 += ctx->client_x; y2 += ctx->client_y; 929 | XGCValues val; 930 | if (((color>>24)&1)==0) 931 | { 932 | val.function = GXcopy; 933 | val.foreground = color; 934 | } 935 | else 936 | { 937 | val.function = GXxor; 938 | val.foreground = 0xFFFFFF; 939 | } 940 | GC gc = XCreateGC(display, win, GCFunction|GCForeground, &val); 941 | XDrawLine(display, win, gc, x1,y1, x2,y2); 942 | XFreeGC(display, gc); 943 | } 944 | 945 | void k_draw_text(k_context* ctx, int x, int y, BYTE* text, int len, DWORD color, DWORD extra) 946 | { 947 | if(win==0) return; k_clear_redraw(ctx); 948 | x += ctx->client_x; y += ctx->client_y; 949 | k_draw_text_intern(ctx,x,y,text,color>>31?-1:len,(color>>30)&1,(color>>28)&3,(color>>27)&1,(color>>24)&7,color,extra); 950 | } 951 | 952 | BYTE* k_itoa(QWORD n, BYTE* buf, DWORD radix, DWORD width, DWORD trim) 953 | { 954 | static char digit[] = "0123456789ABCDEF"; 955 | *buf = digit[n%radix]; 956 | while((n>=radix||trim==0) && --width>0) 957 | { 958 | n /= radix; *--buf = digit[n%radix]; 959 | } 960 | return buf; 961 | } 962 | 963 | void k_draw_num(k_context* ctx, int x, int y, DWORD color, DWORD options, void* pnum, DWORD extra) 964 | { 965 | static char bases[] = {10,16,2,8}; BYTE buf[64]; buf[63]=0; 966 | DWORD width = (options>>16)&63, radix = bases[(options>>8)&3]; 967 | BYTE* num = k_itoa((options>>30)&1?*(QWORD*)pnum:*(DWORD*)pnum,buf+62,radix,width,(options>>31)&1); 968 | k_draw_text(ctx,x,y,num,-1,color,extra); 969 | } 970 | 971 | #define B5(s1,s2) ((((((*(WORD*)img)>>s1)&31)<<3)|(((*(WORD*)img)>>(s1+5))&7))<>s1)&63)<<2)|(((*(WORD*)img)>>(s1+6))&3))<client_x; y += ctx->client_y; 978 | DWORD* image32 = (DWORD*)malloc(width*height*4),i,j,p; int k; 979 | switch(bpp) 980 | { 981 | case 1: 982 | for(p = i = 0; i < height; ++i,img+=pitch) 983 | for(j = 0; j < width; ++img) 984 | for(k = 7; j < width && k >= 0; ++j,--k,++p) image32[p] = pal32[(*img>>k)&1]; 985 | break; 986 | case 2: 987 | for(p = i = 0; i < height; ++i,img+=pitch) 988 | for(j = 0; j < width; ++img) 989 | for(k = 6; j < width && k >= 0; ++j,k-=2,++p) image32[p] = pal32[(*img>>k)&3]; 990 | break; 991 | case 4: 992 | for(p = i = 0; i < height; ++i,img+=pitch) 993 | for(j = 0; j < width; ++img) 994 | for(k = 4; j < width && k >= 0; ++j,k-=4,++p) image32[p] = pal32[(*img>>k)&15]; 995 | break; 996 | case 8: 997 | for(p = i = 0; i < height; ++i,img+=pitch) 998 | for(j = 0; j < width; ++j,++p,++img) image32[p] = pal32[*img]; 999 | break; 1000 | case 9: 1001 | for(p = i = 0; i < height; ++i,img+=pitch) 1002 | for(j = 0; j < width; ++j,++p,++img) image32[p] = ((*img)<<16)|((*img)<<8)|*img; 1003 | break; 1004 | case 15: 1005 | for(p = i = 0; i < height; ++i,img+=pitch) 1006 | for(j = 0; j < width; ++j,++p,img+=2) image32[p] = B5(10,16)|B5(5,8)|B5(0,0); 1007 | break; 1008 | case 16: 1009 | for(p = i = 0; i < height; ++i,img+=pitch) 1010 | for(j = 0; j < width; ++j,++p,img+=2) image32[p] = B5(11,16)|B6(5,8)|B5(0,0); 1011 | break; 1012 | case 24: 1013 | for(p = i = 0; i < height; ++i,img+=pitch) 1014 | for(j = 0; j < width; ++j,++p,img+=3) image32[p] = 0xffffff & *(DWORD*)img; 1015 | break; 1016 | case 32: 1017 | for(p = i = 0; i < height; ++i,img+=pitch) 1018 | for(j = 0; j < width; ++j,++p,img+=4) image32[p] = 0xffffff & *(DWORD*)img; 1019 | break; 1020 | default: 1021 | k_panic("bpp not supported"); 1022 | } 1023 | XImage* ximg = XCreateImage(display, DefaultVisual(display, 0), 24, ZPixmap, 0, (char*)image32, width, height, 32, 0); 1024 | XPutImage(display, win, DefaultGC(display, 0), ximg, 0,0, x,y, width,height); 1025 | XDestroyImage(ximg); 1026 | } 1027 | 1028 | void k_blit_image(k_context* ctx, DWORD rop, DWORD param) 1029 | { 1030 | K_BLIT_PARAM* bp = user_mem(param); 1031 | BYTE* data = user_mem(bp->src_addr); 1032 | LONG x = bp->dst_x, y = bp->dst_y; 1033 | DWORD w = bp->src_wdst_w ? bp->src_w : bp->dst_w; 1034 | DWORD h = bp->src_hdst_h ? bp->src_h : bp->dst_h; 1035 | if((rop&(1<<29))==0) { x-= ctx->client_x; y-= ctx->client_y; }; 1036 | k_draw_image(ctx,x,y,w,h,data+bp->src_y*bp->src_stride+bp->src_x*4,32,bp->src_stride-w*4,0); 1037 | } 1038 | 1039 | #pragma pack(push,1) 1040 | typedef struct 1041 | { 1042 | DWORD biSize; 1043 | LONG biWidth; 1044 | LONG biHeight; 1045 | WORD biPlanes; 1046 | WORD biBitCount; 1047 | DWORD biCompression; 1048 | DWORD biSizeImage; 1049 | LONG biXPelsPerMeter; 1050 | LONG biYPelsPerMeter; 1051 | DWORD biClrUsed; 1052 | DWORD biClrImportant; 1053 | } BITMAPINFOHEADER; 1054 | 1055 | typedef struct 1056 | { 1057 | BYTE width; 1058 | BYTE height; 1059 | BYTE colors; 1060 | BYTE reserved; 1061 | WORD hot_x; 1062 | WORD hot_y; 1063 | DWORD size; 1064 | DWORD offset; 1065 | } k_icondirentry; 1066 | 1067 | typedef struct 1068 | { 1069 | WORD reserved; 1070 | WORD type; // 1 - ICO, 2 - CUR 1071 | WORD count; 1072 | k_icondirentry entry[1]; 1073 | } k_icondir; 1074 | #pragma pack(pop) 1075 | 1076 | #define LDR(c,s) \ 1077 | for(i=0,p=pi+32*32*s; i<32; ++i) for(j=0; j<4; ++j) for(k=0,m=*p++; k<8; ++k,m<<=1,pi+=s) \ 1078 | bmp[31-i][j*8+k] = (0xFFFFFF&c)|(m&0x80?0:0xFF000000); 1079 | 1080 | DWORD k_cursor_load(k_context* ctx, DWORD addr, DWORD param) 1081 | { 1082 | WORD load_type = param, hx = (param>>24)&255, hy = (param>>16)&255; 1083 | DWORD bmp[32][32],i,j,k,m; 1084 | 1085 | XImage image; memset(&image, 0, sizeof(image)); 1086 | image.width = 32; 1087 | image.height = 32; 1088 | image.depth = 32; 1089 | image.bits_per_pixel = 32; 1090 | image.format = ZPixmap; 1091 | image.byte_order = LSBFirst; 1092 | image.bitmap_unit = 8; 1093 | image.bitmap_bit_order = LSBFirst; 1094 | image.bytes_per_line = 32*4; 1095 | image.red_mask = 0xff; 1096 | image.green_mask = 0xff00; 1097 | image.blue_mask = 0xff0000; 1098 | 1099 | if(load_type<=1) 1100 | { 1101 | void* data = user_mem(addr); 1102 | if(load_type==0) 1103 | { 1104 | char fname[512]; k_parse_name(ctx, data, 0, fname, sizeof(fname)); 1105 | FILE* fp = fopen(fname, "rb"); if(fp==NULL) return 0; 1106 | fseek(fp, 0, SEEK_END); DWORD size = ftell(fp); fseek(fp, 0, SEEK_SET); 1107 | data = malloc(size); fread(data, 1, size, fp); fclose(fp); 1108 | } 1109 | 1110 | k_icondir* pd = data; 1111 | k_icondirentry* pe = pd->entry; hx = pe->hot_x; hy = pe->hot_y; 1112 | BITMAPINFOHEADER* pbmp = (BITMAPINFOHEADER*)(pe->offset+(BYTE*)data); 1113 | 1114 | if(pd->type!=2||pd->count!=1||pe->width!=32||pe->height!=32) 1115 | { k_printf("not supported cursor (%dx%d)\n",pe->width,pe->height); return 0; } 1116 | 1117 | DWORD* ppal = (DWORD*)(pe->offset+pbmp->biSize+(BYTE*)data); 1118 | DWORD clrs = pbmp->biClrUsed!=0 || pbmp->biBitCount>8 ? pbmp->biClrUsed : 1<biBitCount; 1119 | BYTE* pi = (BYTE*)(ppal+clrs),*p; 1120 | switch(pbmp->biBitCount) 1121 | { 1122 | case 1: LDR(ppal[((k&7)==7?*pi++:*pi>>(7-k))&1],1/8); break; 1123 | case 4: LDR(ppal[((k&1)==1?*pi++:*pi>>4)&15],1/2); break; 1124 | case 8: LDR(ppal[*pi],1); break; 1125 | case 24: LDR(*(DWORD*)pi,3); break; 1126 | case 32: LDR(*(DWORD*)pi,4); break; 1127 | default: for(i=0; i<32*32; ++i) bmp[0][i] = 0x80000000; break; 1128 | } 1129 | if(load_type==0) free(data); 1130 | image.data = (char*)bmp; 1131 | } 1132 | else if(load_type==2) 1133 | { 1134 | image.data = user_mem(addr); 1135 | } 1136 | else 1137 | { 1138 | k_printf("not supported cursor loading type (%d)\n", load_type); return 0; 1139 | } 1140 | 1141 | Pixmap pm = XCreatePixmap(display, RootWindow(display, 0), 32, 32, 32); 1142 | GC gc = XCreateGC(display, pm, 0, NULL); 1143 | XPutImage(display, pm, gc, &image, 0, 0, 0, 0, 32, 32); 1144 | XFreeGC(display, gc); 1145 | 1146 | Picture p = XRenderCreatePicture(display, pm, XRenderFindStandardFormat(display, PictStandardARGB32), 0, NULL); 1147 | XFreePixmap(display, pm); 1148 | 1149 | Cursor cur = XRenderCreateCursor(display, p, hx, hy); 1150 | XRenderFreePicture(display, p); 1151 | 1152 | return cur; 1153 | } 1154 | 1155 | DWORD k_cursor_set(k_context* ctx, DWORD handle) 1156 | { 1157 | static DWORD last_cursor_handle = 0; 1158 | DWORD ret = last_cursor_handle; last_cursor_handle = handle; 1159 | if(win!=0) XDefineCursor(display, win, handle); 1160 | return ret; 1161 | } 1162 | 1163 | DWORD k_cursor_delete(k_context* ctx, DWORD handle) 1164 | { 1165 | XFreeCursor(display, handle); 1166 | return 0; 1167 | } 1168 | -------------------------------------------------------------------------------- /k_gui.h: -------------------------------------------------------------------------------- 1 | #pragma pack(push,1) 2 | typedef struct 3 | { 4 | DWORD magic; 5 | DWORD version; 6 | DWORD params; 7 | DWORD buttons; 8 | DWORD bitmaps; 9 | } K_SKIN_HDR; 10 | 11 | typedef struct 12 | { 13 | DWORD inner; 14 | DWORD outer; 15 | DWORD frame; 16 | } K_SKIN_COLORS; 17 | 18 | typedef struct 19 | { 20 | DWORD height; 21 | WORD rmargin; 22 | WORD lmargin; 23 | WORD bmargin; 24 | WORD tmargin; 25 | K_SKIN_COLORS acolor; 26 | K_SKIN_COLORS icolor; 27 | DWORD dtpfsize; 28 | DWORD dtp[10]; 29 | } K_SKIN_PARAMS; 30 | 31 | typedef struct 32 | { 33 | DWORD type; // 0-EOL, 1-close, 2-minimize 34 | SHORT x; 35 | SHORT y; 36 | WORD width; 37 | WORD height; 38 | } K_SKIN_BUTTON; 39 | 40 | typedef struct 41 | { 42 | WORD kind; // 0-EOL, 1-left, 2-oper, 3-base 43 | WORD type; // 0-inactive, 1-active 44 | DWORD offset; 45 | } K_SKIN_BMPDEF; 46 | 47 | typedef struct 48 | { 49 | DWORD width; 50 | DWORD height; 51 | BYTE data[1]; 52 | } K_SKIN_BITMAP; 53 | 54 | typedef struct 55 | { 56 | LONG dst_x; 57 | LONG dst_y; 58 | DWORD dst_w; 59 | DWORD dst_h; 60 | LONG src_x; 61 | LONG src_y; 62 | DWORD src_w; 63 | DWORD src_h; 64 | DWORD src_addr; 65 | DWORD src_stride; 66 | } K_BLIT_PARAM; 67 | #pragma pack(pop) 68 | 69 | typedef struct 70 | { 71 | BYTE width; 72 | BYTE height; 73 | WORD chars; 74 | BYTE* bmp; 75 | } k_bitmap_font; 76 | 77 | extern k_bitmap_font font9,font16; 78 | 79 | void k_gui_init(); 80 | void k_process_event(k_context* ctx); 81 | void k_move_mouse(int x, int y); 82 | void k_move_window(k_context* ctx, int x, int y); 83 | void k_move_size_window(k_context* ctx, int x, int y, int width, int height); 84 | void k_raise_window(k_context* ctx); 85 | void k_window(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color, DWORD titleaddr); 86 | void k_set_title(k_context* ctx, DWORD titleaddr, int cp); 87 | void k_draw_pixel(k_context* ctx, int x, int y, DWORD color); 88 | void k_draw_button(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color); 89 | void k_draw_rect(k_context* ctx, int x, int y, DWORD width, DWORD height, DWORD color); 90 | void k_draw_line(k_context* ctx, int x1, int y1, int x2, int y2, DWORD color); 91 | void k_draw_text(k_context* ctx, int x, int y, BYTE* text, int len, DWORD color, DWORD extra); 92 | void k_draw_num(k_context* ctx, int x, int y, DWORD color, DWORD options, void* pnum, DWORD extra); 93 | void k_draw_image(k_context* ctx, int x, int y, DWORD width, DWORD height, BYTE* img, DWORD bpp, DWORD pitch, DWORD* pal32); 94 | void k_blit_image(k_context* ctx, DWORD rop, DWORD param); 95 | void k_get_screen_size(DWORD* width, DWORD* height); 96 | void k_get_desktop_rect(DWORD* left, DWORD* top, DWORD* right, DWORD* bottom); 97 | void k_set_desktop_rect(WORD left, WORD top, WORD right, WORD bottom); 98 | DWORD k_get_pixel(k_context* ctx, int x, int y); 99 | void k_get_image(k_context* ctx, int x, int y, DWORD width, DWORD height, BYTE* img); 100 | 101 | void k_set_skin(BYTE* skin); 102 | DWORD k_get_skin_height(); 103 | void k_get_skin_colors(BYTE* buf, DWORD size); 104 | void k_get_client_rect(k_context* ctx, DWORD* x, DWORD* y, DWORD* w, DWORD* h); 105 | 106 | DWORD k_cursor_load(k_context* ctx, DWORD addr, DWORD param); 107 | DWORD k_cursor_set(k_context* ctx, DWORD handle); 108 | DWORD k_cursor_delete(k_context* ctx, DWORD handle); 109 | -------------------------------------------------------------------------------- /k_iconv.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_iconv.h" 3 | 4 | #include 5 | 6 | DWORD ic_get_cp866(BYTE** p) 7 | { 8 | DWORD ch = *(*p)++; if(ch<0x80) return ch; 9 | if(ch<0xB0) return ch+0x410-0x80; 10 | if(ch<0xE0) return '?'; 11 | if(ch<0xF0) return ch+0x440-0xE0; 12 | if(ch==0xF0) return 0x401; 13 | if(ch==0xF1) return 0x451; 14 | return '?'; 15 | } 16 | 17 | DWORD ic_put_cp866(BYTE* p, DWORD ch) 18 | { 19 | if(ch<0x80) *p = ch; else 20 | if(ch==0x401) *p = 0xF0; else 21 | if(ch<0x410) *p = '?'; else 22 | if(ch<0x440) *p = ch-0x410+0x80; else 23 | if(ch<0x450) *p = ch-0x440+0xE0; else 24 | if(ch==0x451) *p = 0xF1; else 25 | *p='?'; 26 | return 1; 27 | } 28 | 29 | DWORD ic_get_utf8(BYTE** p) 30 | { 31 | DWORD ch = *(*p)++,x=ch; if(ch<0x80) return ch; 32 | if(ch<0xC0||ch>=0xF8) return '?'; else ch &= 0x1F; 33 | for(;x&0x40;x<<=1) ch = (ch<<6)|((*(*p)++)&0x3F); 34 | return ch; 35 | } 36 | 37 | DWORD ic_put_utf8(BYTE* p, DWORD ch) 38 | { 39 | if(ch<0x80) { *p = ch; return 1; } 40 | if(ch<0x800) { *p++ = (ch>>6)|0xC0; *p = (ch&0x3F)|0x80; return 2; } 41 | if(ch<0x10000) { *p++ = (ch>>12)|0xC0; *p++ = ((ch>>6)&0x3F)|0x80; *p = (ch&0x3F)|0x80; return 3; } 42 | *p++ = (ch>>18)|0xC0; *p++ = ((ch>>12)&0x3F)|0x80; *p++ = ((ch>>6)&0x3F)|0x80; *p = (ch&0x3F)|0x80; 43 | return 4; 44 | } 45 | 46 | DWORD ic_get_utf16le(BYTE** p) 47 | { 48 | DWORD ch = *(WORD*)*p; *p += 2; 49 | return ch; 50 | } 51 | 52 | DWORD ic_put_utf16le(BYTE* p, DWORD ch) 53 | { 54 | *(WORD*)p = ch; 55 | return 2; 56 | } 57 | 58 | static DWORD (*ic_get[])(BYTE**) = {ic_get_cp866, ic_get_cp866, ic_get_utf16le, ic_get_utf8}; 59 | static DWORD (*ic_put[])(BYTE*,DWORD) = {ic_put_cp866, ic_put_cp866, ic_put_utf16le, ic_put_utf8}; 60 | 61 | DWORD k_strlen(BYTE* src, int src_cp) 62 | { 63 | DWORD len; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++; 64 | DWORD (*get)(BYTE**) = ic_get[src_cp&3]; 65 | for(len=0; get(&src); ++len); 66 | return len; 67 | } 68 | 69 | DWORD k_strsize(BYTE* src, int src_cp, int dst_cp) 70 | { 71 | DWORD ch,size=0; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++; 72 | DWORD (*get)(BYTE**) = ic_get[src_cp&3]; 73 | DWORD (*put)(BYTE*,DWORD) = ic_put[(dst_cp<0?src_cp:dst_cp)&3]; 74 | BYTE tmp[8]; for(ch=1;ch;) size += put(tmp, ch=get(&src)); 75 | if(dst_cp<0 && src_cp>0) ++size; 76 | return size; 77 | } 78 | 79 | BYTE* k_strncpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp, DWORD maxlen) 80 | { 81 | DWORD ch; if(src_cp<0) src_cp = *src==0||*src>3 ? 0 : *src++; 82 | DWORD (*get)(BYTE**) = ic_get[src_cp&3]; 83 | DWORD (*put)(BYTE*,DWORD) = ic_put[(dst_cp<0?src_cp:dst_cp)&3]; 84 | if(dst_cp<0 && src_cp>0) *dst++ = src_cp; 85 | for(;maxlen>0 && (ch=get(&src))!=0;--maxlen) dst += put(dst, ch); put(dst, 0); 86 | return dst; 87 | } 88 | 89 | BYTE* k_strcpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp) 90 | { 91 | return k_strncpy(dst,dst_cp,src,src_cp,-1); 92 | } 93 | 94 | BYTE* k_strdup(BYTE* src, int src_cp, int dst_cp) 95 | { 96 | BYTE* dst = malloc(k_strsize(src,src_cp,dst_cp)); 97 | k_strncpy(dst,dst_cp,src,src_cp,-1); 98 | return dst; 99 | } 100 | -------------------------------------------------------------------------------- /k_iconv.h: -------------------------------------------------------------------------------- 1 | DWORD k_strlen(BYTE* src, int src_cp); 2 | DWORD k_strsize(BYTE* src, int src_cp, int dst_cp); 3 | BYTE* k_strdup(BYTE* src, int src_cp, int dst_cp); 4 | BYTE* k_strcpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp); 5 | BYTE* k_strncpy(BYTE* dst, int dst_cp, BYTE* src, int src_cp, DWORD maxlen); 6 | -------------------------------------------------------------------------------- /k_ipc.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_gui.h" 4 | #include "k_ipc.h" 5 | 6 | #include 7 | #include 8 | 9 | int ipc_server = -1; 10 | 11 | int read_msg(int fd, msg_t* msg) 12 | { 13 | int len = sizeof(DWORD); 14 | BYTE *buf = (BYTE*)msg, *p = buf; 15 | while(p=sizeof(msg->len)) len = msg->len; 19 | } 20 | return 1; 21 | } 22 | 23 | int write_msg(int fd, msg_t* msg) 24 | { 25 | int len = msg->len; 26 | BYTE *buf = (BYTE*)msg, *p=buf; 27 | while(pipc_buffer; 38 | do 39 | { 40 | read_msg(ipc_server, msg); 41 | switch(msg->type) 42 | { 43 | case MSGTYPE_REPLY: ctx->retcode = msg->u.reply.retcode; return; 44 | case MSGTYPE_IPC: 45 | switch(state) 46 | { 47 | case 0: 48 | switch(msg->u.ipc.code) 49 | { 50 | case IPCCODE_DATA: 51 | if(pdw == NULL) err = 1; else 52 | if(pdw[0] != 0) err = 2; else 53 | if(pdw[1]+msg->u.ipc.len+8 > ctx->ipc_buf_len) err = 3; else 54 | { 55 | err = 0; state = 1; 56 | *(DWORD*)(ctx->ipc_buffer+pdw[1]) = g_slot[msg->u.ipc.from_slot].tid; pdw[1] += 4; 57 | *(DWORD*)(ctx->ipc_buffer+pdw[1]) = msg->u.ipc.len; pdw[1] += 4; 58 | } 59 | msg_ipc(msg, msg->u.ipc.from_slot, err, 0, NULL); 60 | write_msg(ipc_server, msg); 61 | break; 62 | case IPCCODE_ACTIVATE: 63 | k_raise_window(ctx); 64 | break; 65 | case IPCCODE_EVENT: 66 | switch(msg->u.ipc_event.type) 67 | { 68 | case 2: k_event_keypress(ctx, msg->u.ipc_event.param<<8); break; 69 | case 3: ctx->button_id = msg->u.ipc_event.param; ctx->event_pending |= K_EVMASK_BUTTON; break; 70 | } 71 | break; 72 | } 73 | break; 74 | case 1: 75 | memcpy(ctx->ipc_buffer+pdw[1], msg->u.ipc.data, msg->u.ipc.len); pdw[1] += msg->u.ipc.len; 76 | if(msg->u.ipc.code!=IPCCODE_DATA) 77 | { 78 | msg_ipc(msg, msg->u.ipc.from_slot, 0, 0, NULL); 79 | write_msg(ipc_server, msg); 80 | k_event_ipc(ctx); state = 0; 81 | } 82 | break; 83 | } 84 | break; 85 | case MSGTYPE_LOAD_SKIN: 86 | k_set_skin(k_skin_open()); 87 | k_event_redraw(ctx); 88 | break; 89 | } 90 | } 91 | while(state != 0); 92 | } 93 | 94 | void msg_run(msg_t* msg, char* fname, char* args) 95 | { 96 | msg->len = strlen(fname)+7; 97 | msg->type = MSGTYPE_RUN; 98 | msg->u.run.args = 0; 99 | strcpy(msg->u.run.buf, fname); 100 | if(args) 101 | { 102 | msg->u.run.args = msg->len-6; 103 | strcpy(msg->u.run.buf+msg->u.run.args, args); 104 | msg->len += strlen(args)+1; 105 | } 106 | } 107 | 108 | void msg_clone(msg_t* msg, DWORD slot, DWORD eip, DWORD esp) 109 | { 110 | msg->len = sizeof(msg_clone_t)+4; 111 | msg->type = MSGTYPE_CLONE; 112 | msg->u.clone.slot = slot; 113 | msg->u.clone.eip = eip; 114 | msg->u.clone.esp = esp; 115 | } 116 | 117 | void msg_reply(msg_t* msg, int retcode) 118 | { 119 | msg->len = sizeof(msg_reply_t)+4; 120 | msg->type = MSGTYPE_REPLY; 121 | msg->u.reply.retcode = retcode; 122 | } 123 | 124 | void msg_ipc(msg_t* msg, DWORD slot, DWORD code, DWORD len, BYTE* data) 125 | { 126 | msg->len = 20; 127 | msg->type = MSGTYPE_IPC; 128 | msg->u.ipc.to_slot = slot; 129 | msg->u.ipc.code = code; 130 | msg->u.ipc.len = len; 131 | if(len!=0 && data!=NULL) 132 | { 133 | msg->len += len; 134 | memcpy(msg->u.ipc.data, data, len); 135 | } 136 | } 137 | 138 | void msg_ipc_event(msg_t* msg, DWORD slot, DWORD type, DWORD param) 139 | { 140 | msg->len = sizeof(msg_ipc_event_t)+4; 141 | msg->type = MSGTYPE_IPC; 142 | msg->u.ipc_event.to_slot = slot; 143 | msg->u.ipc_event.code = IPCCODE_EVENT; 144 | msg->u.ipc_event.type = type; 145 | msg->u.ipc_event.param = param; 146 | } 147 | 148 | void msg_focus_in(msg_t* msg, DWORD slot) 149 | { 150 | msg->len = sizeof(msg_focus_t)+4; 151 | msg->type = MSGTYPE_GOT_FOCUS; 152 | msg->u.focus.slot = slot; 153 | } 154 | 155 | void msg_load_skin(msg_t* msg, char* fname) 156 | { 157 | msg->len = 4; 158 | msg->type = MSGTYPE_LOAD_SKIN; 159 | if(fname) 160 | { 161 | msg->len += strlen(fname)+3; 162 | strcpy(msg->u.run.buf, fname); 163 | } 164 | } 165 | 166 | void msg_driver_load(msg_t* msg, char* name) 167 | { 168 | msg->len = strlen(name)+7; 169 | msg->type = MSGTYPE_DRV_LOAD; 170 | strcpy(msg->u.run.buf, name); 171 | } 172 | 173 | void msg_driver_ioctl(msg_t* msg, DWORD shmid, DWORD* args) 174 | { 175 | msg->len = sizeof(msg_ioctl_t)+4; 176 | msg->type = MSGTYPE_DRV_IOCTL; 177 | msg->u.ioctl.shmid = shmid; 178 | msg->u.ioctl.handle = args[0]; 179 | msg->u.ioctl.code = args[1]; 180 | msg->u.ioctl.iaddr = args[2]; 181 | msg->u.ioctl.ilen = args[3]; 182 | msg->u.ioctl.oaddr = args[4]; 183 | msg->u.ioctl.olen = args[5]; 184 | } 185 | 186 | void k_focus_in(k_context* ctx) 187 | { 188 | msg_t msg; 189 | msg_focus_in(&msg, ctx-g_slot); 190 | write_msg(ipc_server, &msg); 191 | } 192 | -------------------------------------------------------------------------------- /k_ipc.h: -------------------------------------------------------------------------------- 1 | #pragma pack(push,1) 2 | typedef struct 3 | { 4 | WORD args; 5 | char buf[4096-6]; 6 | } msg_run_t; 7 | 8 | typedef struct 9 | { 10 | DWORD slot; 11 | DWORD eip; 12 | DWORD esp; 13 | } msg_clone_t; 14 | 15 | typedef struct 16 | { 17 | int retcode; 18 | } msg_reply_t; 19 | 20 | typedef struct 21 | { 22 | DWORD from_slot; 23 | DWORD to_slot; 24 | DWORD code; 25 | DWORD len; 26 | BYTE data[4096-20]; 27 | } msg_ipc_t; 28 | 29 | typedef struct 30 | { 31 | DWORD from_slot; 32 | DWORD to_slot; 33 | DWORD code; 34 | DWORD type; 35 | DWORD param; 36 | } msg_ipc_event_t; 37 | 38 | typedef struct 39 | { 40 | DWORD slot; 41 | } msg_focus_t; 42 | 43 | typedef struct 44 | { 45 | DWORD shmid; 46 | DWORD handle; 47 | DWORD code; 48 | DWORD iaddr; 49 | DWORD ilen; 50 | DWORD oaddr; 51 | DWORD olen; 52 | } msg_ioctl_t; 53 | 54 | typedef struct 55 | { 56 | WORD len; 57 | WORD type; 58 | union 59 | { 60 | msg_run_t run; 61 | msg_clone_t clone; 62 | msg_reply_t reply; 63 | msg_ipc_t ipc; 64 | msg_ipc_event_t ipc_event; 65 | msg_focus_t focus; 66 | msg_ioctl_t ioctl; 67 | } u; 68 | } msg_t; 69 | #pragma pack(pop) 70 | 71 | extern int ipc_server; 72 | 73 | #define MSGTYPE_RUN 1 74 | #define MSGTYPE_CLONE 2 75 | #define MSGTYPE_REPLY 3 76 | #define MSGTYPE_IPC 4 77 | #define MSGTYPE_GOT_FOCUS 5 78 | #define MSGTYPE_LOAD_SKIN 6 79 | #define MSGTYPE_DRV_LOAD 7 80 | #define MSGTYPE_DRV_IOCTL 8 81 | 82 | #define IPCCODE_DATA 256 83 | #define IPCCODE_ACTIVATE 257 84 | #define IPCCODE_EVENT 258 85 | 86 | int read_msg(int fd, msg_t* msg); 87 | int write_msg(int fd, msg_t* msg); 88 | void k_process_ipc_event(k_context* ctx, msg_t* msg); 89 | void k_focus_in(k_context* ctx); 90 | 91 | void msg_run(msg_t* msg, char* name, char* args); 92 | void msg_clone(msg_t* msg, DWORD slot, DWORD eip, DWORD esp); 93 | void msg_reply(msg_t* msg, int retcode); 94 | void msg_ipc(msg_t* msg, DWORD slot, DWORD code, DWORD len, BYTE* data); 95 | void msg_ipc_event(msg_t* msg, DWORD slot, DWORD type, DWORD param); 96 | void msg_load_skin(msg_t* msg, char* fname); 97 | void msg_driver_load(msg_t* msg, char* name); 98 | void msg_driver_ioctl(msg_t* msg, DWORD shmid, DWORD* args); 99 | -------------------------------------------------------------------------------- /k_mem.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int modify_ldt(int func, void* ptr, unsigned long bytecount); 12 | 13 | #define HEAP_BLOCK_SIZE 0x100000 14 | 15 | #define HTAG_NONE 0x00 16 | #define HTAG_SZMASK 0x0F 17 | #define HTAG_BIGSZ 0x0F 18 | #define HTAG_NORMAL 0x10 19 | #define HTAG_FREE 0x20 20 | #define HTAG_PARAM 0x80 21 | 22 | #define KERNEL_SHMEM "/kolibri.kmem" 23 | #define KERNEL_MEM_BASE (void*)0x10000000 24 | #define KERNEL_MEM_SIZE ((sizeof(KERNEL_MEM)+0xFFF)&-0x1000) 25 | 26 | #define SKIN_SHMEM "/kolibri.skin" 27 | #define SKIN_BASE (void*)0x11000000 28 | 29 | #define TLS_BASE (void*)0x11FFF000L 30 | #define TLS_SIZE 0x1000 31 | 32 | #define CLIPBOARD_SHMEM "/kolibri.clip.%d" 33 | #define CLIPBOARD_BASE (void*)0x12000000 34 | 35 | #define HCTRL_SHMEM "/kolibri.heap.%d" 36 | #define HCTRL_MEM_BASE (void*)0x1FFC0000 37 | #define HCTRL_MEM_MAXSIZE 0x40000 38 | 39 | #define APP_SHMEM "/kolibri.app.%d" 40 | #define KEX_BASE (void*)0x20000000L 41 | #define KEX_SIZE 0x40000000L 42 | 43 | #define STUB_MEM_BASE (void*)0x5FFFF000 44 | #define STUB_MEM_SIZE 0x1000 45 | 46 | #define USER_SHMEM "/kolibri.usm.%d" 47 | #define USER_SHMEM_START 0x3F000000 48 | 49 | KERNEL_MEM* k_kernel_mem = NULL; 50 | 51 | BYTE* k_base = NULL; DWORD k_base_size = 0, k_shmid = 0; 52 | BYTE* k_heap_map = NULL; DWORD k_heap_map_size; 53 | BYTE* k_skin_data = NULL; DWORD k_skin_size; 54 | BYTE* k_stub = NULL; BYTE* k_tls_base = NULL; 55 | 56 | char _init_keyboard_layout[3][128]={ 57 | "6\x1B" 58 | "1234567890-=\x8\x9" 59 | "qwertyuiop[]\xD" 60 | "~asdfghjkl;\x27\x60\x0\\zxcvbnm,./\x0\x34\x35 " 61 | "@234567890123\xB4\xB2\xB8\x36\xB0\x37" 62 | "\xB3\x38\xB5\xB1\xB7\xB9\xB6" 63 | "AB?\x0\x34\x35 " 70 | "@234567890123\xB4\xB2\xB8\x36\xB0\x37" 71 | "\xB3\x38\xB5\xB1\xB7\xB9\xB6" 72 | "AB>D\377FGHIJKLMNOPQRSTUVWXYZ" 73 | "ABCDEFGHIJKLMNOPQR", 74 | 75 | " \x1B" 76 | " @ $ {[]}\\ \x8\x9" 77 | " \xD" 78 | " \x0 \x0\x34\x0 " 79 | " \xB4\xB2\xB8\x36\xB0\x37" 80 | "\xB3\x38\xB5\xB1\xB7\xB9\xB6" 81 | "ABCD\377FGHIJKLMNOPQRSTUVWXYZ" 82 | "ABCDEFGHIJKLMNOPQR" 83 | }; 84 | 85 | void* k_shmem_open(char* name, int shmid, void* base, DWORD size, int prot, DWORD* psize) 86 | { 87 | char buf[64]; sprintf(buf, name, shmid); int fd; 88 | if (psize != NULL) 89 | { 90 | fd = shm_open(buf, O_RDWR, 0660); if(fd < 0) return NULL; 91 | struct stat st; fstat(fd, &st); *psize = size = st.st_size; 92 | } 93 | else 94 | { 95 | fd = shm_open(buf, O_CREAT|O_RDWR, 0660); 96 | ftruncate(fd, size); 97 | } 98 | void* ret = mmap(base, size, PROT_READ|PROT_WRITE|prot, MAP_SHARED|MAP_FIXED, fd, 0); 99 | close(fd); return ret; 100 | } 101 | 102 | void* k_shmem_resize(char* name, int shmid, void* base, DWORD oldsize, DWORD size) 103 | { 104 | char buf[64]; sprintf(buf, name, shmid); 105 | int fd = shm_open(buf, O_RDWR, 0660); ftruncate(fd, size); 106 | void* ret = mremap(base, oldsize, size, 0); 107 | close(fd); return ret; 108 | } 109 | 110 | void k_shmem_unlink(char* name, int shmid) 111 | { 112 | char buf[64]; sprintf(buf, name, shmid); shm_unlink(buf); 113 | } 114 | 115 | void k_modify_ldt() 116 | { 117 | struct user_desc ldt_code = {1, (unsigned long)k_base, KEX_SIZE>>12, 1, MODIFY_LDT_CONTENTS_CODE, 0, 1, 0, 1}; 118 | struct user_desc ldt_data = {2, (unsigned long)k_base, KEX_SIZE>>12, 1, MODIFY_LDT_CONTENTS_DATA, 0, 1, 0, 1}; 119 | struct user_desc ldt_tls = {3, (unsigned long)k_tls_base, TLS_SIZE>>12, 1, MODIFY_LDT_CONTENTS_DATA, 0, 1, 0, 1}; 120 | 121 | modify_ldt(1, &ldt_code, sizeof(ldt_code)); 122 | modify_ldt(1, &ldt_data, sizeof(ldt_data)); 123 | modify_ldt(1, &ldt_tls, sizeof(ldt_tls)); 124 | } 125 | 126 | void k_kernel_mem_open() 127 | { 128 | k_kernel_mem = (KERNEL_MEM*)k_shmem_open(KERNEL_SHMEM, k_shmid, KERNEL_MEM_BASE, KERNEL_MEM_SIZE, 0, NULL); 129 | } 130 | 131 | void k_kernel_mem_init() 132 | { 133 | k_kernel_mem_open(); 134 | memset(k_kernel_mem, 0, sizeof(KERNEL_MEM)); 135 | memcpy(k_kernel_mem->keyboard_layout, _init_keyboard_layout, sizeof(_init_keyboard_layout)); 136 | k_kernel_mem->keyboard_country = 1; 137 | k_kernel_mem->keyboard_language = 1; 138 | k_kernel_mem->mouse_dbl_click_delay = 50; 139 | k_kernel_mem->pci_enabled = 1; 140 | } 141 | 142 | void k_kernel_mem_cleanup() 143 | { 144 | k_shmem_unlink(KERNEL_SHMEM, k_shmid); 145 | k_shmem_unlink(SKIN_SHMEM, k_shmid); 146 | } 147 | 148 | KERNEL_MEM* kernel_mem() 149 | { 150 | return k_kernel_mem; 151 | } 152 | 153 | void* user_mem(DWORD addr) 154 | { 155 | return k_base+addr; 156 | } 157 | 158 | void k_mem_init(int shmid) 159 | { 160 | k_shmid = shmid; 161 | k_kernel_mem_open(); 162 | k_stub = (BYTE*)mmap(STUB_MEM_BASE, STUB_MEM_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); 163 | k_tls_base = (BYTE*)mmap(TLS_BASE, TLS_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); 164 | } 165 | 166 | BYTE* k_mem_open_app(int shmid, DWORD* psize) 167 | { 168 | void* ptr = k_shmem_open(APP_SHMEM, shmid, KEX_BASE, 0, 0, psize); 169 | return ptr==MAP_FAILED ? NULL : ptr; 170 | } 171 | 172 | void k_mem_close_app(void* ptr, DWORD size) 173 | { 174 | munmap(ptr, size); 175 | } 176 | 177 | void k_mem_done(int shmid) 178 | { 179 | k_shmem_unlink(APP_SHMEM, shmid); 180 | k_shmem_unlink(HCTRL_SHMEM, shmid); 181 | } 182 | 183 | void k_mem_reopen() 184 | { 185 | k_base = k_shmem_open(APP_SHMEM, k_shmid, KEX_BASE, 0, PROT_EXEC, &k_base_size); 186 | k_heap_map = (BYTE*)k_shmem_open(HCTRL_SHMEM, k_shmid, HCTRL_MEM_BASE, 0, 0, &k_heap_map_size); 187 | k_modify_ldt(); 188 | } 189 | 190 | void* k_mem_alloc(DWORD size) 191 | { 192 | void* ptr; DWORD pages = ((size-1)>>12)+1; size = pages << 12; 193 | 194 | if (size <= k_base_size) return k_base; 195 | 196 | if (k_base == NULL) 197 | { 198 | ptr = k_shmem_open(APP_SHMEM, k_shmid, KEX_BASE, size, PROT_EXEC, NULL); 199 | if(ptr != MAP_FAILED) memset(ptr, 0, size); 200 | } 201 | else 202 | { 203 | ptr = k_shmem_resize(APP_SHMEM, k_shmid, k_base, k_base_size, size); 204 | if(ptr != MAP_FAILED) memset(k_base_size+(BYTE*)ptr, 0, size-k_base_size); 205 | } 206 | 207 | if (ptr != MAP_FAILED) 208 | { 209 | k_base = (BYTE*)ptr; k_base_size = size; k_modify_ldt(); 210 | } 211 | 212 | return ptr; 213 | } 214 | 215 | void* k_mem_alloc_from_heap(DWORD size) 216 | { 217 | DWORD addr = k_heap_alloc(size); 218 | return addr==0 ? NULL : k_base+addr; 219 | } 220 | 221 | void k_heap_set_param(BYTE* map, DWORD param) 222 | { 223 | map[0] = HTAG_PARAM|(param&0x7F); 224 | map[1] = HTAG_PARAM|((param>>7)&0x7F); 225 | map[2] = HTAG_PARAM|((param>>14)&0x7F); 226 | } 227 | 228 | void k_heap_clr_param(BYTE* map) 229 | { 230 | map[0] = HTAG_NONE; 231 | map[1] = HTAG_NONE; 232 | map[2] = HTAG_NONE; 233 | } 234 | 235 | DWORD k_heap_get_param(BYTE* map) 236 | { 237 | return ((map[2]&0x7F)<<14)|((map[1]&0x7F)<<7)|(map[0]&0x7F); 238 | } 239 | 240 | DWORD k_heap_get_pcount(BYTE* map) 241 | { 242 | DWORD pages = *map&HTAG_SZMASK; 243 | return pages < HTAG_BIGSZ ? pages : k_heap_get_param(map+1); 244 | } 245 | 246 | void k_heap_mark(BYTE tag, BYTE* map, DWORD pages) 247 | { 248 | if (tag == HTAG_NONE) 249 | { 250 | if (*map != HTAG_NONE) 251 | { 252 | pages = *map&HTAG_SZMASK; *map = HTAG_NONE; 253 | if (pages == HTAG_BIGSZ) 254 | { 255 | pages = k_heap_get_param(map+1); 256 | k_heap_clr_param(map+1); 257 | k_heap_clr_param(map+pages-3); 258 | } 259 | else 260 | { 261 | map[pages-1] = HTAG_NONE; 262 | } 263 | } 264 | } 265 | else 266 | { 267 | if (pages < HTAG_BIGSZ) 268 | { 269 | map[0] = tag|pages; 270 | if (tag==HTAG_FREE) map[pages-1] = tag|pages; 271 | } 272 | else 273 | { 274 | map[0] = tag|HTAG_BIGSZ; 275 | k_heap_set_param(map+1, pages); 276 | if (tag==HTAG_FREE) k_heap_set_param(map+pages-3, pages); 277 | } 278 | } 279 | } 280 | 281 | BYTE* k_heap_find_free(DWORD pages) 282 | { 283 | BYTE* map; DWORD pmax = k_base_size>>12; 284 | for(map = k_heap_map; map < k_heap_map+pmax; map += k_heap_get_pcount(map)) 285 | { 286 | if (*map == HTAG_NONE) 287 | { 288 | return map+pages <= k_heap_map+pmax ? map : NULL; 289 | } 290 | if ((*map&HTAG_FREE)!=0 && k_heap_get_pcount(map)>=pages) 291 | { 292 | return map; 293 | } 294 | } 295 | return NULL; 296 | } 297 | 298 | void k_heap_setsize(DWORD size) 299 | { 300 | DWORD pcount = ((size>>12)+0xFFF)&-0x1000; 301 | if (k_heap_map == NULL) 302 | { 303 | k_heap_map = (BYTE*)k_shmem_open(HCTRL_SHMEM, k_shmid, HCTRL_MEM_BASE, pcount, 0, NULL); 304 | memset(k_heap_map, 0, pcount); 305 | k_heap_mark(HTAG_NORMAL, k_heap_map, k_base_size>>12); 306 | k_heap_map_size = pcount; 307 | } 308 | else if(pcount>k_heap_map_size) 309 | { 310 | k_heap_map = (BYTE*)k_shmem_resize(HCTRL_SHMEM, k_shmid, k_heap_map, k_heap_map_size, pcount); 311 | memset(k_heap_map+k_heap_map_size, 0, pcount-k_heap_map_size); 312 | k_heap_map_size = pcount; 313 | } 314 | k_mem_alloc(size); 315 | } 316 | 317 | DWORD k_mem_size(DWORD size) 318 | { 319 | if (k_heap_map!=NULL) return 1; 320 | return k_mem_alloc(size)==MAP_FAILED ? 1 : 0; 321 | } 322 | 323 | DWORD k_mem_get_size() 324 | { 325 | DWORD i; if(k_heap_map==NULL) return k_base_size; 326 | for(i=(k_base_size>>12)-1; i>0 && k_heap_map[i]==0; --i); 327 | if(k_heap_map[i]&HTAG_NORMAL) i += k_heap_map[i]&HTAG_SZMASK; else ++i; 328 | return i<<12; 329 | } 330 | 331 | DWORD k_heap_init() 332 | { 333 | if (k_heap_map == NULL) k_heap_setsize(((k_base_size-1)|(HEAP_BLOCK_SIZE-1))+1); 334 | return k_base_size; 335 | } 336 | 337 | DWORD k_heap_alloc_noclear(DWORD size) 338 | { 339 | if (size==0) return 0; 340 | if (k_heap_map == NULL) k_heap_init(); 341 | DWORD pages = ((size-1)>>12)+1; 342 | BYTE* map = k_heap_find_free(pages); 343 | if (map == NULL) 344 | { 345 | DWORD hbs = ((size-1)|(HEAP_BLOCK_SIZE-1))+1; 346 | k_heap_setsize(k_base_size+hbs); 347 | map = k_heap_find_free(pages); 348 | if(map == NULL) return 0; 349 | } 350 | if (*map == HTAG_NONE) 351 | { 352 | k_heap_mark(HTAG_NORMAL, map, pages); 353 | } 354 | else 355 | { 356 | DWORD pfree = k_heap_get_pcount(map)-pages; 357 | k_heap_mark(HTAG_NONE, map, 0); 358 | k_heap_mark(HTAG_NORMAL, map, pages); 359 | if (pfree>0) k_heap_mark(HTAG_FREE, map+pages, pfree); 360 | } 361 | return (map-k_heap_map)<<12; 362 | } 363 | 364 | DWORD k_heap_alloc(DWORD size) 365 | { 366 | DWORD addr = k_heap_alloc_noclear(size); 367 | if(addr) memset(user_mem(addr), 0, size); 368 | return addr; 369 | } 370 | 371 | DWORD k_heap_free(DWORD addr) 372 | { 373 | if (addr==0 || addr >= k_base_size) return 0; 374 | BYTE* map = k_heap_map + (addr>>12); 375 | if ((*map&HTAG_NORMAL)==0) return 0; 376 | DWORD pages = k_heap_get_pcount(map); 377 | k_heap_mark(HTAG_NONE, map, 0); 378 | if ((map[pages]&HTAG_FREE)!=0) 379 | { 380 | DWORD p2 = k_heap_get_pcount(map+pages); 381 | k_heap_mark(HTAG_NONE, map+pages, 0); 382 | pages += p2; 383 | } 384 | if ((map[-1]&HTAG_FREE)!=0) 385 | { 386 | DWORD p1 = map[-1]&HTAG_SZMASK; map -= p1; 387 | k_heap_mark(HTAG_NONE, map, 0); 388 | pages += p1; 389 | } 390 | else if ((map[-1]&HTAG_PARAM)!=0) 391 | { 392 | DWORD p1 = k_heap_get_param(map-3); map -= p1; 393 | k_heap_mark(HTAG_NONE, map, 0); 394 | pages += p1; 395 | } 396 | k_heap_mark(HTAG_FREE, map, pages); 397 | return 1; 398 | } 399 | 400 | DWORD k_heap_realloc(DWORD addr, DWORD size) 401 | { 402 | if (addr==0) return k_heap_alloc(size); 403 | if (size==0 || addr >= k_base_size) return 0; 404 | BYTE* map = k_heap_map + (addr>>12); 405 | if ((*map&HTAG_NORMAL)==0) return 0; 406 | DWORD oldpages = k_heap_get_pcount(map); 407 | DWORD oldsize = oldpages<<12; 408 | if (size>0 && size>12)+1; 411 | if(pages==oldpages) return addr; 412 | k_heap_mark(HTAG_NONE, map, 0); 413 | k_heap_mark(HTAG_NORMAL, map, pages); 414 | k_heap_mark(HTAG_FREE, map+pages, oldpages-pages); 415 | return addr; 416 | } 417 | else 418 | { 419 | k_heap_free(addr); if(size==0) return 0; 420 | DWORD newaddr = k_heap_alloc_noclear(size); 421 | if (newaddr==0) return 0; 422 | if (newaddr==addr) return addr; 423 | memmove(k_base+newaddr, k_base+addr, size=k_base_size) return -1; 436 | int i; char* pname = user_mem(aname); 437 | k_user_shm* usm = k_kernel_mem->usm; 438 | for(i=0; iusm; 445 | int i; for(i=0; i=0 && (flags&USM_CREATE)!=0) return 10; 454 | k_user_shm* usm = k_kernel_mem->usm; int clr = (id<0); 455 | if(id<0) { 456 | id = k_find_free_usm(); if(id<0) return 30; 457 | strncpy(usm[id].name, user_mem(aname), 31); usm[id].flags = flags; 458 | } 459 | else 460 | { 461 | if((USM_WRITE&flags&~usm[id].flags)!=0) return 10; 462 | } 463 | for(i=0; iusm_addr[i]!=0 && ctx->usm_addr[i]+ctx->usm_size[i]>top) top = ctx->usm_addr[i]+ctx->usm_size[i]; 464 | BYTE* ptr = top+k_base; size = ((size-1)|0xFFF)+1; 465 | ptr = k_shmem_open(USER_SHMEM, id, ptr, size, 0, (flags&(USM_CREATE|USM_OPEN_ALWAYS))!=0 ? NULL : &size); 466 | ctx->usm_size[id] = size; 467 | ctx->usm_addr[id] = *addr = ptr-k_base; 468 | usm[id].tcount++; 469 | if(clr) memset(ptr, 0, size); 470 | return 0; 471 | } 472 | 473 | DWORD k_usm_close(k_context* ctx, DWORD aname) 474 | { 475 | int id = k_find_usm(aname); if (id<0) return 5; 476 | k_user_shm* usm = k_kernel_mem->usm+id; 477 | munmap(user_mem(ctx->usm_addr[id]), ctx->usm_size[id]); 478 | ctx->usm_addr[id] = ctx->usm_size[id] = 0; 479 | if(usm->tcount--==0) k_shmem_unlink(USER_SHMEM, id); 480 | return 0; 481 | } 482 | 483 | void k_usm_clean(k_context* ctx) 484 | { 485 | int i; k_user_shm* usm = k_kernel_mem->usm; 486 | for(i=0; iusm_addr[i]!=0) 487 | if(usm[i].tcount--==0) k_shmem_unlink(USER_SHMEM, i); 488 | } 489 | 490 | void* k_skin_alloc(DWORD size) 491 | { 492 | if(k_skin_data!=NULL) k_skin_close(); 493 | size = (size+0xFFF)&-0x1000; 494 | return k_skin_data = (BYTE*)k_shmem_open(SKIN_SHMEM, 0, SKIN_BASE, k_skin_size = size, 0, NULL); 495 | } 496 | 497 | BYTE* k_skin_open() 498 | { 499 | if(k_skin_data!=NULL) k_skin_close(); 500 | return k_skin_data = (BYTE*)k_shmem_open(SKIN_SHMEM, 0, SKIN_BASE, 0, 0, &k_skin_size); 501 | } 502 | 503 | void k_skin_close() 504 | { 505 | if(k_skin_data==NULL) return; 506 | munmap(k_skin_data, k_skin_size); k_skin_data = NULL; 507 | } 508 | 509 | DWORD k_clipboard_add(DWORD size, DWORD addr) 510 | { 511 | DWORD* ptr = k_shmem_open(CLIPBOARD_SHMEM, k_kernel_mem->clipboard_count++, CLIPBOARD_BASE, size, 0, NULL); 512 | if(ptr == MAP_FAILED) return 1; 513 | memcpy(ptr, user_pd(addr), size); *ptr = size; 514 | munmap(ptr, size); 515 | return 0; 516 | } 517 | 518 | DWORD k_clipboard_get(DWORD id) 519 | { 520 | DWORD size,addr,*ptr = k_shmem_open(CLIPBOARD_SHMEM, id, CLIPBOARD_BASE, 0, 0, &size); 521 | if(ptr == MAP_FAILED) return 1; 522 | addr = k_heap_alloc((size+0xFFF)&-0x1000); 523 | memcpy(user_pd(addr), ptr, size); 524 | munmap(ptr, size); 525 | return addr; 526 | } 527 | 528 | DWORD k_clipboard_remove_last() 529 | { 530 | if(k_kernel_mem->clipboard_count==0) return 1; 531 | k_shmem_unlink(CLIPBOARD_SHMEM, --k_kernel_mem->clipboard_count); 532 | return 0; 533 | } 534 | 535 | DWORD k_stub_resume(DWORD eip) 536 | { 537 | // dd 17h / mov ss,[3FFFF000h] / jmp eip 538 | memcpy(k_stub, "\x17\x0\x0\x0\x8E\x15\x0\xF0\xFF\x3F\xE9", 11); 539 | *(DWORD*)(k_stub+11) = eip - 0x3FFFF00F; 540 | return 0x3FFFF004; 541 | } 542 | 543 | DWORD k_stub_jmp(DWORD eip, DWORD esp) 544 | { 545 | // mov esp,# / jmp eip 546 | memcpy(k_stub, "\xBC\x0\x0\x0\x0\xE9", 6); 547 | *(DWORD*)(k_stub+1) = esp; 548 | *(DWORD*)(k_stub+6) = eip - 0x3FFFF00A; 549 | return 0x3FFFF000; 550 | } 551 | 552 | #ifdef __x86_64__ 553 | 554 | QWORD __k_fsbase; 555 | 556 | #include 557 | 558 | int arch_prctl(int code, ...); 559 | 560 | void k_save_fsbase() 561 | { 562 | arch_prctl(ARCH_GET_FS, &__k_fsbase); 563 | } 564 | 565 | void k_load_fsbase() 566 | { 567 | arch_prctl(ARCH_SET_FS, __k_fsbase); 568 | } 569 | 570 | void k_set_fsbase() 571 | { 572 | arch_prctl(ARCH_SET_FS, (QWORD)TLS_BASE); 573 | } 574 | 575 | #endif 576 | -------------------------------------------------------------------------------- /k_mem.h: -------------------------------------------------------------------------------- 1 | typedef short SHORT; 2 | typedef int LONG; 3 | 4 | typedef unsigned char BYTE; 5 | typedef unsigned short WORD; 6 | typedef unsigned int DWORD; 7 | typedef unsigned long long QWORD; 8 | 9 | #define MAX_CHILD 64 10 | #define MAX_KEYS 120 11 | #define MAX_HOTKEYS 64 12 | #define MAX_USM 16 13 | #define MAX_DRIVER 16 14 | #define MAX_SOCKET 32 15 | #define MAX_IFACE 8 16 | #define DEBUG_BOARD_LEN 4096 17 | 18 | typedef struct 19 | { 20 | DWORD tv_sec; 21 | DWORD tv_nsec; 22 | } k_timespec; 23 | 24 | typedef struct 25 | { 26 | DWORD pid; 27 | DWORD tid; 28 | DWORD shmid; 29 | DWORD memsize; 30 | DWORD event_mask; 31 | DWORD event_pending; 32 | DWORD mouse_state; 33 | DWORD mouse_last_pressed; 34 | DWORD kbd_mode; 35 | DWORD hotkey_out_pos; 36 | DWORD hotkey_count; 37 | DWORD hotkey_def[MAX_HOTKEYS]; 38 | DWORD window_color; 39 | DWORD window_zpos_me; 40 | DWORD window_zpos; 41 | DWORD window_state; 42 | DWORD window_drag_mode; 43 | char* window_title; 44 | int window_x; 45 | int window_y; 46 | int window_w; 47 | int window_h; 48 | int orig_x; 49 | int orig_y; 50 | int orig_w; 51 | int orig_h; 52 | int client_x; 53 | int client_y; 54 | int mouse_x; 55 | int mouse_y; 56 | int mouse_wheel_y; 57 | int button_id_pressed; 58 | int button_id; 59 | int focused; 60 | int retcode; 61 | BYTE* ipc_buffer; 62 | DWORD ipc_buf_len; 63 | char name[12]; 64 | BYTE curpath[256]; 65 | DWORD usm_addr[MAX_USM]; 66 | DWORD usm_size[MAX_USM]; 67 | int sockets[MAX_SOCKET]; 68 | } k_context; 69 | 70 | typedef struct 71 | { 72 | DWORD tcount; 73 | DWORD flags; 74 | char name[32]; 75 | } k_user_shm; 76 | 77 | typedef struct 78 | { 79 | char name[16]; 80 | DWORD (*ioctl)(DWORD code, void* idata, DWORD ilen, void* odata, DWORD olen); 81 | } k_driver; 82 | 83 | typedef struct 84 | { 85 | char name[32]; 86 | DWORD mac_lo; 87 | DWORD mac_hi; 88 | DWORD ip; 89 | DWORD mask; 90 | DWORD dns; 91 | DWORD gateway; 92 | } k_iface; 93 | 94 | typedef struct 95 | { 96 | DWORD keyboard_modifiers; 97 | DWORD keyboard_country; 98 | DWORD keyboard_language; 99 | DWORD keyboard_in_pos; 100 | DWORD keyboard_out_pos; 101 | DWORD keyboard_buffer[MAX_KEYS]; 102 | DWORD hotkey_in_pos; 103 | DWORD hotkey_buffer[MAX_KEYS]; 104 | char keyboard_layout[3][128]; 105 | int mouse_x; 106 | int mouse_y; 107 | int mouse_dbl_click_delay; 108 | k_timespec mouse_dbl_click_timeout; 109 | WORD desktop_left; 110 | WORD desktop_top; 111 | WORD desktop_right; 112 | WORD desktop_bottom; 113 | DWORD active_slot; 114 | DWORD debug_in_pos; 115 | DWORD debug_out_pos; 116 | int shmtc[MAX_CHILD]; 117 | k_context slot[MAX_CHILD]; 118 | k_user_shm usm[MAX_USM]; 119 | k_driver driver[MAX_DRIVER]; 120 | char extfs_key[64]; 121 | char extfs_path[64]; 122 | DWORD if_count; 123 | k_iface iface[MAX_IFACE]; 124 | DWORD pci_enabled; 125 | DWORD clipboard_count; 126 | BYTE debug_board[DEBUG_BOARD_LEN]; 127 | } KERNEL_MEM; 128 | 129 | void k_printf(char* fmt, ...); 130 | void k_panic(char* msg); 131 | 132 | void k_kernel_mem_init(); 133 | void k_kernel_mem_cleanup(); 134 | KERNEL_MEM* kernel_mem(); 135 | 136 | #define g_slot kernel_mem()->slot 137 | 138 | void k_mem_init(int shmid); 139 | void k_mem_done(int shmid); 140 | void k_mem_reopen(); 141 | void* k_mem_alloc(DWORD size); 142 | void* k_mem_alloc_from_heap(DWORD size); 143 | DWORD k_mem_size(DWORD size); 144 | DWORD k_mem_get_size(); 145 | 146 | DWORD k_heap_init(); 147 | DWORD k_heap_alloc(DWORD size); 148 | DWORD k_heap_realloc(DWORD addr, DWORD size); 149 | DWORD k_heap_free(DWORD addr); 150 | 151 | DWORD k_usm_open(k_context* ctx, DWORD aname, DWORD size, DWORD flags, DWORD* addr); 152 | DWORD k_usm_close(k_context* ctx, DWORD aname); 153 | void k_usm_clean(k_context* ctx); 154 | 155 | void* user_mem(DWORD addr); 156 | 157 | #define user_pb(addr) ((BYTE*)user_mem(addr)) 158 | #define user_pw(addr) ((WORD*)user_mem(addr)) 159 | #define user_pd(addr) ((DWORD*)user_mem(addr)) 160 | #define k_get_byte(addr) (*user_pb(addr)) 161 | #define k_get_word(addr) (*user_pw(addr)) 162 | #define k_get_dword(addr) (*user_pd(addr)) 163 | 164 | void* k_skin_alloc(DWORD size); 165 | BYTE* k_skin_open(); 166 | void k_skin_close(); 167 | 168 | DWORD k_clipboard_add(DWORD size, DWORD addr); 169 | DWORD k_clipboard_get(DWORD id); 170 | DWORD k_clipboard_remove_last(); 171 | 172 | DWORD k_stub_resume(DWORD eip); 173 | DWORD k_stub_jmp(DWORD eip, DWORD esp); 174 | 175 | void k_save_fsbase(); 176 | void k_load_fsbase(); 177 | void k_set_fsbase(); 178 | 179 | BYTE* k_mem_open_app(int shmid, DWORD* psize); 180 | void k_mem_close_app(void* ptr, DWORD size); 181 | -------------------------------------------------------------------------------- /k_net.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_net.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct 13 | { 14 | const char* id; 15 | const char* fmt; 16 | int ofs[9]; 17 | } k_nmcli_line; 18 | 19 | #define MAX_IF_COUNT 4 20 | #define k_if_hwaddr(i) k_if_data[i] 21 | #define k_if_ip(i) *(DWORD*)&k_if_data[i][10] 22 | #define k_if_gw(i) *(DWORD*)&k_if_data[i][14] 23 | #define k_if_dns(i) *(DWORD*)&k_if_data[i][22] 24 | 25 | BYTE k_if_data[MAX_IF_COUNT][30]; 26 | 27 | const k_nmcli_line nmcli_lines[] = { 28 | {"GENERAL.HWADDR", "%x:%x:%x:%x:%x:%x", {0,1,2,3,4,5}}, 29 | {"GENERAL.АППАРАТНЫЙ АДРЕС", "%x:%x:%x:%x:%x:%x", {0,1,2,3,4,5}}, 30 | {"IP4.ADDRESS[1]", " ip = %d.%d.%d.%d/%d, gw = %d.%d.%d.%d", {10,11,12,13,18,14,15,16,17}}, 31 | {"IP4.АДРЕС[1]", " ip = %d.%d.%d.%d/%d, gw = %d.%d.%d.%d", {10,11,12,13,18,14,15,16,17}}, 32 | {"IP4.ADDRESS[1]", "%d.%d.%d.%d/%d", {10,11,12,13,18}}, 33 | {"IP4.АДРЕС[1]", "%d.%d.%d.%d/%d", {10,11,12,13,18}}, 34 | {"IP4.GATEWAY", "%d.%d.%d.%d", {14,15,16,17}}, 35 | {"IP4.ШЛЮЗ", "%d.%d.%d.%d", {14,15,16,17}}, 36 | {"IP4.DNS[1]", "%d.%d.%d.%d", {22,23,24,25}}, 37 | {NULL} 38 | }; 39 | 40 | #define NMP(n) nm->ofs[n]+k_if_data[i] 41 | 42 | int k_nmcli_call(const char* cmd) 43 | { 44 | char line[512],*p; const k_nmcli_line* nm; 45 | int i,ret = 1; FILE* fp = popen(cmd, "r"); if(!fp) return 1; 46 | for(i=-1; iid; ++nm) 50 | { 51 | if(strcmp(line, nm->id)==0) 52 | { 53 | if(nm=MAX_IF_COUNT) break; 54 | if(sscanf(p, nm->fmt, NMP(0), NMP(1), NMP(2), NMP(3), NMP(4), NMP(5), NMP(6), NMP(7), NMP(8))>0) 55 | { 56 | ret = 0; break; 57 | } 58 | } 59 | } 60 | } 61 | fclose(fp); 62 | return ret; 63 | } 64 | 65 | k_timespec k_net_update_timeout; 66 | 67 | void k_net_update() 68 | { 69 | k_timespec now; k_time_get(&now); 70 | if(k_time_gt(&k_net_update_timeout,&now)) return; 71 | k_net_update_timeout = now; k_net_update_timeout.tv_sec++; 72 | KERNEL_MEM* km = kernel_mem(); 73 | if(km->if_count==0) 74 | { 75 | if(k_nmcli_call("nmcli d show 2>/dev/null")) k_nmcli_call("nmcli d list 2>/dev/null"); 76 | struct ifaddrs *ifap = NULL,*p; getifaddrs(&ifap); 77 | for(p=ifap; p!=NULL; p=p->ifa_next) if(p->ifa_addr!=NULL && p->ifa_addr->sa_family==AF_INET) 78 | { 79 | struct sockaddr_in ip,mask; DWORD i = km->if_count++,j; 80 | ip = *(struct sockaddr_in*)p->ifa_addr; 81 | mask = *(struct sockaddr_in*)p->ifa_netmask; 82 | strncpy(km->iface[i].name, p->ifa_name, 32); 83 | km->iface[i].ip = ip.sin_addr.s_addr; 84 | km->iface[i].mask = mask.sin_addr.s_addr; 85 | for(j=0; jiface[i].mac_hi = *(WORD*)k_if_hwaddr(j); 88 | km->iface[i].mac_lo = *(DWORD*)(k_if_hwaddr(j)+2); 89 | km->iface[i].gateway = k_if_gw(j); 90 | km->iface[i].dns = k_if_dns(j); 91 | break; 92 | } 93 | } 94 | if(ifap) freeifaddrs(ifap); 95 | } 96 | } 97 | 98 | DWORD k_net_info(k_context* ctx, BYTE devNo, BYTE func, DWORD* ebx, DWORD* ecx) 99 | { 100 | k_net_update(); 101 | KERNEL_MEM* km = kernel_mem(); if(func!=255 && devNo>=km->if_count) return -1; 102 | switch(func) 103 | { 104 | case 0: return devNo==0 ? 0 : 1; // type 105 | case 1: strcpy(user_mem(*ecx), km->iface[devNo].name); return 0; 106 | case 2: return 0; // reset 107 | case 3: return 0; // stop 108 | case 6: return 0; // send pck 109 | case 7: return 0; // recv pck 110 | case 8: *ebx = 0; return 0; // send bytes 111 | case 9: *ebx = 0; return 0; // recv bytes 112 | case 10: return 10; // link type 113 | case 255: return km->if_count; // iface count 114 | default: return -1; 115 | } 116 | } 117 | 118 | void ks_replace_socket(k_context* ctx, int cmp, int sock) 119 | { 120 | int i; int* list = ctx->sockets; 121 | for(i=0; i=km->if_count) return -1; 149 | switch(func) 150 | { 151 | case 0: *ebx = km->iface[devNo].mac_hi; return km->iface[devNo].mac_lo; 152 | default: return -1; 153 | } 154 | } 155 | 156 | DWORD kp_ipv4(k_context* ctx, BYTE devNo, BYTE func, DWORD ecx) 157 | { 158 | KERNEL_MEM* km = kernel_mem(); if(devNo>=km->if_count) return -1; 159 | switch(func) 160 | { 161 | case 2: return km->iface[devNo].ip; 162 | case 3: km->iface[devNo].ip = ecx; return 0; 163 | case 4: return km->iface[devNo].dns; 164 | case 5: km->iface[devNo].dns = ecx; return 0; 165 | case 6: return km->iface[devNo].mask; 166 | case 7: km->iface[devNo].mask = ecx; return 0; 167 | case 8: return km->iface[devNo].gateway; 168 | case 9: km->iface[devNo].gateway = ecx; return 0; 169 | default: return 0; 170 | } 171 | } 172 | 173 | DWORD kp_icmp(k_context* ctx, BYTE devNo, BYTE func) 174 | { 175 | return 0; 176 | } 177 | 178 | DWORD kp_udp(k_context* ctx, BYTE devNo, BYTE func) 179 | { 180 | return 0; 181 | } 182 | 183 | DWORD kp_tcp(k_context* ctx, BYTE devNo, BYTE func) 184 | { 185 | return 0; 186 | } 187 | 188 | DWORD kp_arp(k_context* ctx, BYTE devNo, BYTE func) 189 | { 190 | switch(func) 191 | { 192 | case 0: return 0; // send pck 193 | case 1: return 0; // recv pck 194 | case 2: return 0; // # ARP recs 195 | case 3: return -1; // read ARP rec 196 | case 4: return 0; // add static rec 197 | case 5: return 0; // remove rec 198 | case 6: return 0; // send ARP announce 199 | case 7: return 0; // # conflicts 200 | default: return -1; 201 | } 202 | } 203 | 204 | DWORD k_net_proto(k_context* ctx, WORD proto, BYTE devNo, BYTE func, DWORD* ebx, DWORD* ecx) 205 | { 206 | k_net_update(); 207 | switch(proto) 208 | { 209 | case 0: return kp_ethernet(ctx, devNo, func, ebx); 210 | case 1: return kp_ipv4(ctx, devNo, func, *ecx); 211 | case 2: return kp_icmp(ctx, devNo, func); 212 | case 3: return kp_udp(ctx, devNo, func); 213 | case 4: return kp_tcp(ctx, devNo, func); 214 | case 5: return kp_arp(ctx, devNo, func); 215 | default: return -1; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /k_net.h: -------------------------------------------------------------------------------- 1 | DWORD k_net_info(k_context* ctx, BYTE devNo, BYTE func, DWORD* ebx, DWORD* ecx); 2 | DWORD k_net_socket(k_context* ctx, BYTE func, DWORD* ebx, DWORD ecx, DWORD edx, DWORD esi, DWORD edi); 3 | DWORD k_net_proto(k_context* ctx, WORD proto, BYTE devNo, BYTE func, DWORD* ebx, DWORD* ecx); 4 | -------------------------------------------------------------------------------- /k_proc.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_file.h" 4 | #include "k_proc.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma pack(push,1) 12 | typedef struct 13 | { 14 | BYTE props; // (pb*5+lp)*9+lc 15 | DWORD dict_size; 16 | QWORD uncomp_size; 17 | BYTE data; 18 | } k_lzma_hdr; 19 | #pragma pack(pop) 20 | 21 | static char* lzma_error = "lzma error"; 22 | 23 | void k_unpack_lzma(DWORD in_size, BYTE* in, DWORD out_size, BYTE* out) 24 | { 25 | k_lzma_hdr hdr = {(2*5+0)*9+3,0x10000,-1,0}; 26 | lzma_stream strm = LZMA_STREAM_INIT; 27 | lzma_ret ret = lzma_alone_decoder(&strm, UINT64_MAX); 28 | if(ret!=LZMA_OK) k_panic(lzma_error); 29 | while(hdr.dict_size=0x80 && data[i+1]<0x90 && data[i+2]==cmp) i+=2; else 49 | if((data[i]&0xFE)==0xE8 && data[i+1]==cmp) ++i; else continue; 50 | tmp = (((data[i+1]<<8)|data[i+2])<<8)|data[i+3]; 51 | *(DWORD*)(data+i) = tmp-(i+4); i+=3; 52 | } 53 | } 54 | 55 | DWORD coff_parse(COFF_HEADER* hdr, BYTE* mem, DWORD* exports) 56 | { 57 | DWORD i,j,size=0; 58 | COFF_SECTION* sec = (COFF_SECTION*)(sizeof(COFF_HEADER)+(BYTE*)hdr); 59 | COFF_SYM* sym = (COFF_SYM*)(hdr->pSymTable+(BYTE*)hdr); 60 | for(i=0; inSection; ++i,++sec) 61 | { 62 | DWORD align = (sec->Flags>>20)&15; 63 | if(align<1||align>12) align = 12; 64 | align = (1<VirtualAddress = (mem-user_pb(0))+size; 69 | if(exports) 70 | { 71 | if(sec->PtrRawData==0) 72 | { 73 | memset(mem+size, 0, sec->SizeOfRawData); 74 | } 75 | else 76 | { 77 | memcpy(mem+size, sec->PtrRawData+(BYTE*)hdr, sec->SizeOfRawData); 78 | } 79 | COFF_RELOC* rel = (COFF_RELOC*)(sec->PtrReloc+(BYTE*)hdr); 80 | for(j=0; jNumReloc; ++j,++rel) 81 | { 82 | DWORD value = sym[rel->SymIndex].Value; 83 | DWORD* pfix = (DWORD*)(mem+size+rel->VirtualAddress); 84 | switch(rel->Type) 85 | { 86 | case 6: *pfix += value; break; 87 | case 20: *pfix += value-(((BYTE*)pfix)-user_pb(0))-4; break; 88 | } 89 | } 90 | } 91 | } 92 | size += sec->SizeOfRawData; 93 | } 94 | if(exports) 95 | { 96 | for(i=0; inSymbols; ++i,++sym) 97 | { 98 | if(strcmp(sym->name, "EXPORTS")==0) 99 | { 100 | *exports = sym->Value; 101 | break; 102 | } 103 | } 104 | } 105 | else if(mem) 106 | { 107 | COFF_SECTION* sec = (COFF_SECTION*)(sizeof(COFF_HEADER)+(BYTE*)hdr); 108 | for(i=0; inSymbols; ++i,++sym) 109 | { 110 | if(sym->SectionNumber>0 && sym->SectionNumber<0xFFFE) 111 | { 112 | sym->Value += sec[sym->SectionNumber-1].VirtualAddress; 113 | } 114 | } 115 | } 116 | return size; 117 | } 118 | 119 | void* k_malloc_wrap(DWORD size) 120 | { 121 | return malloc(size); 122 | } 123 | 124 | void* k_load(k_context* ctx, BYTE* name, int cp, void*(*_mem_alloc)(DWORD), DWORD* exports, DWORD* psize) 125 | { 126 | void* mem = NULL; if(_mem_alloc == NULL) _mem_alloc = k_malloc_wrap; 127 | 128 | FILE* fp = fopen((char*)name, "rb"); 129 | if(fp == NULL) 130 | { 131 | char fname[512]; k_parse_name(ctx, name, cp, fname, sizeof(fname)); 132 | fp = fopen(fname, "rb"); 133 | } 134 | if(fp != NULL) 135 | { 136 | KEX_FILE_HDR hdr; DWORD size,flen; BYTE* unpacked = NULL; 137 | if(fread(&hdr, 1, sizeof(hdr), fp)!=sizeof(hdr)) { fclose(fp); return 0; } 138 | fseek(fp, 0, SEEK_END); size = flen = ftell(fp); 139 | if(size==-1) { fclose(fp); return 0; } 140 | if(memcmp(hdr.magic,"KPCK",4) == 0) 141 | { 142 | size = hdr.u.kpck.unpacked; unpacked = (BYTE*)malloc(size); 143 | BYTE* packed = (BYTE*)malloc(flen-12); 144 | fseek(fp, 12, SEEK_SET); 145 | fread(packed, 1, flen-12, fp); 146 | switch(hdr.u.kpck.flags&0x3F) { 147 | case 0: memcpy(unpacked, packed, size); break; 148 | case 1: k_unpack_lzma(flen-12, packed, size, unpacked); break; 149 | default: k_panic("unsupported pack method"); break; 150 | } 151 | switch(hdr.u.kpck.flags&0xC0) { 152 | case 0x40: k_tricks(size, unpacked, packed[flen-13], 1); break; 153 | case 0x80: k_tricks(size, unpacked, packed[flen-13], 2); break; 154 | case 0xC0: k_panic("unsupported trick"); break; 155 | } 156 | free(packed); 157 | memcpy(&hdr, unpacked, sizeof(hdr)); 158 | } 159 | if(psize) *psize = size; 160 | if(0x14C == *(WORD*)&hdr) 161 | { 162 | size = coff_parse((COFF_HEADER*)unpacked, NULL, NULL); 163 | if(size==0||size>=0x1000000) k_panic("coff error"); 164 | mem = _mem_alloc(size); 165 | coff_parse((COFF_HEADER*)unpacked, (BYTE*)mem, NULL); 166 | coff_parse((COFF_HEADER*)unpacked, (BYTE*)mem, exports); 167 | //fclose(fp); fp=fopen("../0_unpacked","wb"); fwrite(mem,size,1,fp); 168 | } 169 | else 170 | { 171 | if(memcmp(hdr.magic,"MENUET0",7) == 0) 172 | { 173 | mem = _mem_alloc(hdr.u.menuet.ram_size); 174 | } 175 | else 176 | { 177 | mem = _mem_alloc(size); 178 | } 179 | if(unpacked) 180 | { 181 | memcpy(mem, unpacked, size); 182 | } 183 | else 184 | { 185 | fseek(fp, 0, SEEK_SET); 186 | fread(mem, 1, size, fp); 187 | } 188 | } 189 | if(unpacked) free(unpacked); 190 | fclose(fp); 191 | } 192 | #ifdef _DEBUG 193 | else 194 | { 195 | fprintf(stderr, "%s not found\n", name); 196 | } 197 | #endif 198 | 199 | return mem; 200 | } 201 | 202 | DWORD k_load_file(k_context* ctx, BYTE* name, int cp, DWORD* psize) 203 | { 204 | DWORD exports = 0; BYTE* mem; if(psize) *psize = 0; 205 | mem = k_load(ctx, name, cp, k_mem_alloc_from_heap, &exports, psize); 206 | return mem ? mem - user_pb(0) : 0; 207 | } 208 | 209 | DWORD k_load_dll(k_context* ctx, BYTE* name, int cp) 210 | { 211 | DWORD exports = 0; 212 | k_load(ctx, name, cp, k_mem_alloc_from_heap, &exports, NULL); 213 | return exports; 214 | } 215 | 216 | void k_exec(k_context* ctx, char* kexfile, char* args) 217 | { 218 | KEX_FILE_HDR* hdr = (KEX_FILE_HDR*)k_load(ctx, (BYTE*)kexfile, 3, k_mem_alloc, NULL, NULL); 219 | ctx->memsize = k_mem_get_size(); 220 | 221 | if(hdr != NULL && memcmp(hdr->magic,"MENUET0",7) == 0) 222 | { 223 | DWORD esp = hdr->u.menuet.ram_size; 224 | if (hdr->magic[7]!='0') 225 | { 226 | esp = hdr->u.menuet.stack_pos; 227 | if(hdr->u.menuet.path_buf!=0) 228 | { 229 | char* path_buf = (char*)user_mem(hdr->u.menuet.path_buf); *path_buf++='/'; *path_buf++=3; 230 | if(*kexfile!='/') { strcpy(path_buf, "/sys/"); path_buf+=5; } 231 | strcpy(path_buf, kexfile); 232 | } 233 | 234 | if(args!=NULL && hdr->u.menuet.args_buf!=0) 235 | { 236 | char* args_buf = (char*)user_mem(hdr->u.menuet.args_buf); 237 | strncpy(args_buf, args, 256); 238 | } 239 | } 240 | 241 | k_start_thread(hdr->u.menuet.start, esp); 242 | } 243 | } 244 | 245 | void k_start_thread(DWORD eip, DWORD esp) 246 | { 247 | #ifdef __x86_64__ 248 | k_set_fsbase(); 249 | __asm__ __volatile__ ( 250 | "mov $0x17, %%ax\n" 251 | "mov %%ax, %%ds\n" 252 | "mov %%ax, %%es\n" 253 | "mov %%ax, %%ss\n" 254 | "push %0\n" 255 | "lret\n" : : 256 | "r" (k_stub_jmp(eip, esp)+0xf00000000) : "ax" 257 | ); 258 | #else 259 | k_stub_jmp(eip, esp); 260 | __asm__ __volatile__ ( 261 | "mov $0x17, %ax\n" 262 | "mov %ax, %ds\n" 263 | "mov %ax, %es\n" 264 | "mov %ax, %ss\n" 265 | "mov $0x1f, %ax\n" 266 | "mov %ax, %fs\n" 267 | "jmp $0x0f, $0x3FFFF000\n" 268 | ); 269 | #endif 270 | } 271 | -------------------------------------------------------------------------------- /k_proc.h: -------------------------------------------------------------------------------- 1 | #pragma pack(push,1) 2 | typedef struct 3 | { 4 | BYTE magic[4]; 5 | union 6 | { 7 | struct 8 | { 9 | BYTE magic[4]; 10 | DWORD version; 11 | DWORD start; 12 | DWORD code_size; 13 | DWORD ram_size; 14 | DWORD stack_pos; 15 | DWORD args_buf; 16 | DWORD path_buf; 17 | } menuet; 18 | struct 19 | { 20 | DWORD unpacked; 21 | DWORD flags; 22 | } kpck; 23 | } u; 24 | } KEX_FILE_HDR; 25 | 26 | typedef struct 27 | { 28 | WORD machine; 29 | WORD nSection; 30 | DWORD DataTime; 31 | DWORD pSymTable; 32 | DWORD nSymbols; 33 | WORD optHeader; 34 | WORD flags; 35 | } COFF_HEADER; 36 | 37 | typedef struct 38 | { 39 | char name[8]; 40 | DWORD VirtualSize; 41 | DWORD VirtualAddress; 42 | DWORD SizeOfRawData; 43 | DWORD PtrRawData; 44 | DWORD PtrReloc; 45 | DWORD PtrLineNum; 46 | WORD NumReloc; 47 | WORD NumLineNum; 48 | DWORD Flags; 49 | } COFF_SECTION; 50 | 51 | typedef struct 52 | { 53 | DWORD VirtualAddress; 54 | DWORD SymIndex; 55 | WORD Type; 56 | } COFF_RELOC; 57 | 58 | typedef struct 59 | { 60 | char name[8]; 61 | DWORD Value; 62 | WORD SectionNumber; 63 | WORD Type; 64 | BYTE StorageClass; 65 | BYTE MaxAuxSymbols; 66 | } COFF_SYM; 67 | #pragma pack(pop) 68 | 69 | void k_proc_init(); 70 | void k_exec(k_context* ctx, char* kexfile, char* args); 71 | void k_start_thread(DWORD eip, DWORD esp); 72 | void* k_load(k_context* ctx, BYTE* name, int cp, void*(*_mem_alloc)(DWORD), DWORD* exports, DWORD* psize); 73 | DWORD k_load_file(k_context* ctx, BYTE* name, int cp, DWORD* psize); 74 | DWORD k_load_dll(k_context* ctx, BYTE* name, int cp); 75 | -------------------------------------------------------------------------------- /k_syscall.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_iconv.h" 4 | #include "k_proc.h" 5 | #include "k_gui.h" 6 | #include "k_file.h" 7 | #include "k_ipc.h" 8 | #include "k_net.h" 9 | #include "k_syscall.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | int base_pid = 0; 23 | 24 | int gettid() 25 | { 26 | return getpid()-base_pid; 27 | } 28 | 29 | void k_debug_put(BYTE ch) 30 | { 31 | KERNEL_MEM* km = kernel_mem(); 32 | km->debug_board[km->debug_in_pos++] = ch; 33 | km->debug_in_pos %= DEBUG_BOARD_LEN; 34 | } 35 | 36 | DWORD k_debug_get(DWORD* ebx) 37 | { 38 | DWORD ret; KERNEL_MEM* km = kernel_mem(); 39 | if(km->debug_in_pos==km->debug_out_pos) return *ebx = 0; 40 | ret = km->debug_board[km->debug_out_pos++]; *ebx = 1; 41 | km->debug_out_pos %= DEBUG_BOARD_LEN; 42 | return ret; 43 | } 44 | 45 | void k_putc866(char ch) 46 | { 47 | char out[4]; k_strncpy((BYTE*)out,3,(BYTE*)&ch,0,1); 48 | fputs(out, stderr); 49 | } 50 | 51 | void k_vprintf(int opt, char* fmt, va_list va) 52 | { 53 | char buf[4096],*s; int nl=1; 54 | vsprintf(buf, fmt, va); 55 | for(s=buf; *s; ++s) 56 | { 57 | if(nl) 58 | { 59 | k_debug_put('K'); k_debug_put(' '); 60 | k_debug_put(':'); k_debug_put(' '); 61 | } 62 | if((opt&1)!=0) k_putc866(*s); 63 | k_debug_put(*s); 64 | nl = (*s == 10); 65 | } 66 | } 67 | 68 | void k_debug_printf(char* fmt, ...) 69 | { 70 | va_list va; va_start(va, fmt); k_vprintf(0, fmt, va); 71 | } 72 | 73 | void k_printf(char* fmt, ...) 74 | { 75 | va_list va; va_start(va, fmt); k_vprintf(1, fmt, va); 76 | } 77 | 78 | void k_panic(char* msg) 79 | { 80 | k_printf("%s\n", msg); 81 | exit(-1); 82 | } 83 | 84 | void k_get_slot_info(k_context* ctx, K_SLOT_INFO* info, int slot) 85 | { 86 | if(slot<-1 || slot>=MAX_CHILD) { info->state = 9; return; } 87 | if(slot!=-1) ctx = g_slot+slot; 88 | info->cputime = 0; 89 | info->zpos_me = ctx->window_zpos_me; 90 | info->zpos = ctx->window_zpos; 91 | memcpy(info->name, ctx->name, sizeof(ctx->name)); 92 | info->base = 0; 93 | info->last = ctx->memsize-1; 94 | info->pid = ctx->tid; 95 | info->window_x = ctx->window_x; 96 | info->window_y = ctx->window_y; 97 | info->window_w = ctx->window_w>0?ctx->window_w-1:0; 98 | info->window_h = ctx->window_h>0?ctx->window_h-1:0; 99 | info->state = ctx->tid!=0 ? 0 : 9; 100 | k_get_client_rect(ctx, &info->client_x, &info->client_y, &info->client_w, &info->client_h); 101 | info->window_state = ctx->window_state; 102 | info->event_mask = ctx->event_mask; 103 | info->kbd_mode = ctx->kbd_mode; 104 | } 105 | 106 | void k_set_slot(DWORD slot, int shmid, char* name) 107 | { 108 | k_context* ctx = g_slot+slot; 109 | char* p = strrchr(name,'/'); if(p) name = p+1; 110 | 111 | memset(ctx, 0, sizeof(k_context)); 112 | ctx->pid = getpid(); 113 | ctx->tid = gettid(); 114 | ctx->shmid = shmid; 115 | ctx->event_mask = 7; 116 | ctx->event_pending = K_EVMASK_REDRAW; 117 | strncpy(ctx->name, name, sizeof(ctx->name)-1); 118 | p = strchr(ctx->name, '.'); if(p) *p = 0; 119 | k_copy_path(ctx->curpath, (BYTE*)"/sys/"); 120 | kernel_mem()->shmtc[shmid] = 1; 121 | } 122 | 123 | void k_set_slot_from(DWORD slot, DWORD from) 124 | { 125 | k_context* ctx = g_slot+slot; 126 | k_context* src = g_slot+from; 127 | 128 | memset(ctx, 0, sizeof(k_context)); 129 | ctx->pid = getpid(); 130 | ctx->tid = gettid(); 131 | ctx->shmid = src->shmid; 132 | ctx->memsize = src->memsize; 133 | ctx->event_mask = src->event_mask; 134 | ctx->event_pending = K_EVMASK_REDRAW; 135 | strncpy(ctx->name, src->name, sizeof(ctx->name)-1); 136 | k_copy_path(ctx->curpath, src->curpath); 137 | kernel_mem()->shmtc[src->shmid]++; 138 | } 139 | 140 | DWORD k_get_slot() 141 | { 142 | k_context* slot = g_slot; 143 | DWORD i,pid=getpid(),tid=gettid(); 144 | for(i=1; i= slot[i].window_x && y >= slot[i].window_y && 160 | x < slot[i].window_x+slot[i].window_w && y < slot[i].window_y+slot[i].window_h && 161 | (best==0 || slot[best].window_zpos_me0 && slot[i].pid == 0 && slot[i].tid == 0; --i); 170 | return i; 171 | } 172 | 173 | void k_kill_by_slot(DWORD slot) 174 | { 175 | if(slot<1||slot>=MAX_CHILD) return; 176 | k_context* ctx = g_slot+slot; 177 | if(ctx->tid==0) return; 178 | kill(ctx->pid, SIGKILL); 179 | } 180 | 181 | void k_update_memusage(k_context* ctx) 182 | { 183 | ctx->memsize = k_mem_get_size(); 184 | } 185 | 186 | DWORD k_new_thread(k_context* ctx, DWORD slot, DWORD eip, DWORD esp) 187 | { 188 | msg_t msg; 189 | msg_clone(&msg, slot, eip, esp); 190 | write_msg(ipc_server, &msg); 191 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_REPLY); 192 | return ctx->retcode; 193 | } 194 | 195 | DWORD k_send_ipc_message(k_context* ctx, DWORD tid, BYTE* data, DWORD len) 196 | { 197 | int slot = k_find_slot(tid); if(slot<=0) return 4; 198 | msg_t msg; msg_ipc(&msg, slot, IPCCODE_DATA, len, NULL); 199 | write_msg(ipc_server, &msg); 200 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_IPC || msg.u.ipc.code>=IPCCODE_DATA); 201 | if(msg.u.ipc.code!=0) return msg.u.ipc.code; 202 | while(len>0) 203 | { 204 | DWORD n = len<4000 ? len : 4000; 205 | msg_ipc(&msg, slot, n==len?0:IPCCODE_DATA, n, data); 206 | write_msg(ipc_server, &msg); 207 | len -= n; data += n; 208 | } 209 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_IPC || msg.u.ipc.code>=IPCCODE_DATA); 210 | return 0; 211 | } 212 | 213 | void k_make_active(DWORD slot) 214 | { 215 | msg_t msg; msg_ipc(&msg, slot, IPCCODE_ACTIVATE, 0, NULL); 216 | write_msg(ipc_server, &msg); 217 | kernel_mem()->active_slot = slot; 218 | } 219 | 220 | DWORD k_send_event(DWORD type, DWORD param) 221 | { 222 | msg_t msg; msg_ipc_event(&msg, kernel_mem()->active_slot, type, param); 223 | write_msg(ipc_server, &msg); 224 | return 0; 225 | } 226 | 227 | DWORD k_driver_load(k_context* ctx, char* name) 228 | { 229 | msg_t msg; msg_driver_load(&msg, name); 230 | write_msg(ipc_server, &msg); 231 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_REPLY); 232 | return ctx->retcode; 233 | } 234 | 235 | DWORD k_driver_ioctl(k_context* ctx, DWORD* args) 236 | { 237 | msg_t msg; msg_driver_ioctl(&msg, ctx->shmid, args); 238 | write_msg(ipc_server, &msg); 239 | do k_process_ipc_event(ctx, &msg); while(msg.type!=MSGTYPE_REPLY); 240 | return ctx->retcode; 241 | } 242 | 243 | int futex(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3) 244 | { 245 | return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3); 246 | } 247 | 248 | DWORD k_futex_wait(int* uaddr, int val, DWORD timeout) 249 | { 250 | struct timespec tm; 251 | tm.tv_sec = timeout/100; 252 | tm.tv_nsec = (timeout%100)*10000000; 253 | int ret = futex(uaddr, FUTEX_WAIT, val, timeout?&tm:NULL, NULL, 0); 254 | if(ret==0) return 0; 255 | return errno==ETIMEDOUT ? -1 : -2; 256 | } 257 | 258 | DWORD k_futex_wake(int* uaddr, int val) 259 | { 260 | return futex(uaddr, FUTEX_WAKE, val, NULL, NULL, 0); 261 | } 262 | 263 | #define R_FL gregs[REG_EFL] 264 | #define R_ERR gregs[REG_ERR] 265 | #define R_TRAPNO gregs[REG_TRAPNO] 266 | 267 | #ifdef __x86_64__ 268 | 269 | #define R_AX gregs[REG_RAX] 270 | #define R_BX gregs[REG_RBX] 271 | #define R_CX gregs[REG_RCX] 272 | #define R_DX gregs[REG_RDX] 273 | #define R_SI gregs[REG_RSI] 274 | #define R_DI gregs[REG_RDI] 275 | #define R_BP gregs[REG_RBP] 276 | #define R_SP gregs[REG_RSP] 277 | #define R_IP gregs[REG_RIP] 278 | #define R_CS ((WORD)gregs[REG_CSGSFS]) 279 | 280 | #define FMT1 "%08llx" 281 | #define FMT2 "%016llx" 282 | #define FMTD "%lld" 283 | 284 | #else 285 | 286 | #define R_AX gregs[REG_EAX] 287 | #define R_BX gregs[REG_EBX] 288 | #define R_CX gregs[REG_ECX] 289 | #define R_DX gregs[REG_EDX] 290 | #define R_SI gregs[REG_ESI] 291 | #define R_DI gregs[REG_EDI] 292 | #define R_BP gregs[REG_EBP] 293 | #define R_SP gregs[REG_ESP] 294 | #define R_IP gregs[REG_EIP] 295 | #define R_CS gregs[REG_CS] 296 | 297 | #define FMT1 "%08x" 298 | #define FMT2 "%08x" 299 | #define FMTD "%d" 300 | 301 | #endif 302 | 303 | void OnSigSegv(int sig, siginfo_t* info, void* extra) 304 | { 305 | #ifdef __x86_64__ 306 | k_load_fsbase(); 307 | #endif 308 | greg_t* gregs = ((ucontext_t*)extra)->uc_mcontext.gregs; DWORD slot = k_get_slot(); 309 | DWORD* eax = (DWORD*)&R_AX; 310 | DWORD* ebx = (DWORD*)&R_BX; 311 | DWORD* ecx = (DWORD*)&R_CX; 312 | DWORD* edx = (DWORD*)&R_DX; 313 | DWORD* esi = (DWORD*)&R_SI; 314 | DWORD* edi = (DWORD*)&R_DI; 315 | DWORD* ebp = (DWORD*)&R_BP; 316 | if(R_TRAPNO==13 && R_CS == 0x0f && slot!=0) 317 | { 318 | WORD cmd = k_get_word(R_IP); 319 | if(cmd==0x40CD) 320 | { 321 | k_timespec now,timeout; DWORD x,y; QWORD q; int err=0; KERNEL_MEM* km = kernel_mem(); 322 | k_context* ctx = g_slot+slot; DWORD f_nr = *eax; 323 | switch(*eax) 324 | { 325 | case -1: 326 | exit(0); 327 | break; 328 | case 0: 329 | k_window(ctx, *ebx>>16, *ecx>>16, *ebx&0xFFFF, *ecx&0xFFFF, *edx, *edi); 330 | break; 331 | case 1: 332 | k_draw_pixel(ctx, *ebx, *ecx, *edx); 333 | break; 334 | case 2: 335 | *eax = k_get_key(ctx); 336 | break; 337 | case 3: 338 | *eax = k_bcd_time(); 339 | break; 340 | case 4: 341 | k_draw_text(ctx, *ebx>>16, *ebx&0xFFFF, user_pb(*edx), *esi, *ecx, *edi); 342 | break; 343 | case 5: 344 | k_time_get(&timeout); 345 | k_time_add_ms(&timeout, *ebx*10); 346 | for(;;) 347 | { 348 | k_time_get(&now); 349 | if(k_time_gt(&now, &timeout)) break; 350 | k_process_event(ctx); 351 | } 352 | break; 353 | case 7: 354 | k_draw_image(ctx, *edx>>16, *edx&0xFFFF, *ecx>>16, *ecx&0xFFFF, user_pb(*ebx), 24, 0, NULL); 355 | break; 356 | case 8: 357 | if (*edx>>31) 358 | { 359 | k_remove_button(ctx, *edx); 360 | } 361 | else 362 | { 363 | k_define_button(ctx, (*ebx>>16)+ctx->client_x, (*ecx>>16)+ctx->client_y, *ebx&0xFFFF, *ecx&0xFFFF, *edx); 364 | if((*edx&KBS_NO_DRAW)==0) k_draw_button(ctx, *ebx>>16, *ecx>>16, *ebx&0xFFFF, *ecx&0xFFFF, *esi); 365 | } 366 | break; 367 | case 9: 368 | k_get_slot_info(ctx, (K_SLOT_INFO*)user_mem(*ebx), *ecx); 369 | *eax = k_max_slot(); 370 | break; 371 | case 10: 372 | k_process_event(ctx); *eax = k_check_event(ctx); 373 | while(*eax == 0) { k_process_event(ctx); *eax = k_check_event(ctx); } 374 | break; 375 | case 11: 376 | k_process_event(ctx); *eax = k_check_event(ctx); 377 | break; 378 | case 12: 379 | switch(*ebx) 380 | { 381 | case 1: k_clear_buttons(ctx); break; 382 | case 2: k_clear_redraw(ctx); break; 383 | default: err = 1; break; 384 | } 385 | break; 386 | case 13: 387 | k_draw_rect(ctx, *ebx>>16, *ecx>>16, *ebx&0xFFFF, *ecx&0xFFFF, *edx); 388 | break; 389 | case 14: 390 | k_get_screen_size(&x,&y); *eax = ((x-1)<<16)+y-1; 391 | break; 392 | case 17: 393 | *eax = k_get_button(ctx); 394 | break; 395 | case 18: 396 | switch(*ebx) 397 | { 398 | case 2: k_kill_by_slot(*ecx); break; 399 | case 3: k_make_active(*ecx); break; 400 | case 4: *eax = 1<<30; break; // CPU idle clocks 401 | case 5: *eax = 1<<30; break; // CPU clock 402 | case 7: *eax = km->active_slot; break; 403 | case 14: *eax = 0; break; // TODO: wait VRTC 404 | case 16: *eax = 1<<19; break; // RAM size free KB 405 | case 17: *eax = 1<<20; break; // RAM size total KB 406 | case 18: x = k_find_slot(*ecx); if(x==0) *eax=-1; else { *eax=0; k_kill_by_slot(x); } break; 407 | case 19: // mouse settings 408 | switch(*ecx) 409 | { 410 | case 4: k_move_mouse(*edx>>16, *edx&0xFFFF); break; 411 | case 6: *eax = km->mouse_dbl_click_delay; break; 412 | case 7: km->mouse_dbl_click_delay = *edx&255; break; 413 | default: err = 1; break; 414 | } 415 | break; 416 | case 21: *eax = k_find_slot(*ecx); break; 417 | default: err = 1; break; 418 | } 419 | break; 420 | case 21: 421 | switch(*ebx) 422 | { 423 | case 2: *eax = k_set_keyboard_layout(*ecx, *edx); break; 424 | case 5: *eax = k_set_keyboard_lang(*ecx); break; 425 | case 12: *eax = 0; km->pci_enabled = *ecx; break; 426 | default: err = 1; break; 427 | } 428 | break; 429 | case 23: 430 | k_time_get(&timeout); 431 | k_time_add_ms(&timeout, *ebx*10); 432 | k_process_event(ctx); *eax = k_check_event(ctx); 433 | while(*eax == 0) 434 | { 435 | k_time_get(&now); 436 | if(k_time_gt(&now, &timeout)) break; 437 | k_process_event(ctx); *eax = k_check_event(ctx); 438 | } 439 | break; 440 | case 26: 441 | switch(*ebx) 442 | { 443 | case 2: *eax = k_get_keyboard_layout(*ecx, *edx); break; 444 | case 5: *eax = k_get_keyboard_lang(); break; 445 | case 9: k_time_get(&now); *eax = now.tv_sec*100+now.tv_nsec/10000000; break; 446 | case 10: k_time_get(&now); q = now.tv_sec*1000000000L+now.tv_nsec; *edx=q>>32; *eax=q; break; 447 | case 11: *eax = 0; break; // no lowlevel HD access 448 | case 12: *eax = km->pci_enabled; break; 449 | default: err = 1; break; 450 | } 451 | break; 452 | case 29: 453 | *eax = k_bcd_date(); 454 | break; 455 | case 30: 456 | switch(*ebx) 457 | { 458 | case 1: *eax = k_set_curpath(ctx, user_mem(*ecx), -1); break; 459 | case 2: *eax = k_get_curpath(ctx, user_mem(*ecx), -1, *edx); break; 460 | case 3: *eax = k_set_extfs(user_mem(*ecx)); break; 461 | case 4: *eax = k_set_curpath(ctx, user_mem(*ecx), *edx); break; 462 | case 5: *eax = k_get_curpath(ctx, user_mem(*ecx), *esi, *edx); break; 463 | default: err = 1; break; 464 | } 465 | break; 466 | case 34: 467 | *eax = k_get_slot_by_point(*ebx,*ecx); 468 | break; 469 | case 35: 470 | k_get_screen_size(&x, &y); 471 | *eax = k_get_pixel(ctx, *ebx%x, *ebx/x); 472 | break; 473 | case 36: 474 | k_get_image(ctx, *edx>>16, *edx&0xFFFF, *ecx>>16, *ecx&0xFFFF, user_pb(*ebx)); 475 | break; 476 | case 37: 477 | switch(*ebx) 478 | { 479 | case 0: *eax = k_get_mouse(0,0); break; 480 | case 1: *eax = k_get_mousepos(ctx,0,0); break; 481 | case 2: *eax = k_get_mousestate(ctx)&0xFF; break; 482 | case 3: *eax = k_get_mousestate(ctx); break; 483 | case 4: *eax = k_cursor_load(ctx, *ecx, *edx); break; 484 | case 5: *eax = k_cursor_set(ctx, *ecx); break; 485 | case 6: *eax = k_cursor_delete(ctx, *ecx); break; 486 | case 7: *eax = k_get_mousewheel(ctx); break; 487 | default: err = 1; break; 488 | } 489 | break; 490 | case 38: 491 | k_draw_line(ctx, *ebx>>16, *ecx>>16, *ebx&0xFFFF, *ecx&0xFFFF, *edx); 492 | break; 493 | case 40: 494 | *eax = ctx->event_mask; ctx->event_mask = *ebx; 495 | break; 496 | case 47: 497 | k_draw_num(ctx, *edx>>16, *edx&0xFFFF, *esi, *ebx, (*ebx&1)==0?ecx:user_mem(*ecx), *edi); 498 | break; 499 | case 48: 500 | switch(*ebx) 501 | { 502 | case 3: k_get_skin_colors(user_pb(*ecx), *edx); break; 503 | case 4: *eax = k_get_skin_height(); break; 504 | case 5: k_get_desktop_rect(&x,&y,eax,ebx); *eax |= x<<16; *ebx |= y<<16; break; 505 | case 6: k_set_desktop_rect(*ecx>>16, *edx>>16, *ecx&0xFFFF, *edx&0xFFFF); break; 506 | case 8: *eax = k_load_skin(ctx, user_pb(*ecx)); break; 507 | default: err = 1; break; 508 | } 509 | break; 510 | case 51: 511 | switch(*ebx) 512 | { 513 | case 1: *eax = k_new_thread(ctx, slot, *ecx, *edx); break; 514 | default: err = 1; break; 515 | } 516 | break; 517 | case 54: 518 | switch(*ebx) 519 | { 520 | case 0: *eax = km->clipboard_count; break; 521 | case 1: *eax = k_clipboard_get(*ecx); break; 522 | case 2: *eax = k_clipboard_add(*ecx, *edx); break; 523 | case 3: *eax = k_clipboard_remove_last(); break; 524 | case 4: *eax = 0; break; 525 | default: err = 1; break; 526 | } 527 | break; 528 | case 60: 529 | switch(*ebx) 530 | { 531 | case 1: *eax = 0; ctx->ipc_buffer = user_pb(*ecx); ctx->ipc_buf_len = *edx; break; 532 | case 2: *eax = k_send_ipc_message(ctx, *ecx, user_pb(*edx), *esi); break; 533 | default: err = 1; break; 534 | } 535 | break; 536 | case 61: 537 | // TODO: set gs selector 538 | switch(*ebx) 539 | { 540 | case 1: k_get_screen_size(&x,&y); *eax=(x<<16)+y; break; 541 | default: err = 1; break; 542 | } 543 | break; 544 | case 62: 545 | if(km->pci_enabled==0) { *eax = -1; break; } 546 | switch(*ebx&255) 547 | { 548 | case 0: *eax = 0x100; break; 549 | case 1: *eax = k_pci_get_last_bus(); break; 550 | case 2: *eax = 1; break; 551 | case 4: case 5: case 6: *eax = k_pci_read_reg(*ebx,*ecx); break; 552 | default: *eax = -1; break; 553 | } 554 | break; 555 | case 63: 556 | switch(*ebx) 557 | { 558 | case 1: k_debug_put(*ecx); k_putc866(*ecx); break; 559 | case 2: *eax = k_debug_get(ebx); break; 560 | default: err = 1; break; 561 | } 562 | break; 563 | case 64: 564 | switch(*ebx) 565 | { 566 | case 1: *eax = k_mem_size(*ecx); k_update_memusage(ctx); break; 567 | default: err = 1; break; 568 | } 569 | break; 570 | case 65: 571 | k_draw_image(ctx, *edx>>16, *edx&0xFFFF, *ecx>>16, *ecx&0xFFFF, user_pb(*ebx), *esi, *ebp, user_pd(*edi)); 572 | break; 573 | case 66: 574 | switch(*ebx) 575 | { 576 | case 1: ctx->kbd_mode = *ecx; break; 577 | case 2: *eax = ctx->kbd_mode; break; 578 | case 3: *eax = k_get_keyboard_modifiers(); break; 579 | case 4: *eax = k_define_hotkey(ctx, (*edx<<8)|(*ecx&0xFF)); break; 580 | case 5: *eax = k_remove_hotkey(ctx, (*edx<<8)|(*ecx&0xFF)); break; 581 | default: err = 1; break; 582 | } 583 | break; 584 | case 67: 585 | k_move_size_window(ctx, *ebx, *ecx, *edx, *esi); 586 | break; 587 | case 68: 588 | switch(*ebx) 589 | { 590 | case 1: usleep(1); break; 591 | case 11: *eax = k_heap_init(); break; 592 | case 12: *eax = k_heap_alloc(*ecx); break; 593 | case 13: *eax = k_heap_free(*ecx); break; 594 | case 16: *eax = k_driver_load(ctx, user_mem(*ecx)); break; 595 | case 17: *eax = k_driver_ioctl(ctx, user_pd(*ecx)); break; 596 | case 18: *eax = k_load_dll(ctx, user_pb(*ecx), *edx); break; 597 | case 19: *eax = k_load_dll(ctx, user_pb(*ecx), 0); break; 598 | case 20: *eax = k_heap_realloc(*edx, *ecx); break; 599 | case 22: *edx = k_usm_open(ctx, *ecx, *edx, *esi, eax); break; 600 | case 23: *eax = k_usm_close(ctx, *ecx); break; 601 | case 27: *eax = k_load_file(ctx, user_pb(*ecx), 0, edx); break; 602 | case 28: *eax = k_load_file(ctx, user_pb(*ecx), *edx, edx); break; 603 | default: err = 1; break; 604 | } 605 | k_update_memusage(ctx); 606 | break; 607 | case 70: 608 | err = k_file_syscall(ctx, eax, ebx, 0); 609 | break; 610 | case 71: 611 | k_set_title(ctx, *ecx, *ebx==1?-1:(*edx&0xFF)); 612 | break; 613 | case 72: 614 | switch(*ebx) 615 | { 616 | case 1: *eax = k_send_event(*ecx, *edx); break; 617 | default: err = 1; break; 618 | } 619 | break; 620 | case 73: 621 | k_blit_image(ctx, *ebx, *ecx); 622 | break; 623 | case 74: 624 | *eax = k_net_info(ctx, *ebx>>8, *ebx, ebx, ecx); 625 | break; 626 | case 75: 627 | *eax = k_net_socket(ctx, *ebx, ebx, *ecx, *edx, *esi, *edi); 628 | break; 629 | case 76: 630 | *eax = k_net_proto(ctx, *ebx>>16, *ebx>>8, *ebx, ebx, ecx); 631 | break; 632 | case 77: 633 | switch(*ebx) 634 | { 635 | case 0: *eax = *ecx; break; 636 | case 1: *eax = 0; break; 637 | case 2: *eax = k_futex_wait(user_mem(*ecx), *edx, *esi); break; 638 | case 3: *eax = k_futex_wake(user_mem(*ecx), *edx); break; 639 | default: err = 1; break; 640 | } 641 | break; 642 | case 80: 643 | err = k_file_syscall(ctx, eax, ebx, 1); 644 | break; 645 | default: 646 | err = 1; 647 | break; 648 | } 649 | if(err==1) 650 | { 651 | printf("%02X.%08X: mcall %d, 0x%X, 0x%X, 0x%X\n", slot, (DWORD)R_IP, f_nr, *ebx, *ecx, *edx); 652 | } 653 | #ifdef __x86_64__ 654 | R_IP = k_stub_resume(R_IP+2); 655 | k_set_fsbase(); 656 | #else 657 | R_IP += 2; 658 | #endif 659 | return; 660 | } 661 | } 662 | if(R_CS == 0x0f && slot!=0) 663 | { 664 | DWORD* stk = user_pd(R_SP); 665 | k_debug_printf("Process - forced terminate PID: %08X [%.12s]\n", g_slot[slot].tid, g_slot[slot].name); 666 | k_debug_printf("EAX : %08X EBX : %08X ECX : %08X\n", *eax, *ebx, *ecx); 667 | k_debug_printf("EDX : %08X ESI : %08X EDI : %08X\n", *edx, *esi, *edi); 668 | k_debug_printf("EBP : %08X EIP : %08X ESP : %08X\n", *ebp, (DWORD)R_IP, (DWORD)R_SP); 669 | k_debug_printf("Flags : %08X CS: 0x%08X (application)\n", (DWORD)R_FL, R_CS); 670 | k_debug_printf("Stack dump:\n"); 671 | k_debug_printf("[ESP+00]: %08X [ESP+04]: %08X [ESP+08]: %08X\n", stk[0], stk[1], stk[2]); 672 | k_debug_printf("[ESP+12]: %08X [ESP+16]: %08X [ESP+20]: %08X\n", stk[3], stk[4], stk[5]); 673 | k_debug_printf("[ESP+24]: %08X [ESP+28]: %08X [ESP+32]: %08X\n", stk[6], stk[7], stk[8]); 674 | k_debug_printf("destroy app object\n"); 675 | printf("Process: %.12s\n", g_slot[slot].name); 676 | } 677 | printf("err : 0x"FMT1" trapno: "FMTD" addr: 0x"FMT2"\n", R_ERR, R_TRAPNO, (greg_t)info->si_addr); 678 | printf("EAX : 0x"FMT2" EBX : 0x"FMT2" ECX : 0x"FMT2"\n", R_AX, R_BX, R_CX); 679 | printf("EDX : 0x"FMT2" ESI : 0x"FMT2" EDI : 0x"FMT2"\n", R_DX, R_SI, R_DI); 680 | printf("EBP : 0x"FMT2" EIP : 0x"FMT2" ESP : 0x"FMT2"\n", R_BP, R_IP, R_SP); 681 | printf("Flags : 0x"FMT1" CS: 0x%04x\n", R_FL, R_CS); 682 | FILE* fp=fopen("core.kex","wb"); fwrite(user_mem(0), 1, k_mem_get_size(), fp); fclose(fp); 683 | exit(0); 684 | }; 685 | 686 | #define stack_size 0x8000 687 | 688 | void k_syscall_init() 689 | { 690 | #ifdef __x86_64__ 691 | k_save_fsbase(); 692 | #endif 693 | 694 | stack_t altstack; 695 | struct sigaction sigsegv_action; 696 | 697 | altstack.ss_sp = malloc(stack_size); 698 | altstack.ss_flags = 0; 699 | altstack.ss_size = stack_size; 700 | sigaltstack(&altstack, NULL); 701 | 702 | sigsegv_action.sa_sigaction = OnSigSegv; 703 | sigemptyset(&sigsegv_action.sa_mask); 704 | sigsegv_action.sa_flags = SA_ONSTACK | SA_SIGINFO; 705 | sigaction(SIGSEGV, &sigsegv_action, NULL); 706 | } 707 | -------------------------------------------------------------------------------- /k_syscall.h: -------------------------------------------------------------------------------- 1 | #pragma pack(push,1) 2 | typedef struct 3 | { 4 | DWORD cputime; 5 | WORD zpos_me; 6 | WORD zpos; 7 | WORD reserved1; 8 | char name[12]; 9 | DWORD base; 10 | DWORD last; 11 | DWORD pid; 12 | DWORD window_x; 13 | DWORD window_y; 14 | DWORD window_w; 15 | DWORD window_h; 16 | WORD state; 17 | WORD reserved2; 18 | DWORD client_x; 19 | DWORD client_y; 20 | DWORD client_w; 21 | DWORD client_h; 22 | BYTE window_state; 23 | DWORD event_mask; 24 | BYTE kbd_mode; 25 | } K_SLOT_INFO; 26 | #pragma pack(pop) 27 | 28 | extern int base_pid; 29 | 30 | void k_syscall_init(); 31 | void k_set_slot(DWORD slot, int shmid, char* name); 32 | void k_set_slot_from(DWORD slot, DWORD from); 33 | DWORD k_max_slot(); 34 | DWORD k_find_slot(DWORD tid); 35 | DWORD k_get_slot_by_point(int x, int y); 36 | -------------------------------------------------------------------------------- /kex.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | handle SIGSEGV noprint nostop 67 | set detach-on-fork on 68 | set follow-fork-mode child 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | None 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | None 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "k_mem.h" 2 | #include "k_event.h" 3 | #include "k_iconv.h" 4 | #include "k_gui.h" 5 | #include "k_syscall.h" 6 | #include "k_proc.h" 7 | #include "k_file.h" 8 | #include "k_ipc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define SOCK_FILE "/tmp/kolibri.sock" 21 | 22 | int fdlist[MAX_CHILD],fcount,appcount=0; 23 | int winpos[MAX_CHILD]; 24 | 25 | k_bitmap_font font9 = {6,9}; 26 | k_bitmap_font font16 = {8,16}; 27 | 28 | void load_bitmap_font(char* name, k_bitmap_font* bf) 29 | { 30 | FILE* fp = fopen(name, "rb"); if(fp==NULL) return; 31 | fseek(fp, 0, SEEK_END); DWORD len = ftell(fp); fseek(fp, 0, SEEK_SET); 32 | bf->bmp = malloc(len); fread(bf->bmp, 1, len, fp); fclose(fp); 33 | bf->chars = len/bf->height; 34 | } 35 | 36 | int find_free(int* list, int max) 37 | { 38 | int i; for(i=1; i0; ++i) if(winpos[i]==slot) 46 | { 47 | for(; i0; ++i) winpos[i] = winpos[i+1]; 48 | break; 49 | } 50 | winpos[i] = kernel_mem()->active_slot = slot; 51 | } 52 | 53 | void update_zpos() 54 | { 55 | k_context* slot = g_slot; 56 | int i,j,max = k_max_slot(); 57 | for(i=j=1; i0; ++i) if(winpos[i]<=max) winpos[j++] = winpos[i]; 58 | for(; j0; ++j) winpos[j] = 0; 59 | for(i=1; i0; ++i) 60 | { 61 | slot[i].window_zpos = winpos[i]; 62 | slot[winpos[i]].window_zpos_me = i; 63 | } 64 | } 65 | 66 | void do_run(msg_t* msg, int fd) 67 | { 68 | int newslot = find_free(fdlist, MAX_CHILD), pid = -1; 69 | if(newslot>0) 70 | { 71 | move_to_top(newslot); 72 | int pair[2]; socketpair(AF_LOCAL, SOCK_STREAM, 0, pair); 73 | pid = fork(); 74 | if(pid==0) 75 | { // child 76 | msg_t rply; msg_reply(&rply, getpid()-base_pid); 77 | close(pair[1]); ipc_server = pair[0]; 78 | if(msg->type==MSGTYPE_RUN) 79 | { 80 | int shmid = find_free(kernel_mem()->shmtc, MAX_CHILD); 81 | k_mem_init(shmid); 82 | k_gui_init(); 83 | k_syscall_init(); 84 | k_set_skin(k_skin_open()); 85 | k_set_slot(newslot, shmid, msg->u.run.buf); 86 | if(fd>0) write_msg(fd, &rply); 87 | k_exec(g_slot+newslot, msg->u.run.buf, msg->u.run.args==0?NULL:msg->u.run.buf+msg->u.run.args); 88 | } 89 | else // MSGTYPE_CLONE 90 | { 91 | k_mem_init(g_slot[msg->u.clone.slot].shmid); 92 | k_mem_reopen(); 93 | k_gui_init(); 94 | k_syscall_init(); 95 | k_set_skin(k_skin_open()); 96 | k_set_slot_from(newslot, msg->u.clone.slot); 97 | if(fd>0) write_msg(fd, &rply); 98 | k_start_thread(msg->u.clone.eip, msg->u.clone.esp); 99 | } 100 | exit(-1); 101 | } 102 | else if(pid>0) 103 | { // self 104 | close(pair[0]); 105 | fdlist[newslot] = pair[1]; ++appcount; 106 | if(pair[1]>=fcount) fcount = pair[1]+1; 107 | } 108 | } 109 | if (pid<0) 110 | { 111 | msg_reply(msg, -1); 112 | if(fd>0) write_msg(fd, msg); 113 | } 114 | } 115 | 116 | void do_ipc_msg(msg_t* msg, int from) 117 | { 118 | msg->u.ipc.from_slot = from; 119 | int dst = msg->u.ipc.to_slot; 120 | if (g_slot[dst].tid!=0) 121 | { 122 | write_msg(fdlist[dst], msg); 123 | } 124 | else 125 | { 126 | msg_ipc(msg, from, 4, 0, NULL); 127 | write_msg(fdlist[from], msg); 128 | } 129 | } 130 | 131 | void do_focus(msg_t* msg) 132 | { 133 | move_to_top(msg->u.focus.slot); 134 | update_zpos(); 135 | } 136 | 137 | void remove_from_window_stack(int slot) 138 | { 139 | k_context* ctx = g_slot+slot; 140 | k_usm_clean(ctx); 141 | if(--kernel_mem()->shmtc[ctx->shmid]<=0) k_mem_done(ctx->shmid); 142 | memset(ctx, 0, sizeof(*ctx)); 143 | update_zpos(); 144 | } 145 | 146 | void do_load_skin(msg_t* msg) 147 | { 148 | k_load(NULL,(BYTE*)msg->u.run.buf,0,k_skin_alloc,NULL,NULL); 149 | int i; msg_load_skin(msg,NULL); 150 | for(i=1; i0) write_msg(fdlist[i], msg); 151 | } 152 | 153 | void do_driver_load(msg_t* msg, int fd) 154 | { 155 | DWORD i; KERNEL_MEM* km = kernel_mem(); char* name = msg->u.run.buf; 156 | for(i=0; idriver[i].name, 16)!=0; ++i); 157 | if(i>=MAX_DRIVER) 158 | { 159 | char path[2048]; strcpy(path, k_root); path[strlen(path)-5] = 0; 160 | strcat(path, name); strcat(path, ".so"); 161 | k_check_exists(path); 162 | if(access(path,F_OK)==0) 163 | { 164 | void* hDrv = dlopen(path, RTLD_NOW); 165 | if(hDrv!=NULL) 166 | { 167 | void* ioctl = dlsym(hDrv, "k_ioctl"); 168 | if(ioctl!=NULL) 169 | { 170 | for(i=0; idriver[i].name[0]; ++i); 171 | if(idriver[i].name, name, 16); 174 | km->driver[i].ioctl = ioctl; 175 | } 176 | } 177 | } 178 | } 179 | } 180 | msg_reply(msg, iu.ioctl.handle-1; KERNEL_MEM* km = kernel_mem(); 187 | if(idriver[i].name[0]!=0) 188 | { 189 | DWORD size; BYTE* ptr = k_mem_open_app(msg->u.ioctl.shmid, &size); 190 | if(ptr!=NULL) 191 | { 192 | ret = km->driver[i].ioctl(msg->u.ioctl.code, ptr+msg->u.ioctl.iaddr, 193 | msg->u.ioctl.ilen, ptr+msg->u.ioctl.oaddr, msg->u.ioctl.olen); 194 | k_mem_close_app(ptr, size); 195 | } 196 | } 197 | msg_reply(msg, ret); 198 | write_msg(fd, msg); 199 | } 200 | 201 | int main(int argc, char **argv) 202 | { 203 | if(argc<2) 204 | { 205 | printf("\nUse: %s kolibriapp args\n", argv[0]); 206 | return -1; 207 | } 208 | 209 | sprintf(k_root, "%s/.kex/root/", getenv("HOME")); base_pid = getpid(); 210 | 211 | char* p = strchr(k_root,0); 212 | strcpy(p, "../char.mt"); load_bitmap_font(k_root, &font9); 213 | strcpy(p, "../charUni.mt"); load_bitmap_font(k_root, &font16); *p = 0; 214 | 215 | struct sockaddr_un saddr; socklen_t addrlen; 216 | fd_set set; msg_t msg; 217 | 218 | saddr.sun_family = AF_LOCAL; 219 | strcpy(saddr.sun_path, SOCK_FILE); 220 | addrlen = sizeof(struct sockaddr_in); 221 | memset(fdlist,0,sizeof(fdlist)); 222 | memset(winpos,0,sizeof(winpos)); 223 | 224 | msg_run(&msg, argv[1], argc<3?NULL:argv[2]); 225 | 226 | int svr = socket(AF_LOCAL, SOCK_STREAM, 0),ok,i; 227 | if(connect(svr, (struct sockaddr*)&saddr, sizeof(saddr))==0) 228 | { 229 | write_msg(svr, &msg); 230 | close(svr); 231 | return 0; 232 | } 233 | unlink(SOCK_FILE); 234 | if(bind(svr, (struct sockaddr*)&saddr, sizeof(saddr))<0) return -1; 235 | listen(svr, 5); fdlist[0] = svr; fcount=svr+1; 236 | 237 | k_kernel_mem_init(); 238 | 239 | DWORD width,height; 240 | k_gui_init(); 241 | k_get_screen_size(&width, &height); 242 | k_set_desktop_rect(0, 0, width-1, height-1); 243 | 244 | k_load(NULL,(BYTE*)"DEFAULT.SKN",0,k_skin_alloc,NULL,NULL); 245 | 246 | do_run(&msg, 0); if(appcount==0) return 0; 247 | 248 | for(ok=1; ok; ) 249 | { 250 | FD_ZERO(&set); 251 | for(i=0; i0) FD_SET(fdlist[i], &set); 252 | int sel = select(fcount, &set, NULL, NULL, NULL); if(sel<0) break; 253 | for(i=0; i0 && FD_ISSET(fdlist[i], &set)) 254 | { 255 | int fd = i>0 ? fdlist[i] : accept(svr, (struct sockaddr*)&saddr, &addrlen); 256 | if(fd>0) 257 | { 258 | if(read_msg(fd, &msg)) 259 | { 260 | switch(msg.type) 261 | { 262 | case MSGTYPE_RUN: case MSGTYPE_CLONE: do_run(&msg, fd); break; 263 | case MSGTYPE_IPC: do_ipc_msg(&msg, i); break; 264 | case MSGTYPE_GOT_FOCUS: do_focus(&msg); break; 265 | case MSGTYPE_LOAD_SKIN: do_load_skin(&msg); break; 266 | case MSGTYPE_DRV_LOAD: do_driver_load(&msg, fd); break; 267 | case MSGTYPE_DRV_IOCTL: do_driver_ioctl(&msg, fd); break; 268 | } 269 | } 270 | else if(i>0) 271 | { 272 | remove_from_window_stack(i); 273 | close(fd); fdlist[i] = -1; 274 | if(--appcount<=0) ok = 0; 275 | wait(&fd); 276 | } 277 | if(i==0) close(fd); 278 | } 279 | } 280 | } 281 | close(svr); 282 | unlink(SOCK_FILE); 283 | k_kernel_mem_cleanup(); 284 | return 0; 285 | } 286 | --------------------------------------------------------------------------------