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