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 12 int SYS_SLEEP = 2; 13 int SOCK_SELECT = 3; 14 #define MAXSLEEPERS 1500 15 16 extern int cflag; 17 18 DWORD PlatformId; 19 DWORD consolestate; 20 static char* path; 21 static HANDLE kbdh = INVALID_HANDLE_VALUE; 22 static HANDLE conh = INVALID_HANDLE_VALUE; 23 static HANDLE errh = INVALID_HANDLE_VALUE; 24 static int donetermset = 0; 25 static int sleepers = 0; 26 27 wchar_t *widen(char *s); 28 char *narrowen(wchar_t *ws); 29 int widebytes(wchar_t *ws); 30 int runeslen(Rune*); 31 Rune* runesdup(Rune*); 32 Rune* utftorunes(Rune*, char*, int); 33 char* runestoutf(char*, Rune*, int); 34 int runescmp(Rune*, Rune*); 35 36 __declspec(thread) Proc *up; 37 38 HANDLE ntfd2h(int); 39 int nth2fd(HANDLE); 40 void termrestore(void); 41 char *hosttype = "Nt"; 42 char *cputype = "386"; 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 CloseHandle((HANDLE)p->os); 71 free(p); 72 } 73 74 void 75 osblock(void) 76 { 77 if(WaitForSingleObject((HANDLE)up->os, INFINITE) != WAIT_OBJECT_0) 78 panic("osblock failed"); 79 } 80 81 void 82 osready(Proc *p) 83 { 84 if(SetEvent((HANDLE)p->os) == FALSE) 85 panic("osready failed"); 86 } 87 88 void 89 pexit(char *msg, int t) 90 { 91 pfree(up); 92 ExitThread(0); 93 } 94 95 LONG TrapHandler(LPEXCEPTION_POINTERS ureg); 96 97 __cdecl 98 Exhandler(EXCEPTION_RECORD *rec, void *frame, CONTEXT *context, void *dcon) 99 { 100 EXCEPTION_POINTERS ep; 101 ep.ExceptionRecord = rec; 102 ep.ContextRecord = context; 103 TrapHandler(&ep); 104 return ExceptionContinueExecution; 105 } 106 107 DWORD WINAPI 108 tramp(LPVOID p) 109 { 110 up = p; 111 up->func(up->arg); 112 pexit("", 0); 113 /* not reached */ 114 for(;;) 115 panic("tramp"); 116 return 0; 117 } 118 119 void 120 kproc(char *name, void (*func)(void*), void *arg, int flags) 121 { 122 DWORD h; 123 Proc *p; 124 Pgrp *pg; 125 Fgrp *fg; 126 Egrp *eg; 127 128 p = newproc(); 129 if(p == nil) 130 panic("out of kernel processes"); 131 p->os = CreateEvent(NULL, FALSE, FALSE, NULL); 132 if(p->os == NULL) 133 panic("can't allocate os event"); 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(kbdh, buf, sizeof(buf), &r, 0) == FALSE) 208 panic("keyboard fail"); 209 if (r == 0) 210 panic("keyboard EOF"); 211 212 if (buf[0] == 0x03) { 213 // INTR (CTRL+C) 214 termrestore(); 215 ExitProcess(0); 216 } 217 if(buf[0] == '\r') 218 buf[0] = '\n'; 219 return buf[0]; 220 } 221 222 void 223 cleanexit(int x) 224 { 225 sleep(2); /* give user a chance to see message */ 226 termrestore(); 227 ExitProcess(x); 228 } 229 230 struct ecodes { 231 DWORD code; 232 char* name; 233 } ecodes[] = { 234 EXCEPTION_ACCESS_VIOLATION, "segmentation violation", 235 EXCEPTION_DATATYPE_MISALIGNMENT, "data alignment", 236 EXCEPTION_BREAKPOINT, "breakpoint", 237 EXCEPTION_SINGLE_STEP, "single step", 238 EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "array bounds check", 239 EXCEPTION_FLT_DENORMAL_OPERAND, "denormalized float", 240 EXCEPTION_FLT_DIVIDE_BY_ZERO, "floating point divide by zero", 241 EXCEPTION_FLT_INEXACT_RESULT, "inexact floating point", 242 EXCEPTION_FLT_INVALID_OPERATION, "invalid floating operation", 243 EXCEPTION_FLT_OVERFLOW, "floating point result overflow", 244 EXCEPTION_FLT_STACK_CHECK, "floating point stack check", 245 EXCEPTION_FLT_UNDERFLOW, "floating point result underflow", 246 EXCEPTION_INT_DIVIDE_BY_ZERO, "divide by zero", 247 EXCEPTION_INT_OVERFLOW, "integer overflow", 248 EXCEPTION_PRIV_INSTRUCTION, "privileged instruction", 249 EXCEPTION_IN_PAGE_ERROR, "page-in error", 250 EXCEPTION_ILLEGAL_INSTRUCTION, "illegal instruction", 251 EXCEPTION_NONCONTINUABLE_EXCEPTION, "non-continuable exception", 252 EXCEPTION_STACK_OVERFLOW, "stack overflow", 253 EXCEPTION_INVALID_DISPOSITION, "invalid disposition", 254 EXCEPTION_GUARD_PAGE, "guard page violation", 255 0, nil 256 }; 257 258 LONG 259 TrapHandler(LPEXCEPTION_POINTERS ureg) 260 { 261 int i; 262 char *name; 263 DWORD code; 264 // WORD pc; 265 char buf[ERRMAX]; 266 267 code = ureg->ExceptionRecord->ExceptionCode; 268 // pc = ureg->ContextRecord->Eip; 269 270 name = nil; 271 for(i = 0; i < nelem(ecodes); i++) { 272 if(ecodes[i].code == code) { 273 name = ecodes[i].name; 274 break; 275 } 276 } 277 278 if(name == nil) { 279 snprint(buf, sizeof(buf), "unknown trap type (%#.8lux)\n", code); 280 name = buf; 281 } 282 /* 283 if(pc != 0) { 284 snprint(buf, sizeof(buf), "%s: pc=0x%lux", name, pc); 285 name = buf; 286 } 287 */ 288 switch (code) { 289 case EXCEPTION_FLT_DENORMAL_OPERAND: 290 case EXCEPTION_FLT_DIVIDE_BY_ZERO: 291 case EXCEPTION_FLT_INEXACT_RESULT: 292 case EXCEPTION_FLT_INVALID_OPERATION: 293 case EXCEPTION_FLT_OVERFLOW: 294 case EXCEPTION_FLT_STACK_CHECK: 295 case EXCEPTION_FLT_UNDERFLOW: 296 /* clear exception flags and ensure safe empty state */ 297 _asm { fnclex }; 298 _asm { fninit }; 299 } 300 disfault(nil, name); 301 /* not reached */ 302 return EXCEPTION_CONTINUE_EXECUTION; 303 } 304 305 static void 306 termset(void) 307 { 308 DWORD flag; 309 310 if(donetermset) 311 return; 312 donetermset = 1; 313 conh = GetStdHandle(STD_OUTPUT_HANDLE); 314 kbdh = GetStdHandle(STD_INPUT_HANDLE); 315 errh = GetStdHandle(STD_ERROR_HANDLE); 316 if(errh == INVALID_HANDLE_VALUE) 317 errh = conh; 318 319 // The following will fail if kbdh not from console (e.g. a pipe) 320 // in which case we don't care 321 GetConsoleMode(kbdh, &consolestate); 322 flag = consolestate; 323 flag = flag & ~(ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT); 324 SetConsoleMode(kbdh, flag); 325 } 326 327 void 328 termrestore(void) 329 { 330 if(kbdh != INVALID_HANDLE_VALUE) 331 SetConsoleMode(kbdh, consolestate); 332 } 333 334 static int rebootok = 0; /* is shutdown -r supported? */ 335 336 void 337 osreboot(char *file, char **argv) 338 { 339 if(rebootok){ 340 termrestore(); 341 execvp(file, argv); 342 panic("reboot failure"); 343 } 344 } 345 346 void 347 libinit(char *imod) 348 { 349 WSADATA wasdat; 350 DWORD lasterror, namelen; 351 OSVERSIONINFO os; 352 char sys[64], uname[64]; 353 wchar_t wuname[64]; 354 char *uns; 355 356 os.dwOSVersionInfoSize = sizeof(os); 357 if(!GetVersionEx(&os)) 358 panic("can't get os version"); 359 PlatformId = os.dwPlatformId; 360 if (PlatformId == VER_PLATFORM_WIN32_NT) { /* true for NT and 2000 */ 361 rebootok = 1; 362 } else { 363 rebootok = 0; 364 } 365 termset(); 366 367 if((int)INVALID_HANDLE_VALUE != -1 || sizeof(HANDLE) != sizeof(int)) 368 panic("invalid handle value or size"); 369 370 if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0) 371 panic("no winsock.dll"); 372 373 gethostname(sys, sizeof(sys)); 374 kstrdup(&ossysname, sys); 375 if(sflag == 0) 376 SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)TrapHandler); 377 378 path = getenv("PATH"); 379 if(path == nil) 380 path = "."; 381 382 up = newproc(); 383 if(up == nil) 384 panic("cannot create kernel process"); 385 386 strcpy(uname, "inferno"); 387 namelen = sizeof(wuname); 388 if(GetUserName(wuname, &namelen) != TRUE) { 389 lasterror = GetLastError(); 390 if(PlatformId == VER_PLATFORM_WIN32_NT || lasterror != ERROR_NOT_LOGGED_ON) 391 print("cannot GetUserName: %d\n", lasterror); 392 }else{ 393 uns = narrowen(wuname); 394 snprint(uname, sizeof(uname), "%s", uns); 395 free(uns); 396 } 397 kstrdup(&eve, uname); 398 399 emuinit(imod); 400 } 401 402 void 403 FPsave(void *fptr) 404 { 405 _asm { 406 mov eax, fptr 407 fstenv [eax] 408 } 409 } 410 411 void 412 FPrestore(void *fptr) 413 { 414 _asm { 415 mov eax, fptr 416 fldenv [eax] 417 } 418 } 419 420 ulong 421 umult(ulong a, ulong b, ulong *high) 422 { 423 ulong lo, hi; 424 425 _asm { 426 mov eax, a 427 mov ecx, b 428 MUL ecx 429 mov lo, eax 430 mov hi, edx 431 } 432 *high = hi; 433 return lo; 434 } 435 436 int 437 close(int fd) 438 { 439 if(fd == -1) 440 return 0; 441 CloseHandle(ntfd2h(fd)); 442 return 0; 443 } 444 445 int 446 read(int fd, void *buf, uint n) 447 { 448 HANDLE h; 449 450 if(fd == 0) 451 h = kbdh; 452 else 453 h = ntfd2h(fd); 454 if(h == INVALID_HANDLE_VALUE) 455 return -1; 456 if(!ReadFile(h, buf, n, &n, NULL)) 457 return -1; 458 return n; 459 } 460 461 int 462 write(int fd, void *buf, uint n) 463 { 464 HANDLE h; 465 466 if(fd == 1 || fd == 2){ 467 if(!donetermset) 468 termset(); 469 if(fd == 1) 470 h = conh; 471 else 472 h = errh; 473 if(h == INVALID_HANDLE_VALUE) 474 return -1; 475 if(!WriteFile(h, buf, n, &n, NULL)) 476 return -1; 477 return n; 478 } 479 if(!WriteFile(ntfd2h(fd), buf, n, &n, NULL)) 480 return -1; 481 return n; 482 } 483 484 /* 485 * map handles and fds. 486 * this code assumes sizeof(HANDLE) == sizeof(int), 487 * that INVALID_HANDLE_VALUE is -1, and assumes 488 * that all tests of invalid fds check only for -1, not < 0 489 */ 490 int 491 nth2fd(HANDLE h) 492 { 493 return (int)h; 494 } 495 496 HANDLE 497 ntfd2h(int fd) 498 { 499 return (HANDLE)fd; 500 } 501 502 void 503 oslopri(void) 504 { 505 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); 506 } 507 508 /* Resolve system header name conflict */ 509 #undef Sleep 510 void 511 sleep(int secs) 512 { 513 Sleep(secs*1000); 514 } 515 516 void* 517 sbrk(int size) 518 { 519 void *brk; 520 521 brk = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 522 if(brk == 0) 523 return (void*)-1; 524 525 return brk; 526 } 527 528 ulong 529 getcallerpc(void *arg) 530 { 531 ulong cpc; 532 _asm { 533 mov eax, dword ptr [ebp] 534 mov eax, dword ptr [eax+4] 535 mov dword ptr cpc, eax 536 } 537 return cpc; 538 } 539 540 /* 541 * Return an abitrary millisecond clock time 542 */ 543 long 544 osmillisec(void) 545 { 546 return GetTickCount(); 547 } 548 549 #define SEC2MIN 60L 550 #define SEC2HOUR (60L*SEC2MIN) 551 #define SEC2DAY (24L*SEC2HOUR) 552 553 /* 554 * days per month plus days/year 555 */ 556 static int dmsize[] = 557 { 558 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 559 }; 560 static int ldmsize[] = 561 { 562 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 563 }; 564 565 /* 566 * return the days/month for the given year 567 */ 568 static int* 569 yrsize(int yr) 570 { 571 /* a leap year is a multiple of 4, excluding centuries 572 * that are not multiples of 400 */ 573 if( (yr % 4 == 0) && (yr % 100 != 0 || yr % 400 == 0) ) 574 return ldmsize; 575 else 576 return dmsize; 577 } 578 579 static long 580 tm2sec(SYSTEMTIME *tm) 581 { 582 long secs; 583 int i, *d2m; 584 585 secs = 0; 586 587 /* 588 * seconds per year 589 */ 590 for(i = 1970; i < tm->wYear; i++){ 591 d2m = yrsize(i); 592 secs += d2m[0] * SEC2DAY; 593 } 594 595 /* 596 * seconds per month 597 */ 598 d2m = yrsize(tm->wYear); 599 for(i = 1; i < tm->wMonth; i++) 600 secs += d2m[i] * SEC2DAY; 601 602 /* 603 * secs in last month 604 */ 605 secs += (tm->wDay-1) * SEC2DAY; 606 607 /* 608 * hours, minutes, seconds 609 */ 610 secs += tm->wHour * SEC2HOUR; 611 secs += tm->wMinute * SEC2MIN; 612 secs += tm->wSecond; 613 614 return secs; 615 } 616 617 /* 618 * Return the time since the epoch in microseconds 619 * The epoch is defined at 1 Jan 1970 620 */ 621 vlong 622 osusectime(void) 623 { 624 SYSTEMTIME tm; 625 vlong secs; 626 627 GetSystemTime(&tm); 628 secs = tm2sec(&tm); 629 return secs * 1000000 + tm.wMilliseconds * 1000; 630 } 631 632 vlong 633 osnsec(void) 634 { 635 return osusectime()*1000; /* TO DO better */ 636 } 637 638 int 639 osmillisleep(ulong milsec) 640 { 641 SleepEx(milsec, FALSE); 642 return 0; 643 } 644 645 int 646 limbosleep(ulong milsec) 647 { 648 if (sleepers > MAXSLEEPERS) 649 return -1; 650 sleepers++; 651 up->syscall = SYS_SLEEP; 652 SleepEx(milsec, TRUE); 653 up->syscall = 0; 654 sleepers--; 655 return 0; 656 } 657 658 void 659 osyield(void) 660 { 661 SwitchToThread(); 662 } 663 664 void 665 ospause(void) 666 { 667 for(;;) 668 sleep(1000000); 669 } 670 671 /* 672 * these should never be called, and are included 673 * as stubs since we are linking against a library which defines them 674 */ 675 int 676 open(const char *path, int how, ...) 677 { 678 panic("open"); 679 return -1; 680 } 681 682 int 683 creat(const char *path, int how) 684 { 685 panic("creat"); 686 return -1; 687 } 688 689 int 690 stat(const char *path, struct stat *sp) 691 { 692 panic("stat"); 693 return -1; 694 } 695 696 int 697 chown(const char *path, int uid, int gid) 698 { 699 panic("chown"); 700 return -1; 701 } 702 703 int 704 chmod(const char *path, int mode) 705 { 706 panic("chmod"); 707 return -1; 708 } 709 710 void 711 link(char *path, char *next) 712 { 713 panic("link"); 714 } 715 716 int 717 segflush(void *a, ulong n) 718 { 719 return 0; 720 } 721 722 wchar_t * 723 widen(char *s) 724 { 725 int n; 726 wchar_t *ws; 727 728 n = utflen(s) + 1; 729 ws = smalloc(n*sizeof(wchar_t)); 730 utftorunes(ws, s, n); 731 return ws; 732 } 733 734 735 char * 736 narrowen(wchar_t *ws) 737 { 738 char *s; 739 int n; 740 741 n = widebytes(ws); 742 s = smalloc(n); 743 runestoutf(s, ws, n); 744 return s; 745 } 746 747 748 int 749 widebytes(wchar_t *ws) 750 { 751 int n = 0; 752 753 while (*ws) 754 n += runelen(*ws++); 755 return n+1; 756 } 757