繁体   English   中英

WIndows API中的“L”和“LPCWSTR”

[英]The 'L' and 'LPCWSTR' in WIndows API

我发现了

NetUserChangePassword(0, 0, L"ab", L"cd");

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

NetUserChangePassword(0, 0, (LPCWSTR) "ab", (LPCWSTR) "cd");

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

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

NetUserChangePassword(0, 0, (LPCWSTR) vs[0].c_str(), (LPCWSTR) vs[1].c_str());

其中vsstd::vector<std::string>

你有两个问题。

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

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

第二个是以下误解:

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

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

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

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

但是, LPCWSTR中的L不描述字符的宽度。 相反,它描述了指针的大小。 或者,至少,它曾经用过 类型名称上的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::string但是对于wchar_t而不是char 该类型的c_str()方法返回const wchar_t* 如果你没有wstringwchar_t的普通数组可能就足够了。

但是如果你将密码存储在std::string ,那么你需要以其他方式将其转换为宽字符。 要进行转换,您需要知道std::string字符使用的代码页 “当前的ANSI代码页”通常是一个安全的赌注; 它由常量CP_ACP表示。 您将在调用MultiByteToWideString时将其用于将操作系统从密码的代码页转换为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;

现在,当你需要一个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);

你在这里使用的C风格演员是一种非常生硬的乐器。 他们假设你确切地知道你在做什么。

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

LPWSTR定义为wchar_t *(whcar_T是2字节char类型),其解释方式与正常的1字节字符不同。

LPCWSTR意味着您需要传递wchar_t *。

如果你更改vs到std::vector<std::wstring> ,当你传递vs [0] .c_str()时会给你一个宽字符

如果你看看http://msdn.microsoft.com/en-us/library/aa370650(v=vs.85).aspx上的例子,你可以看到他们定义了UNICODE,这就是他们使用wchar_t的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM