1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2015-2020, Intel Corporation */
5 * util_windows.c -- misc utilities with OS-specific implementation
18 /* Windows CRT doesn't support all errors, add unmapped here */
19 #define ENOTSUP_STR "Operation not supported"
20 #define ECANCELED_STR "Operation canceled"
22 #define ENOERROR_STR "Success"
23 #define UNMAPPED_STR "Unmapped error"
26 * util_strerror -- return string describing error number
28 * XXX: There are many other POSIX error codes that are not recognized by
29 * strerror_s(), so eventually we may want to implement this in a similar
30 * fashion as strsignal().
33 util_strerror(int errnum
, char *buff
, size_t bufflen
)
37 strcpy_s(buff
, bufflen
, ENOERROR_STR
);
40 strcpy_s(buff
, bufflen
, ENOTSUP_STR
);
43 strcpy_s(buff
, bufflen
, ECANCELED_STR
);
46 if (strerror_s(buff
, bufflen
, errnum
))
47 strcpy_s(buff
, bufflen
, UNMAPPED_STR
);
52 * util_strwinerror -- return string describing windows error codes
55 util_strwinerror(unsigned long err
, char *buff
, size_t bufflen
)
59 if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
60 FORMAT_MESSAGE_FROM_SYSTEM
|
61 FORMAT_MESSAGE_IGNORE_INSERTS
,
67 sprintf_s(buff
, bufflen
, "GetLastError() == %lu", err
);
71 if (util_toUTF8_buff(error_str
, buff
, bufflen
)) {
73 sprintf_s(buff
, bufflen
, "GetLastError() == %lu", err
);
77 /* let's do the error message without '\r' and '\n' at the end */
78 size_t len
= strlen(buff
);
79 for (size_t i
= len
- 1; i
> 0; i
--) {
80 if (buff
[i
] != '\r' && buff
[i
] != '\n') {
90 * util_part_realpath -- get canonicalized absolute pathname for a part file
92 * On Windows, paths cannot be symlinks and paths used in a poolset have to
93 * be absolute (checked when parsing a poolset file), so we just return
97 util_part_realpath(const char *path
)
103 * util_compare_file_inodes -- compare device and inodes of two files
106 util_compare_file_inodes(const char *path1
, const char *path2
)
108 return strcmp(path1
, path2
) != 0;
112 * util_aligned_malloc -- allocate aligned memory
115 util_aligned_malloc(size_t alignment
, size_t size
)
117 return _aligned_malloc(size
, alignment
);
121 * util_aligned_free -- free allocated memory in util_aligned_malloc
124 util_aligned_free(void *ptr
)
130 * util_toUTF8 -- allocating conversion from wide char string to UTF8
133 util_toUTF8(const wchar_t *wstr
)
135 int size
= WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, wstr
, -1,
136 NULL
, 0, NULL
, NULL
);
140 char *str
= Malloc(size
* sizeof(char));
144 if (WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, wstr
, -1, str
,
145 size
, NULL
, NULL
) == 0) {
159 * util_free_UTF8 -- free UTF8 string
161 void util_free_UTF8(char *str
) {
166 * util_toUTF16 -- allocating conversion from UTF8 to wide char string
169 util_toUTF16(const char *str
)
171 int size
= MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, str
, -1,
176 wchar_t *wstr
= Malloc(size
* sizeof(wchar_t));
180 if (MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, str
, -1, wstr
,
195 * util_free_UTF16 -- free wide char string
198 util_free_UTF16(wchar_t *wstr
)
204 * util_toUTF16_buff -- non-allocating conversion from UTF8 to wide char string
206 * The user responsible for supplying a large enough out buffer.
209 util_toUTF16_buff(const char *in
, wchar_t *out
, size_t out_size
)
213 int size
= MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, in
,
215 if (size
== 0 || out_size
< size
)
218 if (MultiByteToWideChar(CP_UTF8
, MB_ERR_INVALID_CHARS
, in
, -1,
229 * util_toUTF8_buff -- non-allocating conversion from wide char string to UTF8
231 * The user responsible for supplying a large enough out buffer.
234 util_toUTF8_buff(const wchar_t *in
, char *out
, size_t out_size
)
238 int size
= WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, in
, -1,
239 NULL
, 0, NULL
, NULL
);
240 if (size
== 0 || out_size
< size
)
243 if (WideCharToMultiByte(CP_UTF8
, WC_ERR_INVALID_CHARS
, in
, -1,
244 out
, size
, NULL
, NULL
) == 0)
254 * util_getexecname -- return name of current executable
257 util_getexecname(char *path
, size_t pathlen
)
260 if ((cc
= GetModuleFileNameA(NULL
, path
, (DWORD
)pathlen
)) == 0)
261 strcpy(path
, "unknown");
269 * util_suppress_errmsg -- suppresses "abort" window on Windows if env variable
270 * is set, useful for automatic tests
273 util_suppress_errmsg(void)
275 if (os_getenv("PMDK_NO_ABORT_MSG") != NULL
) {
276 DWORD err
= GetErrorMode();
277 SetErrorMode(err
| SEM_NOGPFAULTERRORBOX
|
278 SEM_FAILCRITICALERRORS
);
279 _set_abort_behavior(0, _WRITE_ABORT_MSG
| _CALL_REPORTFAULT
);
283 static int Lasterror_to_errno
[16000] = {
284 [ERROR_ACCESS_DENIED
] = EACCES
,
285 [ERROR_FILE_NOT_FOUND
] = ENOENT
,
286 [ERROR_INVALID_ACCESS
] = EACCES
,
287 [ERROR_INVALID_ADDRESS
] = EINVAL
,
288 [ERROR_INVALID_FUNCTION
] = EINVAL
,
289 [ERROR_INVALID_HANDLE
] = EINVAL
,
290 [ERROR_INVALID_PARAMETER
] = EINVAL
,
291 [ERROR_LOCK_FAILED
] = EACCES
,
292 [ERROR_MAPPED_ALIGNMENT
] = EINVAL
,
293 [ERROR_NOT_ENOUGH_MEMORY
] = ENOMEM
,
294 [ERROR_NOT_SUPPORTED
] = ENOTSUP
,
295 [ERROR_OUTOFMEMORY
] = ENOMEM
,
296 [ERROR_PATH_NOT_FOUND
] = ENOENT
,
297 [ERROR_TOO_MANY_OPEN_FILES
] = EMFILE
,
301 * util_lasterror_to_errno - converts windows error codes to errno
304 util_lasterror_to_errno(unsigned long err
)
306 if (err
>= ARRAY_SIZE(Lasterror_to_errno
))
313 int ret
= Lasterror_to_errno
[err
];
315 /* 0 is used to signalize missing entry in Lasterror_to_errno array */