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