source: trunk/source/lisp-kernel/windows-calls.c @ 10697

Last change on this file since 10697 was 10697, checked in by gb, 12 years ago

windows_find_symbol() handle nonsense.

File size: 10.7 KB
Line 
1/*
2   Copyright (C) 2008, Clozure Associates and contributors,
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17#include "lisp.h"
18#include "x86-exceptions.h"
19#include <io.h>
20#include <unistd.h>
21#include <sys/fcntl.h>
22#include <errno.h>
23#include <sys/stat.h>
24#include <windows.h>
25#include <psapi.h>
26#include <dirent.h>
27#include <stdio.h>
28
29
30#ifndef WIN_32
31#define _dosmaperr mingw_dosmaperr
32#else
33void
34_dosmaperr(unsigned long oserrno)
35{
36  switch(oserrno) {
37  case  ERROR_INVALID_FUNCTION:
38    errno = EINVAL;
39    break;
40  case ERROR_FILE_NOT_FOUND:
41    errno = ENOENT;
42    break;
43  case ERROR_PATH_NOT_FOUND:
44    errno = ENOENT;
45    break;
46  case  ERROR_TOO_MANY_OPEN_FILES:
47    errno = EMFILE;
48    break;
49  case  ERROR_ACCESS_DENIED:
50    errno = EACCES;
51    break;
52  case  ERROR_ARENA_TRASHED:
53    errno = ENOMEM;
54    break;
55  case  ERROR_NOT_ENOUGH_MEMORY:
56    errno = ENOMEM;
57    break;
58  case  ERROR_INVALID_BLOCK:
59    errno = ENOMEM;
60    break;
61  case  ERROR_BAD_ENVIRONMENT:
62    errno = E2BIG;
63    break;
64  case  ERROR_BAD_FORMAT:
65    errno = ENOEXEC;
66    break;
67  case  ERROR_INVALID_ACCESS:
68    errno = EINVAL;
69    break;
70  case  ERROR_INVALID_DATA:
71    errno = EINVAL;
72    break;
73  case  ERROR_INVALID_DRIVE:
74    errno = ENOENT;
75    break;
76  case  ERROR_CURRENT_DIRECTORY:
77    errno = EACCES;
78    break;
79  case  ERROR_NOT_SAME_DEVICE:
80    errno = EXDEV;
81    break;
82  case  ERROR_NO_MORE_FILES:
83    errno = ENOENT;
84    break;
85  case  ERROR_LOCK_VIOLATION:
86    errno = EACCES;
87    break;
88  case  ERROR_BAD_NETPATH:
89    errno = ENOENT;
90    break;
91  case  ERROR_NETWORK_ACCESS_DENIED:
92    errno = EACCES;
93    break;
94  case  ERROR_BAD_NET_NAME:
95    errno = ENOENT;
96    break;
97  case  ERROR_FILE_EXISTS:
98    errno = EEXIST;
99    break;
100  case  ERROR_CANNOT_MAKE:
101    errno = EACCES;
102    break;
103  case  ERROR_FAIL_I24:
104    errno = EACCES;
105    break;
106  case  ERROR_INVALID_PARAMETER:
107    errno = EINVAL;
108    break;
109  case  ERROR_NO_PROC_SLOTS:
110    errno = EAGAIN;
111    break;
112  case  ERROR_DRIVE_LOCKED:
113    errno = EACCES;
114    break;
115  case  ERROR_BROKEN_PIPE:
116    errno = EPIPE;
117    break;
118  case  ERROR_DISK_FULL:
119    errno = ENOSPC;
120    break;
121  case  ERROR_INVALID_TARGET_HANDLE:
122    errno = EBADF;
123    break;
124  case  ERROR_INVALID_HANDLE:
125    errno = EINVAL;
126    break;
127  case  ERROR_WAIT_NO_CHILDREN:
128    errno = ECHILD;
129    break;
130  case  ERROR_CHILD_NOT_COMPLETE:
131    errno = ECHILD;
132    break;
133  case  ERROR_DIRECT_ACCESS_HANDLE:
134    errno = EBADF;
135    break;
136  case  ERROR_NEGATIVE_SEEK:
137    errno = EINVAL;
138    break;
139  case  ERROR_SEEK_ON_DEVICE:   
140    errno = EACCES;
141    break;
142  case  ERROR_DIR_NOT_EMPTY:
143    errno = ENOTEMPTY;
144    break;
145  case  ERROR_NOT_LOCKED:
146    errno = EACCES;
147    break;
148  case  ERROR_BAD_PATHNAME:
149    errno = ENOENT;
150    break;
151  case  ERROR_MAX_THRDS_REACHED:
152    errno = EAGAIN;
153    break;
154  case  ERROR_LOCK_FAILED:
155    errno = EACCES;
156    break;
157  case  ERROR_ALREADY_EXISTS:
158    errno = EEXIST;
159    break;
160  case  ERROR_FILENAME_EXCED_RANGE:
161    errno = ENOENT;
162    break;
163  case  ERROR_NESTING_NOT_ALLOWED:
164    errno = EAGAIN;
165    break;
166  case  ERROR_NOT_ENOUGH_QUOTA:
167    errno = ENOMEM;
168    break;
169  default:
170    errno = EINVAL;
171    break;
172  }
173}
174   
175#endif
176
177
178
179int
180lisp_open(wchar_t *path, int flag, int mode)
181{
182  int fd;
183  HANDLE hfile;
184  DWORD dwDesiredAccess = 0;
185  DWORD dwShareMode = 0;
186  DWORD dwCreationDistribution = 0;
187  DWORD dwFlagsAndAttributes = 0;
188  SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
189
190  if ((flag & S_IREAD) == S_IREAD) {
191    dwShareMode = FILE_SHARE_READ;
192  } else {
193    if ((flag & S_IWRITE) == S_IWRITE) {
194      dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
195    }
196  }
197
198  if ((flag & _O_WRONLY) == _O_WRONLY) {
199    dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
200      FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
201  } else if ((flag & _O_RDWR) == _O_RDWR) {
202    dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
203      FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
204  } else {
205    dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
206      FILE_WRITE_ATTRIBUTES;
207  }
208   
209  if ((flag & S_IREAD) == S_IREAD) {
210    dwShareMode |= FILE_SHARE_READ;
211  }
212  if ((flag & S_IWRITE) == S_IWRITE) {
213    dwShareMode |= FILE_SHARE_WRITE;
214  }
215
216  if ((flag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
217    dwCreationDistribution |= CREATE_NEW;
218  } else if ((flag &  O_TRUNC) == O_TRUNC) {
219    if ((flag &  O_CREAT) ==  O_CREAT) {
220      dwCreationDistribution |= CREATE_ALWAYS;
221    } else if ((flag & O_RDONLY) != O_RDONLY) {
222      dwCreationDistribution |= TRUNCATE_EXISTING;
223    }
224  } else if ((flag & _O_APPEND) == _O_APPEND) {
225    dwCreationDistribution |= OPEN_EXISTING;
226  } else if ((flag &  _O_CREAT) == _O_CREAT) {
227    dwCreationDistribution |= OPEN_ALWAYS;
228  } else {
229    dwCreationDistribution |= OPEN_EXISTING;
230  }
231  if ((flag &  _O_RANDOM) == _O_RANDOM) {
232    dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
233  }
234  if ((flag &  _O_SEQUENTIAL) == _O_SEQUENTIAL) {
235    dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
236  }
237
238  if ((flag &  _O_TEMPORARY) == _O_TEMPORARY) {
239    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
240  }
241
242  if ((flag &  _O_SHORT_LIVED) == _O_SHORT_LIVED) {
243    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
244  }
245
246  if (flag & _O_NOINHERIT) {
247    sa.bInheritHandle = FALSE;
248  }
249
250#if 0
251  dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
252#endif
253   
254
255  hfile = CreateFileW(path,
256                      dwDesiredAccess,
257                      dwShareMode,
258                      &sa,
259                      dwCreationDistribution,
260                      dwFlagsAndAttributes,
261                      NULL);
262  if (hfile == ((HANDLE)-1)) {
263    _dosmaperr(GetLastError());
264    return -errno;
265  }
266  fd = _open_osfhandle((intptr_t)hfile, flag);
267
268  if (fd < 0) {
269    CloseHandle(hfile);
270  }
271  return fd;
272}
273
274int
275lisp_close(int fd)
276{
277  return close(fd);
278}
279
280int
281lisp_read(int fd, void *buf, unsigned int count)
282{
283  HANDLE hfile;
284  OVERLAPPED overlapped;
285  DWORD err, nread;
286  pending_io pending;
287  TCR *tcr;
288  extern TCR *get_tcr(int);
289
290  hfile = (HANDLE) _get_osfhandle(fd);
291
292  if (hfile == ((HANDLE)-1)) {
293    return -EBADF;
294  }
295 
296  memset(&overlapped,0,sizeof(overlapped));
297
298  if (GetFileType(hfile) == FILE_TYPE_DISK) {
299    overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT);
300  }
301
302  tcr = (TCR *)get_tcr(1);
303  pending.h = hfile;
304  pending.o = &overlapped;
305  tcr->foreign_exception_status = (signed_natural)&pending;
306
307  if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
308    tcr->foreign_exception_status = 0;
309    return nread;
310  }
311  err = GetLastError();
312
313  if (err == ERROR_HANDLE_EOF) {
314    tcr->foreign_exception_status = 0;
315    return 0;
316  }
317
318  if (err != ERROR_IO_PENDING) {
319    _dosmaperr(err);
320    tcr->foreign_exception_status = 0;
321    return -1;
322  }
323 
324  /* We block here */
325  if (GetOverlappedResult(hfile, &overlapped, &nread, TRUE)) {
326    tcr->foreign_exception_status = 0;
327    return nread;
328  }
329  err = GetLastError();
330  tcr->foreign_exception_status = 0;
331
332  switch (err) {
333  case ERROR_HANDLE_EOF: 
334    return 0;
335  case ERROR_OPERATION_ABORTED:
336    errno = EINTR;
337    return -1;
338  default:
339    _dosmaperr(err);
340    return -1;
341  }
342}
343
344int
345lisp_write(int fd, void *buf, unsigned int count)
346{
347  return _write(fd, buf, count);
348}
349
350int
351lisp_fchmod(int fd, int mode)
352{
353  errno = ENOSYS;
354  return -1;
355}
356
357off_t
358lisp_lseek(int fd, __int64 offset, int whence)
359{
360  return lseek64(fd, offset, whence);
361}
362
363int
364lisp_stat(wchar_t *path, struct __stat64 *buf)
365{
366  return _wstat64(path,buf);
367}
368
369int
370lisp_fstat(int fd, struct __stat64 *buf)
371{
372  return _fstat64(fd,buf);
373}
374
375int
376lisp_futex(int *uaddr, int op, int val, void *timeout, int *uaddr2, int val3)
377{
378  errno = ENOSYS;
379  return -1;
380}
381
382
383__int64
384lisp_ftruncate(int fd, __int64 new_size)
385{
386  /* Note that _ftruncate only allows 32-bit length */
387  return ftruncate(fd,(off_t)new_size);
388}
389
390_WDIR *
391lisp_opendir(wchar_t *path)
392{
393  return _wopendir(path);
394}
395
396struct _wdirent *
397lisp_readdir(_WDIR *dir)
398{
399  return _wreaddir(dir);
400}
401
402__int64
403lisp_closedir(_WDIR *dir)
404{
405  return _wclosedir(dir);
406}
407
408int
409lisp_pipe(int fd[2])
410{
411  HANDLE input, output;
412  SECURITY_ATTRIBUTES sa;
413
414  sa.nLength= sizeof(SECURITY_ATTRIBUTES);
415  sa.lpSecurityDescriptor = NULL;
416  sa.bInheritHandle = TRUE;
417
418  if (!CreatePipe(&input, &output, &sa, 0))
419    {
420      wperror("CreatePipe");
421      return -1;
422    }
423  fd[0] = _open_osfhandle((intptr_t)input, 0);
424  fd[1] = _open_osfhandle((intptr_t)output, 0);
425  return 0;
426}
427
428
429HMODULE *modules = NULL;
430DWORD cbmodules = 0;
431
432void *
433windows_find_symbol(void *handle, char *name)
434{
435  if ((handle == ((void *)-2L)) ||
436      (handle == ((void *)-1L))) {
437    handle = NULL;
438  }
439  if (handle != NULL) {
440    return GetProcAddress(handle, name);
441  } else {
442    DWORD cbneeded,  have, i;
443
444    if (cbmodules == 0) {
445      cbmodules = 16 * sizeof(HANDLE);
446      modules = LocalAlloc(LPTR, cbmodules);
447    }
448   
449    while (1) {
450      EnumProcessModules(GetCurrentProcess(),modules,cbmodules,&cbneeded);
451      if (cbmodules >= cbneeded) {
452        break;
453      }
454      cbmodules = cbneeded;
455      modules = LocalReAlloc(modules,cbmodules,0);
456    }
457    have = cbneeded/sizeof(HANDLE);
458
459    for (i = 0; i < have; i++) {
460      void *addr = GetProcAddress(modules[i],name);
461
462      if (addr) {
463        return addr;
464      }
465    }
466    return NULL;
467  }
468}
469
470void
471init_windows_io()
472{
473#if 0
474  int fd;
475  HANDLE hfile0, hfile1;
476
477  hfile0 = (HANDLE) _get_osfhandle(0);
478  hfile1 = ReOpenFile(hfile0,GENERIC_READ,FILE_SHARE_READ,FILE_FLAG_OVERLAPPED);
479  if (hfile1 != ((HANDLE)-1)) {
480    fd = _open_osfhandle(hfile1,O_RDONLY);
481    dup2(fd,0);
482    _close(fd);
483    SetStdHandle(STD_INPUT_HANDLE,hfile1);
484    CloseHandle(hfile0);
485  } else {
486    wperror("ReOpenFile");
487  }
488
489  hfile0 = (HANDLE) _get_osfhandle(1);
490  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
491  if (hfile1 != ((HANDLE)-1)) {
492    fd = _open_osfhandle(hfile1,O_WRONLY);
493    dup2(fd,1);
494    _close(fd);
495    SetStdHandle(STD_OUTPUT_HANDLE,hfile1);
496    CloseHandle(hfile0);
497  }
498
499  hfile0 = (HANDLE) _get_osfhandle(2);
500  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
501  if (hfile1 != ((HANDLE)-1)) {
502    fd = _open_osfhandle(hfile1,O_WRONLY);
503    dup2(fd,2);
504    _close(fd);
505    SetStdHandle(STD_ERROR_HANDLE,hfile1);
506    CloseHandle(hfile0);
507  }
508#endif 
509}
510
511void
512init_winsock()
513{
514  WSADATA data;
515
516  WSAStartup((2<<8)|2,&data);
517}
Note: See TracBrowser for help on using the repository browser.