-
Notifications
You must be signed in to change notification settings - Fork 2
/
OSCore.c
205 lines (169 loc) · 4.8 KB
/
OSCore.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/***************************************************************************************************************:')
OSCore.c
Include the main Linux and Windows headers. Some Windows types ported to Linux.
Debug and error handling functions, macros and strings.
Fabrice Le Bars
Created : 2007
***************************************************************************************************************:)*/
// Prevent Visual Studio Intellisense from defining _WIN32 and _MSC_VER when we use
// Visual Studio to edit Linux or Borland C++ code.
#ifdef __linux__
# undef _WIN32
#endif // __linux__
#if defined(__GNUC__) || defined(__BORLANDC__)
# undef _MSC_VER
#endif // defined(__GNUC__) || defined(__BORLANDC__)
#include "OSCore.h"
const char* szOSUtilsErrMsgs[] = {
"The operation completed successfully. ", // EXIT_SUCCESS
"The operation failed. ", // EXIT_FAILURE
"The operation timed out. ", // EXIT_TIMEOUT
"The parameter is incorrect. ", // EXIT_INVALID_PARAMETER
"Invalid data. ", // EXIT_INVALID_DATA
"Name too long. ", // EXIT_NAME_TOO_LONG
"Out of memory. ", // EXIT_OUT_OF_MEMORY
"The object is nonsignaled. ", // EXIT_OBJECT_NONSIGNALED
"Cannot create another system semaphore. ", // EXIT_TOO_MANY_SEMAPHORES
"The thread was killed. ", // EXIT_KILLED_THREAD
"The thread was canceled. ", // EXIT_CANCELED_THREAD
"Overlapped I/O operation is in progress. ", // EXIT_IO_PENDING
"The process was killed. ", // EXIT_KILLED_PROCESS
"Element changed. ", // EXIT_CHANGED
"Element not changed. ", // EXIT_NOT_CHANGED
"Element found. ", // EXIT_FOUND
"Element not found. ", // EXIT_NOT_FOUND
"Not implemented. ", // EXIT_NOT_IMPLEMENTED
""
};
/*
Format a message corresponding to the last error in a system call (thread-
safe).
char* buf : (INOUT) Valid pointer to a buffer that will receive the message.
int buflen : (IN) Size of the buffer in bytes.
Return : buf or NULL if buf is too small.
*/
char* FormatLastErrorMsg(char* buf, int buflen)
{
#ifdef _WIN32
TCHAR* tstr = NULL;
#endif // _WIN32
if (buflen < 32)
{
return NULL;
}
#ifdef _WIN32
tstr = (TCHAR*)calloc((size_t)buflen, sizeof(TCHAR));
memset(buf, 0, (size_t)buflen);
if (tstr == NULL)
{
sprintf(buf, "calloc failed. ");
buf[buflen-1] = 0;
return buf;
}
memset(tstr, 0, (size_t)(buflen*sizeof(TCHAR)));
if (!FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, // Remove the line break at the end.
// Note that there is still a dot and a space at the end.
NULL,
GetLastError(),
0,
tstr,
(DWORD)buflen,
NULL
))
{
sprintf(buf, "FormatMessage failed. ");
buf[buflen-1] = 0;
free(tstr); tstr = NULL;
return buf;
}
#ifdef UNICODE
wcstombs(buf, tstr, buflen);
#else
memcpy(buf, tstr, buflen);
#endif // UNICODE
buf[buflen-1] = 0;
free(tstr); tstr = NULL;
#else
char* lpMsgBuf = (char*)calloc((size_t)buflen, sizeof(char));
memset(buf, 0, (size_t)buflen);
if (lpMsgBuf == NULL)
{
sprintf(buf, "calloc failed. ");
buf[buflen-1] = 0;
return buf;
}
memset(lpMsgBuf, 0, (size_t)buflen);
// Note that pthreads do not use errno!
#if defined(__ANDROID__) || defined(__APPLE__)
if (strerror_r(errno, lpMsgBuf, (size_t)buflen-3) == EXIT_SUCCESS)
{
// Here the use of snprintf() is mandatory to be sure that buf do not overflow...
snprintf(buf, (size_t)buflen, "%s. ", lpMsgBuf);
}
else
{
sprintf(buf, "strerror_r failed. ");
}
#else
// GNU version of strerror_r() is strange...
// Here the use of snprintf() is mandatory to be sure that buf do not overflow...
snprintf(buf, (size_t)buflen, "%s. ", strerror_r(errno, lpMsgBuf, (size_t)buflen-3));
#endif // defined(__ANDROID__) || defined(__APPLE__)
buf[buflen-1] = 0;
free(lpMsgBuf); lpMsgBuf = NULL;
#endif // _WIN32
return buf;
}
#ifdef _DEBUG_DISPLAY
void fprintf_stdout(const char * _Format, ...)
{
va_list VaList;
va_start(VaList, _Format);
vfprintf(stdout, _Format, VaList);
fflush(stdout);
va_end(VaList);
}
void fprintf_stderr(const char * _Format, ...)
{
va_list VaList;
va_start(VaList, _Format);
vfprintf(stderr, _Format, VaList);
fflush(stderr);
va_end(VaList);
}
#endif // _DEBUG_DISPLAY
#ifdef _DEBUG_FILE
void fprintf_messages_file(const char * _Format, ...)
{
FILE* file;
va_list VaList;
va_start(VaList, _Format);
file = fopen(MESSAGES_FILENAME, "a");
vfprintf(file, _Format, VaList);
fclose(file);
va_end(VaList);
}
void fprintf_warnings_file(const char * _Format, ...)
{
FILE* file;
va_list VaList;
va_start(VaList, _Format);
file = fopen(WARNINGS_FILENAME, "a");
vfprintf(file, _Format, VaList);
fclose(file);
va_end(VaList);
}
void fprintf_errors_file(const char * _Format, ...)
{
FILE* file;
va_list VaList;
va_start(VaList, _Format);
file = fopen(ERRORS_FILENAME, "a");
vfprintf(file, _Format, VaList);
fclose(file);
va_end(VaList);
}
#endif // _DEBUG_FILE