加密与解密学习笔记3-Windows与Unicode

windows 9x几乎都是使用ANSI字符串来进行所有内部操作。但也有少量函数支持Unicode的能力。
 
Win9x_Unicode.exe例子
 
#include <windows.h>
#include <tchar.h>
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdline, int iCmdShow)
{
MessageBox(NULL, TEXT("Windows 9x支持Unicode?"), TEXT("Hello"), 0);
return 0;
}
运行结果:
反汇编工具(W32Dasm)查看代码
:00411690 6A00 push 00000000
:00411692 68306B4100 push 00416B30
:00411697 68406B4100 push 00416B40
:0041169C 6A00 push 00000000
* Reference To: USER32.MessageBoxW, Ord:024Dh
|
:0041169E FF1598A04100 Call dword ptr [0041A098]
:004116A4 3BF4 cmp esi, esp
:004116A6 E859FAFFFF call 00411104
:004116AB 33C0 xor eax, eax
:004116AD 5F pop edi
:004116AE 5E pop esi
:004116AF 5B pop ebx
:004116B0 81C4C0000000 add esp, 000000C0
:004116B6 3BEC cmp ebp, esp
:004116B8 E847FAFFFF call 00411104
:004116BD 8BE5 mov esp, ebp
:004116BF 5D pop ebp
:004116C0 C21000 ret 0010
 
程序存在一个Unicode版本的messagebox函数,Unicode函数能在windows9x上运行的很好。
 
windows 9x系统,即win95-win98(不是很严谨)的处理如下:
windows98里MessageBoxW函数的内部定义
int MessageBoxW(
MessageBoxExW{ // 调用MessageBoxExW()函数
WideCharToMultiByte(); // 取得要显示文本的长度(取得上例中Unicode字符串"Windows 9x支持Unicode?"的长度
GlobalAlloc(); // 按字符串长度分配内存
WideCharToMultiByte(); // 将UNICODE文本转换成ANSI字符串(将上例中Unicode字符串"Windows 9x支持Unicode?"转换成ANSI字符串)
WideCharToMultiByte(); // 取得消息框标题文本的长度(取得字符串“hello”的长度)
GlobalAlloc(); // 按字符串长度分配内存
WideCharToMultiByte(); // 将UNICODE文本转换成ANSI字符串(将上例字符串“hello”转换成ANSI字符串)
MessageBoxExA(); // 最终还是调用ANSI版的MessageBoxExA();函数显示窗口
GlobalFree(); // 释放内存
GlobalFree(); // 释放内存
}
);
MessageBoxW函数将Unicode字符串转换成ANSI字符串,最终ANSI版的MessageBoxExA函数来显示窗口。(注意:不是同一种编码,ASCII码主要是针对拉丁语系的文字的表示,ANSI是针对各国语言之间的交互信息的。)
其中,程序调用WideCharToMultiByte函数进行转换,这个函数用于将宽字符转换成等价的多字节字符串,如下:
WideCharToMultiByte(
UINT CodePage, //标识与新转换的字符串相关的代码页
DWORD dwFlags, //设定用于转换的其他空间,通常设置为0
LPCWCH lpWideCharStr, //要转换的字符串的内存
int cchWideChar, //该字符串的长度(字节)[注意:如果传递参数为-1.那么该函数用于确定源字符串的长度,如果传递参数为0,那么该函数将不执行字符串转换,而是返回使转换取得成功所需要的缓存值。]
LPSTR lpMultiByteStr, //转换后多字节版本字符串的内存地址
int cbMultiByte, //转换后多字节版本字符串的长度(字节)
LPCCH lpDefaultChar, //通常为NULL
LPBOOL lpUsedDefaultChar //通常为NULL
);
转换步骤:
1、调用WideCharToMultiByte函数,lpMultiByteStr传递值NULL,cchWideChar参数传递0,以得到所需要的缓存值。
2、分配足够的内存块,准备用于存放转换后的ANSI字符串;
3、再调用WideCharToMultiByte函数进行转换,将缓存地址作为lpMultiByteStr的参数,并传递第一次调用WideCharToMultiByte返回的缓存大小作为cchWideChar参数,
4、使用转换后的字符串
5、释放ANSI字符串占用的内存块
 
如果要将ANSI字符串转换成Unicode字符串,可调用MultiByteToWideChar函数来实现
windows 9x系统成百上千函数只提供Unicode参数的进入点,并不会将Unicode字符串转换成ANSI字符串,只返回运行失败的消息。所以,windows 9x系统开发软件只能用ASNI版函数开发应用程序,而Unicode版程序无法在windows 9x系统正常运行。
 
NT及以上系统是使用Unicode从头进行开发的,其系统核心完全使用Unicode函数工作的
如果调用任何一个windows函数并给他传递一个ANSI字符串,那么系统首先要将字符串转换成Unicode,然后再讲Unicode传递给操作系统,反之,如果希望函数返回ANSI函数,系统首先会将Unicode字符串转换成ANSI字符串,然后将结果返回给应用程序。
int MessageBoxA(
MessageBoxExA{ // 调用MessageBoxExA()函数
MBToWCSEx(); // 将MessageBoxA消息框主体文字转换成Unicode字符串
MBToWCSEx(); // 将MessageBoxA消息框标题栏上的文字转换成Unicode字符串
MessageBoxExW() // 调用MessageBoxExW()函数
HeapFree() // 释放内存
}
);
MessageBoxExA函数其实就是一个替换翻译层,用于分配内存,并将ANSI字符串转换为Unicode字符串,系统最终调用Unicode版的MessageBoxExW函数执行,当MessageBoxExW返回时,它便释放内存缓存。
Windows NT及以上系统既支持Unicode,也支持ANSI,所有新增和未过时的函数在Windows NT及以上系统都同时拥有两个版本。
原文地址:https://www.cnblogs.com/guiguxiaosheng/p/12295899.html