add GHC.HetMet.{hetmet_kappa,hetmet_kappa_app}
[ghc-base.git] / cbits / Win32Utils.c
1 /* ----------------------------------------------------------------------------
2    (c) The University of Glasgow 2006
3    
4    Useful Win32 bits
5    ------------------------------------------------------------------------- */
6
7 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
8
9 #include "HsBase.h"
10
11 /* This is the error table that defines the mapping between OS error
12    codes and errno values */
13
14 struct errentry {
15         unsigned long oscode;           /* OS return value */
16         int errnocode;  /* System V error code */
17 };
18
19 static struct errentry errtable[] = {
20         {  ERROR_INVALID_FUNCTION,       EINVAL    },  /* 1 */
21         {  ERROR_FILE_NOT_FOUND,         ENOENT    },  /* 2 */
22         {  ERROR_PATH_NOT_FOUND,         ENOENT    },  /* 3 */
23         {  ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },  /* 4 */
24         {  ERROR_ACCESS_DENIED,          EACCES    },  /* 5 */
25         {  ERROR_INVALID_HANDLE,         EBADF     },  /* 6 */
26         {  ERROR_ARENA_TRASHED,          ENOMEM    },  /* 7 */
27         {  ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },  /* 8 */
28         {  ERROR_INVALID_BLOCK,          ENOMEM    },  /* 9 */
29         {  ERROR_BAD_ENVIRONMENT,        E2BIG     },  /* 10 */
30         {  ERROR_BAD_FORMAT,             ENOEXEC   },  /* 11 */
31         {  ERROR_INVALID_ACCESS,         EINVAL    },  /* 12 */
32         {  ERROR_INVALID_DATA,           EINVAL    },  /* 13 */
33         {  ERROR_INVALID_DRIVE,          ENOENT    },  /* 15 */
34         {  ERROR_CURRENT_DIRECTORY,      EACCES    },  /* 16 */
35         {  ERROR_NOT_SAME_DEVICE,        EXDEV     },  /* 17 */
36         {  ERROR_NO_MORE_FILES,          ENOENT    },  /* 18 */
37         {  ERROR_LOCK_VIOLATION,         EACCES    },  /* 33 */
38         {  ERROR_BAD_NETPATH,            ENOENT    },  /* 53 */
39         {  ERROR_NETWORK_ACCESS_DENIED,  EACCES    },  /* 65 */
40         {  ERROR_BAD_NET_NAME,           ENOENT    },  /* 67 */
41         {  ERROR_FILE_EXISTS,            EEXIST    },  /* 80 */
42         {  ERROR_CANNOT_MAKE,            EACCES    },  /* 82 */
43         {  ERROR_FAIL_I24,               EACCES    },  /* 83 */
44         {  ERROR_INVALID_PARAMETER,      EINVAL    },  /* 87 */
45         {  ERROR_NO_PROC_SLOTS,          EAGAIN    },  /* 89 */
46         {  ERROR_DRIVE_LOCKED,           EACCES    },  /* 108 */
47         {  ERROR_BROKEN_PIPE,            EPIPE     },  /* 109 */
48         {  ERROR_DISK_FULL,              ENOSPC    },  /* 112 */
49         {  ERROR_INVALID_TARGET_HANDLE,  EBADF     },  /* 114 */
50         {  ERROR_INVALID_HANDLE,         EINVAL    },  /* 124 */
51         {  ERROR_WAIT_NO_CHILDREN,       ECHILD    },  /* 128 */
52         {  ERROR_CHILD_NOT_COMPLETE,     ECHILD    },  /* 129 */
53         {  ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },  /* 130 */
54         {  ERROR_NEGATIVE_SEEK,          EINVAL    },  /* 131 */
55         {  ERROR_SEEK_ON_DEVICE,         EACCES    },  /* 132 */
56         {  ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },  /* 145 */
57         {  ERROR_NOT_LOCKED,             EACCES    },  /* 158 */
58         {  ERROR_BAD_PATHNAME,           ENOENT    },  /* 161 */
59         {  ERROR_MAX_THRDS_REACHED,      EAGAIN    },  /* 164 */
60         {  ERROR_LOCK_FAILED,            EACCES    },  /* 167 */
61         {  ERROR_ALREADY_EXISTS,         EEXIST    },  /* 183 */
62         {  ERROR_FILENAME_EXCED_RANGE,   ENOENT    },  /* 206 */
63         {  ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },  /* 215 */
64            /* Windows returns this when the read end of a pipe is
65             * closed (or closing) and we write to it. */
66         {  ERROR_NO_DATA,                EPIPE     },  /* 232 */
67         {  ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }  /* 1816 */
68 };
69
70 /* size of the table */
71 #define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))
72
73 /* The following two constants must be the minimum and maximum
74    values in the (contiguous) range of Exec Failure errors. */
75 #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
76 #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
77
78 /* These are the low and high value in the range of errors that are
79    access violations */
80 #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
81 #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
82
83 void maperrno (void)
84 {
85         int i;
86         DWORD dwErrorCode;
87
88         dwErrorCode = GetLastError();
89
90         /* check the table for the OS error code */
91         for (i = 0; i < ERRTABLESIZE; ++i)
92         {
93                 if (dwErrorCode == errtable[i].oscode)
94                 {
95                         errno = errtable[i].errnocode;
96                         return;
97                 }
98         }
99
100         /* The error code wasn't in the table.  We check for a range of */
101         /* EACCES errors or exec failure errors (ENOEXEC).  Otherwise   */
102         /* EINVAL is returned.                                          */
103
104         if (dwErrorCode >= MIN_EACCES_RANGE && dwErrorCode <= MAX_EACCES_RANGE)
105                 errno = EACCES;
106         else
107                 if (dwErrorCode >= MIN_EXEC_ERROR && dwErrorCode <= MAX_EXEC_ERROR)
108                         errno = ENOEXEC;
109                 else
110                         errno = EINVAL;
111 }
112
113 HsWord64 getUSecOfDay(void)
114 {
115     HsWord64 t;
116     FILETIME ft;
117     GetSystemTimeAsFileTime(&ft);
118     t = ((HsWord64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
119     t = t / 10LL;
120     /* FILETIMES are in units of 100ns,
121        so we divide by 10 to get microseconds */
122     return t;
123 }
124
125 #endif
126