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