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