1 #define Unknown win_Unknown 2 #define UNICODE 3 #include <windows.h> 4 #include <winbase.h> 5 #include <winsock.h> 6 #undef Unknown 7 #include <excpt.h> 8 #include "dat.h" 9 #include "fns.h" 10 #include "error.h" 11 #include "ieplugin.h" 12 13 extern int SYS_SLEEP = 2; 14 extern int SOCK_SELECT = 3; 15 #define MAXSLEEPERS 1500 16 17 extern Plugin* plugin; 18 extern void newiop(); 19 extern int sendiop(); 20 21 DWORD PlatformId; 22 static char* path; 23 static HANDLE kbdh = INVALID_HANDLE_VALUE; 24 static HANDLE conh = INVALID_HANDLE_VALUE; 25 static int sleepers; 26 27 static ulong erendezvous(void*, ulong); 28 29 wchar_t *widen(char *s); 30 char *narrowen(wchar_t *ws); 31 int widebytes(wchar_t *ws); 32 int runeslen(Rune*); 33 Rune* runesdup(Rune*); 34 Rune* utftorunes(Rune*, char*, int); 35 char* runestoutf(char*, Rune*, int); 36 int runescmp(Rune*, Rune*); 37 38 __declspec(thread) Proc *up; 39 40 HANDLE ntfd2h(int); 41 int nth2fd(HANDLE); 42 char *hosttype = "Nt"; 43 44 static void 45 pfree(Proc *p) 46 { 47 Osenv *e; 48 49 lock(&procs.l); 50 if(p->prev) 51 p->prev->next = p->next; 52 else 53 procs.head = p->next; 54 55 if(p->next) 56 p->next->prev = p->prev; 57 else 58 procs.tail = p->prev; 59 unlock(&procs.l); 60 61 e = p->env; 62 if(e != nil) { 63 closefgrp(e->fgrp); 64 closepgrp(e->pgrp); 65 closeegrp(e->egrp); 66 closesigs(e->sigs); 67 } 68 free(e->user); 69 free(p->prog); 70 free(p); 71 } 72 73 void 74 osblock(void) 75 { 76 erendezvous(up, 0); 77 } 78 79 void 80 osready(Proc *p) 81 { 82 erendezvous(p, 0); 83 } 84 85 86 void 87 pexit(char *msg, int t) 88 { 89 pfree(up); 90 ExitThread(0); 91 } 92 93 LONG TrapHandler(LPEXCEPTION_POINTERS ureg); 94 95 __cdecl 96 Exhandler(EXCEPTION_RECORD *rec, void *frame, CONTEXT *context, void *dcon) 97 { 98 EXCEPTION_POINTERS ep; 99 ep.ExceptionRecord = rec; 100 ep.ContextRecord = context; 101 TrapHandler(&ep); 102 return ExceptionContinueExecution; 103 } 104 105 DWORD WINAPI 106 tramp(LPVOID p) 107 { 108 // install our own exception handler 109 // replacing all others installed on this thread 110 DWORD handler = (DWORD)Exhandler; 111 _asm { 112 mov eax,handler 113 push eax 114 mov eax,-1 115 push eax 116 mov fs:[0],esp 117 } 118 119 up = p; 120 up->func(up->arg); 121 pexit("", 0); 122 // should never get here but tidy up anyway 123 _asm { 124 mov fs:[0],-1 125 add esp, 8 126 } 127 return 0; 128 } 129 130 int 131 kproc(char *name, void (*func)(void*), void *arg, int flags) 132 { 133 DWORD h; 134 Proc *p; 135 Pgrp *pg; 136 Fgrp *fg; 137 Egrp *eg; 138 139 p = newproc(); 140 if(p == nil){ 141 print("out of kernel processes\n"); 142 return -1; 143 } 144 145 if(flags & KPDUPPG) { 146 pg = up->env->pgrp; 147 incref(&pg->r); 148 p->env->pgrp = pg; 149 } 150 if(flags & KPDUPFDG) { 151 fg = up->env->fgrp; 152 incref(&fg->r); 153 p->env->fgrp = fg; 154 } 155 if(flags & KPDUPENVG) { 156 eg = up->env->egrp; 157 incref(&eg->r); 158 p->env->egrp = eg; 159 } 160 161 p->env->ui = up->env->ui; 162 kstrdup(&p->env->user, up->env->user); 163 strcpy(p->text, name); 164 165 p->func = func; 166 p->arg = arg; 167 168 lock(&procs.l); 169 if(procs.tail != nil) { 170 p->prev = procs.tail; 171 procs.tail->next = p; 172 } 173 else { 174 procs.head = p; 175 p->prev = nil; 176 } 177 procs.tail = p; 178 unlock(&procs.l); 179 180 p->pid = (int)CreateThread(0, 16384, tramp, p, 0, &h); 181 if(p->pid <= 0){ 182 pfree(p); 183 print("ran out of kernel processes\n"); 184 return -1; 185 } 186 return p->pid; 187 } 188 189 #if(_WIN32_WINNT >= 0x0400) 190 void APIENTRY sleepintr(DWORD param) 191 { 192 } 193 #endif 194 195 void 196 oshostintr(Proc *p) 197 { 198 if (p->syscall == SOCK_SELECT) 199 return; 200 p->intwait = 0; 201 #if(_WIN32_WINNT >= 0x0400) 202 if(p->syscall == SYS_SLEEP) { 203 QueueUserAPC(sleepintr, (HANDLE) p->pid, (DWORD) p->pid); 204 } 205 #endif 206 } 207 208 void 209 oslongjmp(void *regs, osjmpbuf env, int val) 210 { 211 USED(regs); 212 longjmp(env, val); 213 } 214 215 int 216 readkbd(void) 217 { 218 DWORD r; 219 char buf[1]; 220 221 if(ReadFile(plugin->conin, buf, sizeof(buf), &r, 0) == FALSE) 222 panic("keyboard fail"); 223 if (r == 0) 224 panic("keyboard EOF"); 225 226 if(buf[0] == '\r') 227 buf[0] = '\n'; 228 return buf[0]; 229 } 230 231 void 232 cleanexit(int x) 233 { 234 newiop(); 235 IOP.op = Iquit; 236 sendiop(); 237 ExitProcess(x); 238 } 239 240 struct ecodes { 241 DWORD code; 242 char* name; 243 } ecodes[] = { 244 EXCEPTION_ACCESS_VIOLATION, "Segmentation violation", 245 EXCEPTION_DATATYPE_MISALIGNMENT, "Data Alignment", 246 EXCEPTION_BREAKPOINT, "Breakpoint", 247 EXCEPTION_SINGLE_STEP, "SingleStep", 248 EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Check", 249 EXCEPTION_FLT_DENORMAL_OPERAND, "Denormalized Float", 250 EXCEPTION_FLT_DIVIDE_BY_ZERO, "Floating Point Divide by Zero", 251 EXCEPTION_FLT_INEXACT_RESULT, "Inexact Floating Point", 252 EXCEPTION_FLT_INVALID_OPERATION, "Invalid Floating Operation", 253 EXCEPTION_FLT_OVERFLOW, "Floating Point Result Overflow", 254 EXCEPTION_FLT_STACK_CHECK, "Floating Point Stack Check", 255 EXCEPTION_FLT_UNDERFLOW, "Floating Point Result Underflow", 256 EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by Zero", 257 EXCEPTION_INT_OVERFLOW, "Integer Overflow", 258 EXCEPTION_PRIV_INSTRUCTION, "Privileged Instruction", 259 EXCEPTION_IN_PAGE_ERROR, "Page-in Error", 260 EXCEPTION_ILLEGAL_INSTRUCTION, "Illegal Instruction", 261 EXCEPTION_NONCONTINUABLE_EXCEPTION, "Non-Continuable Exception", 262 EXCEPTION_STACK_OVERFLOW, "Stack Overflow", 263 EXCEPTION_INVALID_DISPOSITION, "Invalid Disposition", 264 EXCEPTION_GUARD_PAGE, "Guard Page Violation", 265 0, nil 266 }; 267 268 void 269 dodisfault(void) 270 { 271 disfault(nil, up->env->errstr); 272 } 273 274 typedef struct Ereg Ereg; 275 struct Ereg { 276 Ereg *prev; 277 FARPROC handler; 278 }; 279 280 void 281 dumpex() 282 { 283 Ereg *er; 284 int i; 285 _asm { mov eax,fs:[0] }; 286 _asm { mov [er],eax }; 287 288 i = 0; 289 while ((unsigned)er != ~0) { 290 print("handler %ux\n", er->handler); 291 i++; 292 er = er->prev; 293 } 294 print("EXCEPTION CHAIN LENGTH = %d\n", i); 295 } 296 297 LONG 298 TrapHandler(LPEXCEPTION_POINTERS ureg) 299 { 300 int i; 301 char *name; 302 DWORD code; 303 // WORD pc; 304 char buf[ERRMAX]; 305 306 code = ureg->ExceptionRecord->ExceptionCode; 307 // pc = ureg->ContextRecord->Eip; 308 309 name = nil; 310 for(i = 0; i < nelem(ecodes); i++) { 311 if(ecodes[i].code == code) { 312 name = ecodes[i].name; 313 break; 314 } 315 } 316 317 if(name == nil) { 318 snprint(buf, sizeof(buf), "Unrecognized Machine Trap (%.8lux)\n", code); 319 name = buf; 320 } 321 /* 322 if(pc != 0) { 323 snprint(buf, sizeof(buf), "%s: pc=0x%lux", name, pc); 324 name = buf; 325 } 326 */ 327 /* YUCK! */ 328 strncpy(up->env->errstr, name, ERRMAX); 329 switch (code) { 330 case EXCEPTION_FLT_DENORMAL_OPERAND: 331 case EXCEPTION_FLT_DIVIDE_BY_ZERO: 332 case EXCEPTION_FLT_INEXACT_RESULT: 333 case EXCEPTION_FLT_INVALID_OPERATION: 334 case EXCEPTION_FLT_OVERFLOW: 335 case EXCEPTION_FLT_STACK_CHECK: 336 case EXCEPTION_FLT_UNDERFLOW: 337 /* clear exception flags and register stack */ 338 _asm { fnclex }; 339 ureg->ContextRecord->FloatSave.StatusWord = 0x0000; 340 ureg->ContextRecord->FloatSave.TagWord = 0xffff; 341 } 342 ureg->ContextRecord->Eip = (DWORD)dodisfault; 343 return EXCEPTION_CONTINUE_EXECUTION; 344 } 345 346 static int rebootok = 0; /* is shutdown -r supported? */ 347 348 void 349 osreboot(char *file, char **argv) 350 { 351 if(rebootok){ 352 execvp(file, argv); 353 panic("reboot failure"); 354 }else 355 error("reboot option not supported on this system"); 356 } 357 358 void 359 libinit(char *imod) 360 { 361 WSADATA wasdat; 362 // DWORD lasterror, namelen; 363 OSVERSIONINFO os; 364 // char sys[64]; 365 366 os.dwOSVersionInfoSize = sizeof(os); 367 if(!GetVersionEx(&os)) 368 panic("can't get os version"); 369 PlatformId = os.dwPlatformId; 370 if (PlatformId == VER_PLATFORM_WIN32_NT) { /* true for NT and 2000 */ 371 rebootok = 1; 372 } else { 373 rebootok = 0; 374 } 375 376 if((int)INVALID_HANDLE_VALUE != -1 || sizeof(HANDLE) != sizeof(int)) 377 panic("invalid handle value or size"); 378 379 if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0) 380 panic("no winsock.dll"); 381 382 // gethostname(sys, sizeof(sys)); 383 // kstrdup(&ossysname, sys); 384 kstrdup(&ossysname, "plugin"); 385 386 // if(sflag == 0) 387 // SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TrapHandler); 388 389 path = getenv("PATH"); 390 if(path == nil) 391 path = "."; 392 393 up = newproc(); 394 if(up == nil) 395 panic("cannot create kernel process"); 396 397 kstrdup(&eve, "system"); 398 emuinit(imod); 399 } 400 401 enum 402 { 403 NHLOG = 7, 404 NHASH = (1<<NHLOG) 405 }; 406 407 typedef struct Tag Tag; 408 struct Tag 409 { 410 void* tag; 411 ulong val; 412 HANDLE pid; 413 Tag* next; 414 }; 415 416 static Tag* ht[NHASH]; 417 static Tag* ft; 418 static Lock hlock; 419 static int nsema; 420 421 ulong 422 erendezvous(void *tag, ulong value) 423 { 424 int h; 425 ulong rval; 426 Tag *t, **l, *f; 427 428 429 h = (ulong)tag & (NHASH-1); 430 431 lock(&hlock); 432 l = &ht[h]; 433 for(t = ht[h]; t; t = t->next) { 434 if(t->tag == tag) { 435 rval = t->val; 436 t->val = value; 437 t->tag = 0; 438 unlock(&hlock); 439 if(SetEvent(t->pid) == FALSE) 440 panic("Release failed\n"); 441 return rval; 442 } 443 } 444 445 t = ft; 446 if(t == 0) { 447 t = malloc(sizeof(Tag)); 448 if(t == nil) 449 panic("rendezvous: no memory"); 450 t->pid = CreateEvent(0, 0, 0, 0); 451 } 452 else 453 ft = t->next; 454 455 t->tag = tag; 456 t->val = value; 457 t->next = *l; 458 *l = t; 459 unlock(&hlock); 460 461 if(WaitForSingleObject(t->pid, INFINITE) != WAIT_OBJECT_0) 462 panic("WaitForSingleObject failed\n"); 463 464 lock(&hlock); 465 rval = t->val; 466 for(f = *l; f; f = f->next) { 467 if(f == t) { 468 *l = f->next; 469 break; 470 } 471 l = &f->next; 472 } 473 t->next = ft; 474 ft = t; 475 unlock(&hlock); 476 477 return rval; 478 } 479 480 void 481 FPsave(void *fptr) 482 { 483 _asm { 484 mov eax, fptr 485 fstenv [eax] 486 } 487 } 488 489 void 490 FPrestore(void *fptr) 491 { 492 _asm { 493 mov eax, fptr 494 fldenv [eax] 495 } 496 } 497 498 ulong 499 umult(ulong a, ulong b, ulong *high) 500 { 501 ulong lo, hi; 502 503 _asm { 504 mov eax, a 505 mov ecx, b 506 MUL ecx 507 mov lo, eax 508 mov hi, edx 509 } 510 *high = hi; 511 return lo; 512 } 513 514 int 515 close(int fd) 516 { 517 if(fd != -1) 518 CloseHandle(ntfd2h(fd)); 519 return 0; 520 } 521 522 int 523 read(int fd, void *buf, uint n) 524 { 525 if(!ReadFile(ntfd2h(fd), buf, n, &n, NULL)) 526 return -1; 527 return n; 528 } 529 530 int 531 write(int fd, void *buf, uint n) 532 { 533 if(fd == 1 || fd == 2){ 534 int w; 535 if (plugin->conout == NULL) 536 return n; 537 if (!WriteFile(plugin->conout, buf, n, &w, NULL) || n != w) 538 abort(); 539 return n; 540 } 541 if(!WriteFile(ntfd2h(fd), buf, n, &n, NULL)) 542 return -1; 543 return n; 544 } 545 546 /* 547 * map handles and fds. 548 * this code assumes sizeof(HANDLE) == sizeof(int), 549 * that INVALID_HANDLE_VALUE is -1, and assumes 550 * that all tests of invalid fds check only for -1, not < 0 551 */ 552 int 553 nth2fd(HANDLE h) 554 { 555 return (int)h; 556 } 557 558 HANDLE 559 ntfd2h(int fd) 560 { 561 return (HANDLE)fd; 562 } 563 564 void 565 oslopri(void) 566 { 567 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); 568 } 569 570 /* Resolve system header name conflict */ 571 #undef Sleep 572 void 573 sleep(int secs) 574 { 575 Sleep(secs*1000); 576 } 577 578 void* 579 sbrk(int size) 580 { 581 void *brk; 582 583 brk = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 584 if(brk == 0) 585 return (void*)-1; 586 587 return brk; 588 } 589 590 ulong 591 getcallerpc(void *arg) 592 { 593 ulong cpc; 594 _asm { 595 mov eax, dword ptr [ebp] 596 mov eax, dword ptr [eax+4] 597 mov dword ptr cpc, eax 598 } 599 return cpc; 600 } 601 602 /* 603 ulong 604 getpc(void *arg, ulong *narg) 605 { 606 ulong *a = arg, *fp, pc; 607 608 if(a == nil){ 609 *narg = 0; 610 return 0; 611 } 612 fp = a-2; 613 pc = fp[1]; 614 fp = *(ulong**)fp; 615 if(fp == nil) 616 *narg = 0; 617 else 618 *narg = (ulong)(fp+2); 619 return pc; 620 } 621 */ 622 623 /* 624 * Return an abitrary millisecond clock time 625 */ 626 long 627 osmillisec(void) 628 { 629 return GetTickCount(); 630 } 631 632 #define SEC2MIN 60L 633 #define SEC2HOUR (60L*SEC2MIN) 634 #define SEC2DAY (24L*SEC2HOUR) 635 636 /* 637 * days per month plus days/year 638 */ 639 static int dmsize[] = 640 { 641 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 642 }; 643 static int ldmsize[] = 644 { 645 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 646 }; 647 648 /* 649 * return the days/month for the given year 650 */ 651 static int* 652 yrsize(int yr) 653 { 654 /* a leap year is a multiple of 4, excluding centuries 655 * that are not multiples of 400 */ 656 if( (yr % 4 == 0) && (yr % 100 != 0 || yr % 400 == 0) ) 657 return ldmsize; 658 else 659 return dmsize; 660 } 661 662 static long 663 tm2sec(SYSTEMTIME *tm) 664 { 665 long secs; 666 int i, *d2m; 667 668 secs = 0; 669 670 /* 671 * seconds per year 672 */ 673 for(i = 1970; i < tm->wYear; i++){ 674 d2m = yrsize(i); 675 secs += d2m[0] * SEC2DAY; 676 } 677 678 /* 679 * seconds per month 680 */ 681 d2m = yrsize(tm->wYear); 682 for(i = 1; i < tm->wMonth; i++) 683 secs += d2m[i] * SEC2DAY; 684 685 /* 686 * secs in last month 687 */ 688 secs += (tm->wDay-1) * SEC2DAY; 689 690 /* 691 * hours, minutes, seconds 692 */ 693 secs += tm->wHour * SEC2HOUR; 694 secs += tm->wMinute * SEC2MIN; 695 secs += tm->wSecond; 696 697 return secs; 698 } 699 700 /* 701 * Return the time since the epoch in microseconds 702 * The epoch is defined at 1 Jan 1970 703 */ 704 vlong 705 osusectime(void) 706 { 707 SYSTEMTIME tm; 708 vlong secs; 709 710 GetSystemTime(&tm); 711 secs = tm2sec(&tm); 712 return secs * 1000000 + tm.wMilliseconds * 1000; 713 } 714 715 vlong 716 osnsec(void) 717 { 718 return osusectime()*1000; /* TO DO better */ 719 } 720 721 int 722 osmillisleep(ulong milsec) 723 { 724 up->syscall = 1; 725 SleepEx(milsec, FALSE); 726 up->syscall = 0; 727 return 0; 728 } 729 730 int 731 limbosleep(ulong milsec) 732 { 733 if (sleepers > MAXSLEEPERS) 734 return -1; 735 sleepers++; 736 up->syscall = SYS_SLEEP; 737 SleepEx(milsec, TRUE); 738 up->syscall = 0; 739 sleepers--; 740 return 0; 741 } 742 743 void 744 osyield(void) 745 { 746 sleep(0); 747 } 748 749 void 750 ospause(void) 751 { 752 for(;;) 753 sleep(1000000); 754 } 755 756 /* 757 * these should never be called, and are included 758 * as stubs since we are linking against a library which defines them 759 */ 760 int 761 open(const char *path, int how, ...) 762 { 763 panic("open"); 764 return -1; 765 } 766 767 int 768 creat(const char *path, int how) 769 { 770 panic("creat"); 771 return -1; 772 } 773 774 int 775 stat(const char *path, struct stat *sp) 776 { 777 panic("stat"); 778 return -1; 779 } 780 781 int 782 chown(const char *path, int uid, int gid) 783 { 784 panic("chown"); 785 return -1; 786 } 787 788 int 789 chmod(const char *path, int mode) 790 { 791 panic("chmod"); 792 return -1; 793 } 794 795 void 796 link(char *path, char *next) 797 { 798 panic("link"); 799 } 800 801 int 802 segflush(void *a, ulong n) 803 { 804 return 0; 805 } 806 807 wchar_t * 808 widen(char *s) 809 { 810 int n; 811 wchar_t *ws; 812 813 n = utflen(s) + 1; 814 ws = smalloc(n*sizeof(wchar_t)); 815 utftorunes(ws, s, n); 816 return ws; 817 } 818 819 820 char * 821 narrowen(wchar_t *ws) 822 { 823 char *s; 824 int n; 825 826 n = widebytes(ws); 827 s = smalloc(n); 828 runestoutf(s, ws, n); 829 return s; 830 } 831 832 833 int 834 widebytes(wchar_t *ws) 835 { 836 int n = 0; 837 838 while (*ws) 839 n += runelen(*ws++); 840 return n+1; 841 } 842