WIndows API中的"L"和"LPCWSTR"

Don*_*alo 3 c++ winapi

我发现了

NetUserChangePassword(0, 0, L"ab", L"cd");
Run Code Online (Sandbox Code Playgroud)

将用户密码从ab更改为cd.然而,

NetUserChangePassword(0, 0, (LPCWSTR) "ab", (LPCWSTR) "cd");
Run Code Online (Sandbox Code Playgroud)

不起作用.返回的值表示密码无效.

我需要传递const char*此函数调用的最后两个参数.我怎样才能做到这一点?例如,

NetUserChangePassword(0, 0, (LPCWSTR) vs[0].c_str(), (LPCWSTR) vs[1].c_str());
Run Code Online (Sandbox Code Playgroud)

哪里vsstd::vector<std::string>.

Dav*_*vid 6

你有两个问题.

首先是实际问题 - 如何做到这一点.你混淆宽窄的弦乐,从一个到另一个.带L前缀的字符串是一个宽字符串,其中每个字符是两个字节(a wchar_t).没有L的字符串是单个字节(a char). 您不能使用C样式转换从一个转换为另一个, (LPCWSTR) "ab"因为您有一个chars 数组,并将其转换为指向宽字符的指针.它只是更改指针类型,而不是基础数据.

要从窄字符串转换为宽字符串,通常使用MultiByteToWideChar.你没有提到你的窄字符串所在的代码页; 你可能会传入CP_ACP第一个参数.但是,由于您在字符串和wstring之间进行转换,因此您可能对其他转换方法感兴趣(,).这会给你一个wstring与你的角色,而不是一个string,和wstring.c_str()方法返回一个指向wchar_t秒.

第二个是以下误解:

我需要传递const char*作为此函数调用的最后两个参数.我怎样才能做到这一点?

不,你没有.你需要传递一个宽字符串,你在上面.你的方法(转换指针)表明你可能不知道不同的字符串类型和字符编码,这是每个软件开发人员都应该知道的.因此,假设您有兴趣,希望您能找到以下参考资料:

我建议您调查UNICODE使用宽字符串重新编译应用程序.许多API都是在窄版本和宽版本中定义的,通常这意味着您默认访问窄版本(您可以通过直接调用A或W版本来访问这些API的ANSI(窄版)或宽版本 - 它们具有A或W附加到它们的名称,例如CreateWindowW - 请参见该页面底部的两个名称.您通常不需要担心这一点.)据我所知,此API始终可用.无论如何UNICODE,它只是原型的广泛.


Mar*_*som 5

您在这里使用的 C 风格转换是一种非常生硬的工具。他们假设你确切地知道自己在做什么。

您需要将 ASCII 或多字节字符串转换为 API 的 Unicode 字符串。可能有一个NetUserChangePasswordA函数接受char *您尝试传递的类型,请先尝试一下。


Rob*_*edy 5

那是两个完全不同的L '.第一部分是C++语言语法的一部分.使用字符串文字前缀L,它变为字符串文字; 而不是数组char,你得到一个数组wchar_t.

但是,Lin LPCWSTR并没有描述字符的宽度.相反,它描述了指针的大小.或者,至少,它曾经用过.L类型名称的缩写是16位Windows的遗留物,当有两种指针时.有指针,其中地址位于当前64 KB段内的某个位置,并且存在指针,它们可能指向当前段之外.操作系统要求调用者将后者提供给其API,因此所有指针类型名称都使用LP.如今,只有一种指针; Microsoft保留相同的类型名称,以便旧代码继续编译.

其中LPCWSTR指定宽字符的部分是W.但仅仅输入char字符串文字LPCWSTR是不足以将这些字符转换为宽字符.相反,会发生什么是类型转换告诉编译器你写的是真正的指向宽字符串的指针,即使它实际上不是.编译器信任你.除非你真的比编译器更了解真实类型,否则不要进行类型转换.

如果你真的需要传递一个const char*,那么你不需要输入任何东西,并且你不需要任何L前缀.一个普通的旧字符串文字就足够了.(如果你真的想要转换为Windows类型,请使用LPCSTR- 不W.)但看起来你真正需要传递的是一个const wchar_t*.如上所述,您可以使用L字符串文字中的前缀来获取它.

在实际程序中,您可能没有字符串文字.用户将提供密码,或者您将从其他外部源读取密码.理想情况下,你会存储在该密码std::wstring,这就好比std::stringwchar_t代替char.该c_str()类型的方法返回一个const wchar_t*.如果你没有a wstring,那么一个简单的数组wchar_t就足够了.

但是如果你将密码存储在a中std::string,那么你需要以其他方式将其转换为宽字符.做一个转换,你需要知道什么代码页std::string字符使用."当前的ANSI代码页"通常是一个安全的赌注; 它由常数表示CP_ACP.在调用MultiByteToWideStringOS将密码的代码页转换为Unicode 时,您将使用它.

int required_size = MultiByteToWideChar(CP_ACP, 0, vs[0].c_str(), vs[0].size(), NULL, 0);
if (required_size == 0)
  ERROR;
// We'll be storing the Unicode password in this vector. Reserve at
// least enough space for all the characters plus a null character
// at the end.
std::vector<wchar_t> wv(required_size);
int result = MultiByteToWideChar(CP_ACP, 0, vs[0].c_str(), vs[0].size(), &wv[0], required_size);
if (result != required_size - 1)
  ERROR;
Run Code Online (Sandbox Code Playgroud)

现在,当你需要a时wchar_t*,只需使用指向该向量的第一个元素的指针:&wv[0].如果你需要它wstring,你可以通过几种方式从向量构造它:

// The vector is null-terminated, so use "const wchar_t*" constructor
std::wstring ws1 = &wv[0];
// Use iterator constructor. The vector is null-terminated, so omit
// the final character from the iterator range.
std::wstring ws2(wv.begin(), wv.end() - 1);
// Use pointer/length constructor.
std::wstring ws3(&wv[0], wv.size() - 1);
Run Code Online (Sandbox Code Playgroud)