Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
448
long
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
}