如何将std::wstring转换为LSA_UNICODE_STRING
How do I convert a std::wstring to an LSA_UNICODE_STRING
今天我能够编写一个简单的C++程序,该程序授予用户"作为服务登录"权限。其中一部分涉及在LPCWSTR
和LSA_UNICODE_STRING
之间进行转换。代码在这里:
LSA_UNICODE_STRING StringToLsaUnicodeString(LPCWSTR string) {
LSA_UNICODE_STRING lsaString;
DWORD dwLen = 0;
dwLen = wcslen(string);
lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
return lsaString;
}
当我在这个函数中出现一些小错误时,我对LsaLookupNames2()
的调用失败,代码为87(十六进制0x57)"参数不正确"。我试图在使用std::wstring
的C++应用程序中进行这个调用,但它失败了。我目前的功能如下:
#if defined(_UNICODE)
LSA_UNICODE_STRING toLsaUnicodeString (std::wstring str) {
LSA_UNICODE_STRING lsaWStr;
DWORD len = 0;
LPWSTR cstr = (LPWSTR)str.c_str();
len = wcslen(cstr);
lsaWStr.Buffer = cstr;
lsaWStr.Length = (USHORT)((len) * sizeof(WCHAR));
lsaWStr.MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));
return lsaWStr;
}
#endif
我做错了什么?
您可能会遇到从str.c_str()
返回的wchar_t*
的生存期问题。str.c_str()
将返回一个指向其生存期由str
控制的底层字符串的指针。由于str
是按值传递的,因此它将在toLsaUnicodeString
函数结束时被销毁,导致返回的LSA_UNICODE_STRING
指向已解除分配的内存。为了避免这种情况,您需要在toLsaUnicodeString
函数中创建一个底层字符串的副本,并将该副本与返回的LSA_UNICODE_STRING
相关联,类似于:
LSA_UNICODE_STRING toLsaUnicodeString (const std::wstring& str) {
LSA_UNICODE_STRING lsaWStr;
DWORD len = 0;
len = str.length();
LPWSTR cstr = new WCHAR[len + 1];
memcpy(cstr, str.c_str(), (len + 1) * sizeof(WCHAR));
lsaWStr.Buffer = cstr;
lsaWStr.Length = (USHORT)((len) * sizeof(WCHAR));
lsaWStr.MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));
return lsaWStr;
}
由于内存现在是在堆上分配的,您有责任确保它被释放。您可以使用以下函数来处理此问题。
void freeLsaUnicodeString(LSA_UNICODE_STRING& str) {
delete [] str.Buffer;
str.Buffer = 0;
str.Length = 0;
str.MaximumLength = 0;
}
更好的方法是使用RAII来管理内存,并保证在变量不再使用时释放内存。有关此方法的详细信息,请参阅_C64先生的回答。
我认为在C++中实现这一点的正确方法是围绕原始C结构LSA_UNICODE_STRING编写一个RAII包装器类。
该类的构造函数重载正确地初始化它,析构函数释放分配的资源(帮助编写异常安全代码),并且您可以提供一些operator=重载来进行正确的深度复制。
动态分配的WCHAR缓冲区不是使用显式的new[]和delete[],而是由std::vector的实例管理,这简化了代码(例如std::vector的析构函数将自动释放分配的内存)。
类似这样的东西:
#include <windows.h> // Win32 SDK header
#include <LsaLookup.h> // LSA_UNICODE_STRING
#include <vector> // std::vector
#include <string> // std::wstring
//
// C++ RAII wrapper to LSA_UNICODE_STRING
//
class LsaUnicodeString
{
public:
LsaUnicodeString()
{
SetEmpty();
}
LsaUnicodeString(const LsaUnicodeString & source)
{
CopyFrom(source);
}
explicit LsaUnicodeString(const std::wstring & source)
{
CopyFrom(source);
}
~LsaUnicodeString()
{
// Nothing to do:
// the string buffer is managed by std::vector data member
}
LsaUnicodeString & operator=(const LsaUnicodeString & source)
{
if (&source != this)
{
CopyFrom(source);
}
return *this;
}
LsaUnicodeString & operator=(const std::wstring & source)
{
CopyFrom(source);
return *this;
}
const LSA_UNICODE_STRING & Get() const
{
return m_us;
}
//
// Implementation
//
private:
LSA_UNICODE_STRING m_us; // raw C structure
std::vector<WCHAR> m_buffer; // string content
void SetEmpty()
{
m_buffer.resize(1);
m_buffer[0] = L' '; // end-of-string
m_us.Length = 0;
m_us.MaximumLength = sizeof(WCHAR);
m_us.Buffer = &m_buffer[0];
}
void CopyFrom(const std::wstring & source)
{
if ( source.empty() )
{
SetEmpty();
return;
}
const int len = source.length();
m_buffer.resize(len + 1);
::CopyMemory(&m_buffer[0], source.c_str(), (len+1)*sizeof(WCHAR));
m_us.Length = len * sizeof(WCHAR);
m_us.MaximumLength = m_us.Length + sizeof(WCHAR);
m_us.Buffer = &m_buffer[0];
}
void CopyFrom(const LsaUnicodeString & source)
{
if (source.m_us.Length == 0)
{
SetEmpty();
return;
}
m_buffer = source.m_buffer;
m_us.Length = source.m_us.Length;
m_us.MaximumLength = source.m_us.MaximumLength;
m_us.Buffer = &m_buffer[0];
}
};
您可以使用RtlInitUnicodeString函数来初始化unicode字符串。在使用UNICODE_STRING调用RtlFreeUnicodeString之后。
UNICODE_STRING和LSA_UNCODE_STRING是相同的。
- C++ - Unicode Newline
- 如何将unicode字符串从C++传递到delphi
- ascii 和 unicode 在处理级别有什么区别吗?
- 无法从 std::string 中提取C++ Unicode 符号
- MinGW64 - Unicode 源文件错误?
- 使用 Visual Studio 2019 编译 Unicode
- 将ANSI C字符串转换为UNICODE
- 如何从 oracle 数据库 c++ 读取 unicode
- 在特定 Unicode 路径中创建文件
- 如何存储 unicode 字符并将其输出到文件?
- C++ wmain 函数错误时使用 Unicode
- C++:打印 Unicode 字符
- QTextStream,用于打印英语和Unicode 16
- 将 unicode 字符串与 c ++ 符号进行比较?
- 如何在C++中使用 UTF-8 和 Unicode?C++20 char8_t有多大?
- 在 CHtmlEditCtrl::SetDocumentHTML 中使用 Unicode
- C++ - 为什么 unicode 输出不正确?
- 如何在 c++ 中读取用 utf-8 编码的 java unicode 字节字符串
- 在 Windows 中使用 boost::p rogram_options 从命令行参数读取 Unicode 字符
- C++:Unicode 字符串文字的可移植性