1 #include <windows.h> 2 #include "u.h" 3 #include "lib.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include <libsec.h> 7 8 typedef struct Oproc Oproc; 9 struct Oproc { 10 int tid; 11 HANDLE *sema; 12 }; 13 14 static int tlsx = TLS_OUT_OF_INDEXES; 15 16 char *argv0; 17 18 Proc* 19 _getproc(void) 20 { 21 if(tlsx == TLS_OUT_OF_INDEXES) 22 return nil; 23 return TlsGetValue(tlsx); 24 } 25 26 void 27 _setproc(Proc *p) 28 { 29 if(tlsx == TLS_OUT_OF_INDEXES){ 30 tlsx = TlsAlloc(); 31 if(tlsx == TLS_OUT_OF_INDEXES) 32 panic("out of indexes"); 33 } 34 TlsSetValue(tlsx, p); 35 } 36 37 void 38 oserror(void) 39 { 40 oserrstr(); 41 nexterror(); 42 } 43 44 void 45 osinit(void) 46 { 47 Oproc *t; 48 static Proc firstprocCTstore; 49 50 _setproc(&firstprocCTstore); 51 t = (Oproc*)firstprocCTstore.oproc; 52 assert(t != 0); 53 54 t->tid = GetCurrentThreadId(); 55 t->sema = CreateSemaphore(0, 0, 1000, 0); 56 if(t->sema == 0) { 57 oserror(); 58 panic("could not create semaphore: %r"); 59 } 60 } 61 62 void 63 osnewproc(Proc *p) 64 { 65 Oproc *op; 66 67 op = (Oproc*)p->oproc; 68 op->sema = CreateSemaphore(0, 0, 1000, 0); 69 if (op->sema == 0) { 70 oserror(); 71 panic("could not create semaphore: %r"); 72 } 73 } 74 75 void 76 osmsleep(int ms) 77 { 78 Sleep((DWORD) ms); 79 } 80 81 void 82 osyield(void) 83 { 84 Sleep(0); 85 } 86 87 static DWORD WINAPI tramp(LPVOID vp); 88 89 void 90 osproc(Proc *p) 91 { 92 DWORD tid; 93 94 if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) { 95 oserror(); 96 panic("osproc: %r"); 97 } 98 99 Sleep(0); 100 } 101 102 static DWORD WINAPI 103 tramp(LPVOID vp) 104 { 105 Proc *p = (Proc *) vp; 106 Oproc *op = (Oproc*) p->oproc; 107 108 _setproc(p); 109 op->tid = GetCurrentThreadId(); 110 op->sema = CreateSemaphore(0, 0, 1000, 0); 111 if(op->sema == 0) { 112 oserror(); 113 panic("could not create semaphore: %r"); 114 } 115 116 (*p->fn)(p->arg); 117 ExitThread(0); 118 return 0; 119 } 120 121 void 122 procsleep(void) 123 { 124 Proc *p; 125 Oproc *op; 126 127 p = up; 128 op = (Oproc*)p->oproc; 129 WaitForSingleObject(op->sema, INFINITE);} 130 131 void 132 procwakeup(Proc *p) 133 { 134 Oproc *op; 135 136 op = (Oproc*)p->oproc; 137 ReleaseSemaphore(op->sema, 1, 0); 138 } 139 140 void 141 random20(uchar *p) 142 { 143 LARGE_INTEGER ti; 144 int i, j; 145 FILETIME ft; 146 DigestState ds; 147 vlong tsc; 148 149 GetSystemTimeAsFileTime(&ft); 150 memset(&ds, 0, sizeof ds); 151 sha1((uchar*)&ft, sizeof(ft), 0, &ds); 152 for(i=0; i<50; i++) { 153 for(j=0; j<10; j++) { 154 QueryPerformanceCounter(&ti); 155 sha1((uchar*)&ti, sizeof(ti), 0, &ds); 156 tsc = GetTickCount(); 157 sha1((uchar*)&tsc, sizeof(tsc), 0, &ds); 158 } 159 Sleep(10); 160 } 161 sha1(0, 0, p, &ds); 162 } 163 164 void 165 randominit(void) 166 { 167 } 168 169 ulong 170 randomread(void *v, ulong n) 171 { 172 int i; 173 uchar p[20]; 174 175 for(i=0; i<n; i+=20){ 176 random20(p); 177 if(i+20 <= n) 178 memmove((char*)v+i, p, 20); 179 else 180 memmove((char*)v+i, p, n-i); 181 } 182 return n; 183 } 184 185 long 186 seconds(void) 187 { 188 return time(0); 189 } 190 191 ulong 192 ticks(void) 193 { 194 return GetTickCount(); 195 } 196 197 #if 0 198 uvlong 199 fastticks(uvlong *v) 200 { 201 uvlong n; 202 203 n = GetTickCount() * 1000 * 1000; 204 if(v) 205 *v = n; 206 return n; 207 } 208 #endif 209 210 extern int main(int, char*[]); 211 212 213 int 214 wstrutflen(Rune *s) 215 { 216 int n; 217 218 for(n=0; *s; n+=runelen(*s),s++) 219 ; 220 return n; 221 } 222 223 int 224 wstrtoutf(char *s, Rune *t, int n) 225 { 226 int i; 227 char *s0; 228 229 s0 = s; 230 if(n <= 0) 231 return wstrutflen(t)+1; 232 while(*t) { 233 if(n < UTFmax+1 && n < runelen(*t)+1) { 234 *s = 0; 235 return s-s0+wstrutflen(t)+1; 236 } 237 i = runetochar(s, t); 238 s += i; 239 n -= i; 240 t++; 241 } 242 *s = 0; 243 return s-s0; 244 } 245 246 int 247 win_hasunicode(void) 248 { 249 OSVERSIONINFOA osinfo; 250 int r; 251 252 osinfo.dwOSVersionInfoSize = sizeof(osinfo); 253 if(!GetVersionExA(&osinfo)) 254 panic("GetVersionEx failed"); 255 switch(osinfo.dwPlatformId) { 256 default: 257 panic("unknown PlatformId"); 258 case VER_PLATFORM_WIN32s: 259 panic("Win32s not supported"); 260 case VER_PLATFORM_WIN32_WINDOWS: 261 r = 0; 262 break; 263 case VER_PLATFORM_WIN32_NT: 264 r = 1; 265 break; 266 } 267 268 return r; 269 } 270 271 int 272 wstrlen(Rune *s) 273 { 274 int n; 275 276 for(n=0; *s; s++,n++) 277 ; 278 return n; 279 } 280 static int args(char *argv[], int n, char *p); 281 282 int APIENTRY 283 WinMain(HINSTANCE x, HINSTANCE y, LPSTR z, int w) 284 { 285 int argc, n; 286 char *arg, *p, **argv; 287 Rune *warg; 288 289 if(0 && win_hasunicode()){ 290 warg = GetCommandLineW(); 291 n = (wstrlen(warg)+1)*UTFmax; 292 arg = malloc(n); 293 wstrtoutf(arg, warg, n); 294 }else 295 arg = GetCommandLineA(); 296 297 /* conservative guess at the number of args */ 298 for(argc=4,p=arg; *p; p++) 299 if(*p == ' ' || *p == '\t') 300 argc++; 301 argv = malloc(argc*sizeof(char*)); 302 argc = args(argv, argc, arg); 303 304 mymain(argc, argv); 305 ExitThread(0); 306 return 0; 307 } 308 309 /* 310 * Break the command line into arguments 311 * The rules for this are not documented but appear to be the following 312 * according to the source for the microsoft C library. 313 * Words are seperated by space or tab 314 * Words containing a space or tab can be quoted using " 315 * 2N backslashes + " ==> N backslashes and end quote 316 * 2N+1 backslashes + " ==> N backslashes + literal " 317 * N backslashes not followed by " ==> N backslashes 318 */ 319 static int 320 args(char *argv[], int n, char *p) 321 { 322 char *p2; 323 int i, j, quote, nbs; 324 325 for(i=0; *p && i<n-1; i++) { 326 while(*p == ' ' || *p == '\t') 327 p++; 328 quote = 0; 329 argv[i] = p2 = p; 330 for(;*p; p++) { 331 if(!quote && (*p == ' ' || *p == '\t')) 332 break; 333 for(nbs=0; *p == '\\'; p++,nbs++) 334 ; 335 if(*p == '"') { 336 for(j=0; j<(nbs>>1); j++) 337 *p2++ = '\\'; 338 if(nbs&1) 339 *p2++ = *p; 340 else 341 quote = !quote; 342 } else { 343 for(j=0; j<nbs; j++) 344 *p2++ = '\\'; 345 *p2++ = *p; 346 } 347 } 348 /* move p up one to avoid pointing to null at end of p2 */ 349 if(*p) 350 p++; 351 *p2 = 0; 352 } 353 argv[i] = 0; 354 355 return i; 356 } 357 /* 358 * Windows socket error messages 359 * There must be a way to get these strings out of the library. 360 * This table is derived from the MSDN online help. 361 */ 362 static struct { 363 int e; 364 char *s; 365 } tab[] = { 366 { 10004, "interrupted function call" }, 367 { 10013, "permission denied" }, 368 { 10014, "bad address" }, 369 { 10022, "invalid argument" }, 370 { 10024, "too many open files" }, 371 { 10035, "resource temporarily unavailable" }, 372 { 10036, "operation now in progress" }, 373 { 10037, "operation already in progress" }, 374 { 10038, "socket operation on nonsocket" }, 375 { 10039, "destination address required" }, 376 { 10040, "message too long" }, 377 { 10041, "protocol wrong type for socket" }, 378 { 10042, "bad protocol option" }, 379 { 10043, "protocol not supported" }, 380 { 10044, "socket type not supported" }, 381 { 10045, "operation not supported" }, 382 { 10046, "protocol family not supported" }, 383 { 10047, "address family not supported by protocol family" }, 384 { 10048, "address already in use" }, 385 { 10049, "cannot assign requested address" }, 386 { 10050, "network is down" }, 387 { 10051, "network is unreachable" }, 388 { 10052, "network dropped connection on reset" }, 389 { 10053, "software caused connection abort" }, 390 { 10054, "connection reset by peer" }, 391 { 10055, "no buffer space available" }, 392 { 10056, "socket is already connected" }, 393 { 10057, "socket is not connected" }, 394 { 10058, "cannot send after socket shutdown" }, 395 { 10060, "connection timed out" }, 396 { 10061, "connection refused" }, 397 { 10064, "host is down" }, 398 { 10065, "no route to host" }, 399 { 10067, "too many processes" }, 400 { 10091, "network subsystem is unavailable" }, 401 { 10092, "winsock.dll version out of range" }, 402 { 10093, "wsastartup not called" }, 403 { 10101, "graceful shutdown in progress" }, 404 { 10109, "class type not found" }, 405 { 11001, "host name not found" }, 406 { 11002, "host not found (non-authoritative)" }, 407 { 11003, "nonrecoverable error" }, 408 { 11004, "valid name, but no data record of requested type" }, 409 }; 410 411 void 412 osrerrstr(char *buf, uint nbuf) 413 { 414 char *p, *q; 415 int e, i, r; 416 417 e = GetLastError(); 418 r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 419 0, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 420 buf, nbuf, 0); 421 if(r == 0){ 422 for(i=0; i<nelem(tab); i++) 423 if(tab[i].e == e){ 424 strecpy(buf, buf+nbuf, tab[i].s); 425 break; 426 } 427 if(i==nelem(tab)) 428 snprint(buf, nbuf, "windows error %d", e); 429 } 430 431 for(p=q=buf; *p; p++) { 432 if(*p == '\r') 433 continue; 434 if(*p == '\n') 435 *q++ = ' '; 436 else 437 *q++ = *p; 438 } 439 *q = '\0'; 440 } 441 442 void 443 oserrstr(void) 444 { 445 osrerrstr(up->errstr, ERRMAX); 446 } 447