-
Notifications
You must be signed in to change notification settings - Fork 36
/
Win32Utils.c
159 lines (137 loc) · 6.13 KB
/
Win32Utils.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* ----------------------------------------------------------------------------
(c) The University of Glasgow 2006
Useful Win32 bits
------------------------------------------------------------------------- */
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
#include "HsBase.h"
/* This is the error table that defines the mapping between OS error
codes and errno values */
struct errentry {
unsigned long oscode; /* OS return value */
int errnocode; /* System V error code */
};
static struct errentry errtable[] = {
{ ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
{ ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
{ ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */
{ ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */
{ ERROR_ACCESS_DENIED, EACCES }, /* 5 */
{ ERROR_INVALID_HANDLE, EBADF }, /* 6 */
{ ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */
{ ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */
{ ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */
{ ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */
{ ERROR_INVALID_ACCESS, EINVAL }, /* 12 */
{ ERROR_INVALID_DATA, EINVAL }, /* 13 */
{ ERROR_INVALID_DRIVE, ENOENT }, /* 15 */
{ ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */
{ ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */
{ ERROR_NO_MORE_FILES, ENOENT }, /* 18 */
{ ERROR_LOCK_VIOLATION, EACCES }, /* 33 */
{ ERROR_BAD_NETPATH, ENOENT }, /* 53 */
{ ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */
{ ERROR_BAD_NET_NAME, ENOENT }, /* 67 */
{ ERROR_FILE_EXISTS, EEXIST }, /* 80 */
{ ERROR_CANNOT_MAKE, EACCES }, /* 82 */
{ ERROR_FAIL_I24, EACCES }, /* 83 */
{ ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */
{ ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */
{ ERROR_DRIVE_LOCKED, EACCES }, /* 108 */
{ ERROR_BROKEN_PIPE, EPIPE }, /* 109 */
{ ERROR_DISK_FULL, ENOSPC }, /* 112 */
{ ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */
{ ERROR_INVALID_HANDLE, EINVAL }, /* 124 */
{ ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */
{ ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */
{ ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */
{ ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */
{ ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */
{ ERROR_NOT_LOCKED, EACCES }, /* 158 */
{ ERROR_BAD_PATHNAME, ENOENT }, /* 161 */
{ ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */
{ ERROR_LOCK_FAILED, EACCES }, /* 167 */
{ ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
{ ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */
/* Windows returns this when the read end of a pipe is
* closed (or closing) and we write to it. */
{ ERROR_NO_DATA, EPIPE }, /* 232 */
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */
};
/* size of the table */
#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))
/* The following two constants must be the minimum and maximum
values in the (contiguous) range of Exec Failure errors. */
#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
/* These are the low and high value in the range of errors that are
access violations */
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
void maperrno (void)
{
int i;
DWORD dwErrorCode;
dwErrorCode = GetLastError();
/* check the table for the OS error code */
for (i = 0; i < ERRTABLESIZE; ++i)
{
if (dwErrorCode == errtable[i].oscode)
{
errno = errtable[i].errnocode;
return;
}
}
/* The error code wasn't in the table. We check for a range of */
/* EACCES errors or exec failure errors (ENOEXEC). Otherwise */
/* EINVAL is returned. */
if (dwErrorCode >= MIN_EACCES_RANGE && dwErrorCode <= MAX_EACCES_RANGE)
errno = EACCES;
else
if (dwErrorCode >= MIN_EXEC_ERROR && dwErrorCode <= MAX_EXEC_ERROR)
errno = ENOEXEC;
else
errno = EINVAL;
}
// Number of ticks per second used by the QueryPerformanceFrequency
// implementaiton, represented by a 64-bit union type.
static LARGE_INTEGER qpc_frequency = {.QuadPart = 0};
// Initialize qpc_frequency. This function should be called before any call to
// getMonotonicUSec. If QPC is not supported on this system, qpc_frequency is
// set to 0.
void initializeTimer()
{
BOOL qpc_supported = QueryPerformanceFrequency(&qpc_frequency);
if (!qpc_supported)
{
qpc_frequency.QuadPart = 0;
}
}
HsWord64 getMonotonicUSec()
{
if (qpc_frequency.QuadPart)
{
// system_time is a 64-bit union type used to represent the
// tick count returned by QueryPerformanceCounter
LARGE_INTEGER system_time;
// get the tick count.
QueryPerformanceCounter(&system_time);
// compute elapsed seconds as double
double secs = (double)system_time.QuadPart /
(double)qpc_frequency.QuadPart;
// return elapsed time in microseconds
return (HsWord64)(secs * 1e6);
}
else // fallback to GetTickCount
{
// NOTE: GetTickCount is a 32-bit millisecond value, so it wraps around
// every 49 days.
DWORD count = GetTickCount();
// getTickCount is in milliseconds, so multiply it by 1000 to get
// microseconds.
return (HsWord64)count * 1000;
}
}
#endif