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