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