xref: /plan9/sys/src/cmd/unix/drawterm/kern/win32.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
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