Add StringWiden function

StringWiden converts a narrow C-style string to a wide string. It serves the opposite role of StringNarrow function. The function is useful on Windows platforms where the OS favors wide functions with the UTF-16 character set. For example, the Data Proction API (DPAPI) allows a description, but its a wide character C-string. There is no narrwo version of the API.
This commit is contained in:
Jeffrey Walton 2017-03-17 04:57:38 -04:00
parent e55560e1a2
commit c90a63196a
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 80 additions and 3 deletions

View File

@ -197,6 +197,70 @@ std::string StringNarrow(const wchar_t *str, bool throwOnError)
return result;
}
std::wstring StringWiden(const char *str, bool throwOnError)
{
CRYPTOPP_ASSERT(str);
std::wstring result;
// Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
#if (CRYPTOPP_MSC_VERSION >= 1400)
size_t len=0, size=0;
errno_t err = 0;
//const char* ptr = str;
//while (*ptr++) len++;
len = std::strlen(str)+1;
err = mbstowcs_s(&size, NULLPTR, 0, str, len);
CRYPTOPP_ASSERT(err == 0);
if (err != 0)
{
if (throwOnError)
throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
else
return std::wstring();
}
result.resize(size);
err = mbstowcs_s(&size, &result[0], size, str, len);
CRYPTOPP_ASSERT(err == 0);
if (err != 0)
{
if (throwOnError)
throw InvalidArgument("StringWiden: wcstombs_s() call failed with error " + IntToString(err));
else
return std::wstring();
}
// The safe routine's size includes the NULL.
if (!result.empty() && result[size - 1] == '\0')
result.erase(size - 1);
#else
size_t size = mbstowcs(NULLPTR, str, 0);
CRYPTOPP_ASSERT(size != (size_t)-1);
if (size == (size_t)-1)
{
if (throwOnError)
throw InvalidArgument("StringWiden: mbstowcs() call failed");
else
return std::wstring();
}
result.resize(size);
size = mbstowcs(&result[0], str, size);
CRYPTOPP_ASSERT(size != (size_t)-1);
if (size == (size_t)-1)
{
if (throwOnError)
throw InvalidArgument("StringWiden: mbstowcs() call failed");
else
return std::wstring();
}
#endif
return result;
}
void CallNewHandler()
{
using std::new_handler;

19
misc.h
View File

@ -163,7 +163,6 @@ struct CompileAssert
{
static char dummy[2*b-1];
};
//! \endif
#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
@ -1293,9 +1292,9 @@ inline void SecureWipeArray(T *buf, size_t n)
//! \brief Converts a wide character C-string to a multibyte string
//! \param str C-string consisting of wide characters
//! \param throwOnError flag indication the function should throw on error
//! \param throwOnError flag indicating the function should throw on error
//! \returns str converted to a multibyte string or an empty string.
//! \details StringNarrow converts a wide string to a narrow string using C++ std::wcstombs() under
//! \details StringNarrow() converts a wide string to a narrow string using C++ std::wcstombs() under
//! the executing thread's locale. A locale must be set before using this function, and it can be
//! set with std::setlocale() if needed. Upon success, the converted string is returned.
//! \details Upon failure with throwOnError as false, the function returns an empty string. If
@ -1305,6 +1304,20 @@ inline void SecureWipeArray(T *buf, size_t n)
//! then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception.
std::string StringNarrow(const wchar_t *str, bool throwOnError = true);
//! \brief Converts a multibyte C-string to a wide character string
//! \param str C-string consisting of wide characters
//! \param throwOnError flag indicating the function should throw on error
//! \returns str converted to a multibyte string or an empty string.
//! \details StringWiden() converts a narrow string to a wide string using C++ std::mbstowcs() under
//! the executing thread's locale. A locale must be set before using this function, and it can be
//! set with std::setlocale() if needed. Upon success, the converted string is returned.
//! \details Upon failure with throwOnError as false, the function returns an empty string. If
//! throwOnError as true, the function throws an InvalidArgument() exception.
//! \note If you try to convert, say, the Chinese character for "bone" from UTF-8 (0xE9 0xAA 0xA8)
//! to UTF-16 (0x9AA8), then you must ensure the locale is available. If the locale is not available,
//! then a 0x21 error is returned on Windows which eventually results in an InvalidArgument() exception.
std::wstring StringWiden(const char *str, bool throwOnError = true);
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
//! \brief Allocates a buffer on 16-byte boundary