Wine Notes AnsiString and Unicode String
[ ]Windows下有两种字符的格式 Unicode 和 ANSI, Windows下的很多API(Rtl系列, 之类的) 是需要认清二者的区别的
二者的对比
{% highlight C %} #ifndef STRING_DEFINED #define STRING_DEFINED typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } STRING, *PSTRING; #endif
typedef STRING ANSI_STRING; {% endhighlight %}
而PCHAR
是 char*
的一个定义 , 因而ANSI_STRING 每一个字符占一个字节(sizeof(char))
{% highlight C %} #ifndef UNICODE_STRING_DEFINED #define UNICODE_STRING_DEFINED typedef struct _UNICODE_STRING { USHORT Length; /* bytes / USHORT MaximumLength; / bytes */ PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; #endif
typedef const UNICODE_STRING *PCUNICODE_STRING; {% endhighlight %}
这里的 PWSTR 的定义是 WCHAR*, 即宽字符指针, 查看WCHAR的定义后知, WCHAR为 (unsigned short) 型(16bit char)
初始化WCHAR 的时候要用下面这种形式进行初始化:
{% highlight C %} WCHAR sample_1[] = L”Example”; WCHAR sample_2[] = {‘E’, ‘x’, ‘a’, ‘m’, ‘p’, ‘l’, ‘e’, 0}; {% endhighlight %}
一定要注意第二种形式最后的 0
WCHAR, char 之间的转换
二者之间的转换可以通过两个函数来完成, 先将char的字符串转为 ANSI_STRING
, 然后将ANSI_STRING
,转为UNICODE_STRING
, 从而UNICODE_STRING
中的Buffer
即为转换后的结果
参考Sebastian Lackner 的Sample
通过 RtlInitAnsiString
将 filename
的内容写入一个ANSI_STRING
dospath
内, 然后调用 RtlAnsiStringToUnicodeString
并且设置 AllocateDestinationString
为 TRUE, 让这个函数自行分配内存给dospathW, 要注意这种方式分配的内存要用 RtlFreeUnicodeString
手动回收
Wine 下打印WCHAR
使用函数 wine_dbgstr_* 系列函数, 这里使用 wine_dbgstr_w, 打印宽字符
防止内存泄露
- 使用
RtlInitAnsiString
创建的字符串不需要手动Free - 使用
RtlAnsiStringToUnicodeString
, 并且AllocateDestinationString
为TRUE
的话需要手动释放内存 - 使用
wine_nt_to_unix_filename
得到的ANSI_STRING
需要手动释放内存