使用RtlUnicodeStringToAnsiString

时间:2017-06-08 17:08:26

标签: c++ unicode kernel driver

关于RtlUnicodeStringToAnsiString的文件对于可能的失败是相当模糊的 - 模糊不清,我的意思是它没有说出任何关于它们的内容。

我不确定如何/是否处理不同的编码,或者如果我的理解是如此有缺陷以至于它甚至不会进入等式,但让我们假设输入是{ {3}}出于争论的缘故。

如果所有字符都在ASCII范围内,则没有问题,它们可能会被截断并丢失高位字节 - 前128个Unicode代码点是ASCII字符,UTF-16编码U + 0000到U + D7FF在数值上等于代码点。UTF-16 [1]

注意:[2]有一个WCHAR *缓冲区,UNICODE_STRING有一个CHAR *缓冲区,可能是预期的。

[跳过129-255和区域设置/代码页]

255以上的字符会怎样?有ANSI_STRING功能,因此可以安全地假设它不能转换为UTF-8。

RtlUnicodeToUTF8N之外的代码点(代理对和诸如此类的东西)怎么样?

我看到了一个类似下面代码的函数:

char *pTarget = reinterpret_cast<char*>(char_str);
const WCHAR  *pSource = reinterpret_cast<const WCHAR*>(wchar_str);

for ( long i = 0; i < targetMaxSizeInBytes; i++ )
{
    *pTarget = static_cast<char>(*pSource);

    if (L'\0' == *pSource)
        break;

    pTarget++;
    pSource++;
}

这会导致任何非ASCII字符出现问题,对吗?

更新

来自RbMm的答案:

  

BMPRtlUnicodeStringToAnsiString例程

的shell

我得到更多信息:

  

RtlUnicodeToMultiByteSize 类似, RtlUnicodeToMultiByteN 仅支持映射到系统启动时安装的当前系统ANSI代码页的预先组合的Unicode字符。

RtlUnicodeToMultiByteN有一个选项,如果转换中使用的默认字符无法在指定的代码页中表示,则会通知

  

lpUsedDefaultChar [out,optional]

     

指向标志的指针,该标志指示该函数是否在转换中使用了默认字符。如果源字符串中的一个或多个字符无法在指定的代码页中表示,则该标志设置为 TRUE 。否则,该标志设置为 FALSE 。此参数可以设置为 NULL

然而,似乎RtlUnicodeToMultiByteN,因此RtlUnicodeStringToAnsiString,似乎不支持当前代码页之外的字符?

我尝试了几个角色并且看似随机转换(见下文) - 更重要的是,我返回了 STATUS_SUCCESS

U+03A3 Σ -> 0n83 'S'
U+03A4 Τ -> 0n63 '?'
U+03A5 Υ -> 0n63 '?'
U+03A6 Φ -> 0n70 'F'

2 个答案:

答案 0 :(得分:1)

RtlUnicodeStringToAnsiStringRtlUnicodeToMultiByteN例程

的shell
  

RtlUnicodeToMultiByteN 例程转换指定的Unicode   使用当前系统 ANSI将字符串转换为新的字符串   代码页(ACP)。翻译的字符串不一定来自a   多字节字符集。

所以此例程中的任何一个都与WideCharToMultiByte具有 CP_ACP

相同的转换

也存在下一个例程:

RtlUnicodeStringToOemString - shell RtlUnicodeToOemN例程

  

RtlUnicodeToOemN 例程将给定的Unicode字符串转换为   OEM字符串,使用当前系统 OEM代码页

因此,此例程与WideCharToMultiByte的转化次数与 CP_OEMCP

相同

UTF-8 转换存在RtlUnicodeToUTF8N将Unicode字符串转换为UTF-8字符串)和RtlUTF8ToUnicodeN将UTF-8字符串转换为Unicode字符串。

对于自定义代码页,您可以使用未记录的api

NTSYSAPI
NTSTATUS
NTAPI
RtlCustomCPToUnicodeN(
    _In_ PCPTABLEINFO CustomCP,
    _Out_writes_bytes_to_(MaxBytesInUnicodeString, *BytesInUnicodeString) PWCH UnicodeString,
    _In_ ULONG MaxBytesInUnicodeString,
    _Out_opt_ PULONG BytesInUnicodeString,
    _In_reads_bytes_(BytesInCustomCPString) PCH CustomCPString,
    _In_ ULONG BytesInCustomCPString
    );

这里是初始化CPTABLEINFO的关键点,因此您可以使用任何 USHORT CodePage; 此处

答案 1 :(得分:0)

不确定这是否有帮助,但我之前使用WideCharToMultiByte转换为UTF-16(wchar_t *)和UTF-8(char *),并将CP_UTF8作为代码页传递。

编辑:我刚刚注意到了内核标签。我引用的函数是用户模式(kernel32.dll),因此可能对内核模式代码没用。 :(