mdbx: use MultiByteToWideChar(CP_THREAD_ACP) instead of mbstowcs().

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2022-08-09 16:12:24 +03:00
parent 6d85e35876
commit c8b1392cbe
4 changed files with 64 additions and 45 deletions

View File

@ -12971,12 +12971,8 @@ __cold static int mdbx_handle_env_pathname(MDBX_handle_env_pathname *ctx,
return MDBX_EINVAL;
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
const wchar_t *pathnameW = nullptr;
MUSTDIE_MB2WIDE(pathname, pathnameW);
const DWORD dwAttrib = GetFileAttributesW(pathnameW);
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {

View File

@ -216,26 +216,17 @@ MDBX_MAYBE_UNUSED PATH pchar_to_path(const char *c_str) {
#if defined(_WIN32) || defined(_WIN64)
#ifndef WC_ERR_INVALID_CHARS
static const DWORD WC_ERR_INVALID_CHARS =
(6 /* Windows Vista */ <= /* MajorVersion */ LOBYTE(LOWORD(GetVersion())))
? 0x00000080
: 0;
#endif /* WC_ERR_INVALID_CHARS */
template <> struct path_to_pchar<std::wstring> {
std::string str;
path_to_pchar(const std::wstring &path) {
if (!path.empty()) {
const int chars =
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(),
int(path.size()), nullptr, 0, nullptr, nullptr);
if (chars == 0)
const auto chars = mdbx_w2mb(nullptr, 0, path.data(), path.size());
if (chars < 1)
mdbx::error::throw_exception(GetLastError());
str.append(chars, '\0');
WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(),
int(path.size()), const_cast<char *>(str.data()),
chars, nullptr, nullptr);
if (!mdbx_w2mb(const_cast<char *>(str.data()), chars, path.data(),
path.size()))
mdbx::error::throw_exception(GetLastError());
}
}
operator const char *() const { return str.c_str(); }
@ -245,14 +236,14 @@ template <>
MDBX_MAYBE_UNUSED std::wstring pchar_to_path<std::wstring>(const char *c_str) {
std::wstring wstr;
if (c_str && *c_str) {
const int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str,
int(strlen(c_str)), nullptr, 0);
if (chars == 0)
const auto c_str_len = strlen(c_str);
const auto wchars = mdbx_mb2w(nullptr, 0, c_str, c_str_len);
if (wchars < 1)
mdbx::error::throw_exception(GetLastError());
wstr.append(wchars, '\0');
if (!mdbx_mb2w(const_cast<wchar_t *>(wstr.data()), wchars, c_str,
c_str_len))
mdbx::error::throw_exception(GetLastError());
wstr.append(chars, '\0');
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str,
int(strlen(c_str)), const_cast<wchar_t *>(wstr.data()),
chars);
}
return wstr;
}

View File

@ -518,14 +518,35 @@ MDBX_INTERNAL_FUNC int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) {
/*----------------------------------------------------------------------------*/
#if defined(_WIN32) || defined(_WIN64)
#ifndef WC_ERR_INVALID_CHARS
static const DWORD WC_ERR_INVALID_CHARS =
(6 /* Windows Vista */ <= /* MajorVersion */ LOBYTE(LOWORD(GetVersion())))
? 0x00000080
: 0;
#endif /* WC_ERR_INVALID_CHARS */
MDBX_INTERNAL_FUNC size_t mdbx_mb2w(wchar_t *dst, size_t dst_n, const char *src,
size_t src_n) {
return MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS, src,
(int)src_n, dst, (int)dst_n);
}
MDBX_INTERNAL_FUNC size_t mdbx_w2mb(char *dst, size_t dst_n, const wchar_t *src,
size_t src_n) {
return WideCharToMultiByte(CP_THREAD_ACP, WC_ERR_INVALID_CHARS, src,
(int)src_n, dst, (int)dst_n, nullptr, nullptr);
}
#endif /* Windows */
/*----------------------------------------------------------------------------*/
MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
const wchar_t *pathnameW = nullptr;
MUSTDIE_MB2WIDE(pathname, pathnameW);
return DeleteFileW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError();
#else
return unlink(pathname) ? errno : MDBX_SUCCESS;
@ -538,12 +559,8 @@ static bool is_valid_fd(int fd) { return !(isatty(fd) < 0 && errno == EBADF); }
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
const wchar_t *pathnameW = nullptr;
MUSTDIE_MB2WIDE(pathname, pathnameW);
return RemoveDirectoryW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError();
#else
return rmdir(pathname) ? errno : MDBX_SUCCESS;
@ -557,12 +574,8 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
*fd = INVALID_HANDLE_VALUE;
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
const wchar_t *pathnameW = nullptr;
MUSTDIE_MB2WIDE(pathname, pathnameW);
DWORD CreationDisposition = unix_mode_bits ? OPEN_ALWAYS : OPEN_EXISTING;
DWORD FlagsAndAttributes =

View File

@ -180,6 +180,11 @@ static inline void mdbx_free(void *ptr) { HeapFree(GetProcessHeap(), 0, ptr); }
#define vsnprintf _vsnprintf /* ntdll */
#endif
MDBX_INTERNAL_FUNC size_t mdbx_mb2w(wchar_t *dst, size_t dst_n, const char *src,
size_t src_n);
MDBX_INTERNAL_FUNC size_t mdbx_w2mb(char *dst, size_t dst_n, const wchar_t *src,
size_t src_n);
#else /*----------------------------------------------------------------------*/
typedef pthread_t mdbx_thread_t;
@ -549,6 +554,20 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid);
#if defined(_WIN32) || defined(_WIN64)
#define MUSTDIE_MB2WIDE(FROM, TO) \
do { \
const char *const from_tmp = (FROM); \
const size_t from_mblen = strlen(from_tmp); \
const size_t to_wlen = mdbx_mb2w(nullptr, 0, from_tmp, from_mblen); \
if (to_wlen < 1 || to_wlen > /* MAX_PATH */ INT16_MAX) \
return ERROR_INVALID_NAME; \
wchar_t *const to_tmp = _alloca((to_wlen + 1) * sizeof(wchar_t)); \
if (to_wlen + 1 != \
mdbx_mb2w(to_tmp, to_wlen + 1, from_tmp, from_mblen + 1)) \
return ERROR_INVALID_NAME; \
(TO) = to_tmp; \
} while (0)
typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *);
MDBX_INTERNAL_VAR MDBX_srwlock_function mdbx_srwlock_Init,
mdbx_srwlock_AcquireShared, mdbx_srwlock_ReleaseShared,