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*
_getproc(void)19 _getproc(void)
20 {
21 if(tlsx == TLS_OUT_OF_INDEXES)
22 return nil;
23 return TlsGetValue(tlsx);
24 }
25
26 void
_setproc(Proc * p)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
oserror(void)38 oserror(void)
39 {
40 oserrstr();
41 nexterror();
42 }
43
44 void
osinit(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
osnewproc(Proc * p)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
osmsleep(int ms)76 osmsleep(int ms)
77 {
78 Sleep((DWORD) ms);
79 }
80
81 void
osyield(void)82 osyield(void)
83 {
84 Sleep(0);
85 }
86
87 static DWORD WINAPI tramp(LPVOID vp);
88
89 void
osproc(Proc * p)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
tramp(LPVOID vp)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
procsleep(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
procwakeup(Proc * p)132 procwakeup(Proc *p)
133 {
134 Oproc *op;
135
136 op = (Oproc*)p->oproc;
137 ReleaseSemaphore(op->sema, 1, 0);
138 }
139
140 void
random20(uchar * p)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
randominit(void)165 randominit(void)
166 {
167 }
168
169 ulong
randomread(void * v,ulong n)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
seconds(void)186 seconds(void)
187 {
188 return time(0);
189 }
190
191 ulong
ticks(void)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
wstrutflen(Rune * s)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
wstrtoutf(char * s,Rune * t,int n)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
win_hasunicode(void)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
wstrlen(Rune * s)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
WinMain(HINSTANCE x,HINSTANCE y,LPSTR z,int w)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
args(char * argv[],int n,char * p)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
osrerrstr(char * buf,uint nbuf)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
oserrstr(void)443 oserrstr(void)
444 {
445 osrerrstr(up->errstr, ERRMAX);
446 }
447
448 long
showfilewrite(char * a,int n)449 showfilewrite(char *a, int n)
450 {
451 Rune *action, *arg, *cmd, *p;
452 static Rune Lopen[] = { 'o', 'p', 'e', 'n', 0 };
453
454 cmd = runesmprint("%.*s", n, a);
455 if(cmd == nil)
456 error("out of memory");
457 if(cmd[runestrlen(cmd)-1] == '\n')
458 cmd[runestrlen(cmd)] = 0;
459 p = runestrchr(cmd, ' ');
460 if(p){
461 action = cmd;
462 *p++ = 0;
463 arg = p;
464 }else{
465 action = Lopen;
466 arg = cmd;
467 }
468 ShellExecute(0, 0, action, arg, 0, SW_SHOWNORMAL);
469 return n;
470 }
471