输入法故障处理日记
输入法故障处理日记
搜狗输入法经常碰到明明已经切到该输入法了,可是却看不到如下输入法的窗口,在编辑窗口也打不出字,如果刚好碰到和MM聊天,那就要郁闷坏了,于是决定好好研究下,首先经过搜索找到http://bbs.pediy.com/showthread.php?t=144962 ,了解到输入法文件是个特殊的DLL文件,它定义一套标准的接口函数,部分函数如下:(相关函数定义可以查阅MSDN)
ImeConversionList 将字符或字符串转换成目标字符
ImeConfigure 配置当前ime参数函数
ImeDestroy 退出当前使用的IME
ImeEscape
ImeInquire ;启动并初始化当前IME输入法
ImeProcessKey ;IME输入键盘事件管理函数
ImeSelect ;初始化
ImeSetActiveContext ;设置当前的输入处于活动状态
ImeToAsciiEx ;编码转换函数
NotifyIME ;IME通知管理函数
ImeRegisterWord ;向输入法字典注册字符串
ImeUnregisterWord
ImeGetRegisterWordStyle
ImeEnumRegisterWord
ImeSetCompositionString
可以将sogoupy.ime复制一份改名为sogoupy.dll,用depends查看其输出函数,有了初步了解后我们来尝试分析解决问题。
首先打开记事本,用XT显示其模块,发现有默认输入法模块MSCTFIME.IME,切换输入法,发现进程会加载相应的模块(如IMSC40A.IME 微软拼音输入法,winabc智能ABC),郁闷的是切换到搜狗输入法,进程并未加载相应的模块sogoupy.ime,所以才导致看不见如下的窗口,也无法输入中文等等。

问题初步原因找到了,尝试解决如下:
一、在语言栏设置里删除搜狗输入法再重新添加,无效
二、设想手动注入该模块,于是使用process hacker工具,将sogoupy.ime注入notepad.exe进程,可惜切换输入法后输入仍然无效。
三、难道要重新注册?首先在语言栏设置里将搜狗拼音删除,然后使用ImmInstallIME添加,ImmInstallIME原型如下:
HKL ImmInstallIME(
LPCTSTR lpszIMEFileName,
LPCTSTR lpszLayoutText
);
Return Values:The function returns the input locale identifier for the IME.注意它的返回值是输入法的ID.
具体代码如下,执行后惊奇的发现语言栏设置里重新添加了搜狗输入法,并变成如下摸样,呵呵
.386
.model flat,stdcall
option casemap:none
include kernel32.inc
include imm32.inc
includelib kernel32.lib
includelib imm32.lib
.data
filename db "c:\windows\system32\SogouPY.ime",0
imename db "sou gou",0
.code
start:
invoke ImmInstallIME,addr filename,addr imename ;函数返回值EAX里为搜狗输入法的ID=E0210804。
invoke ExitProcess,0
end start

不过很可惜,该方法仍然无效。
看样子必须对系统如何启动以及使用输入法做深入研究了(可惜后来我用结束EXPLORER.EXE进程,重新添加输入法解决了,所以下面的分析是基于正常情况下的)
首先用OD载入记事本,然后更改OD-调试设置选项--中断于新模块,F9运行,观察直到新模块为msctfime.ime,在堆栈回溯如下:
0007F6F4 |77D18816 返回到 USER32.77D18816 来自 USER32.77D1870C
0007F6F8 |77D6C95B USER32.77D6C95B ;消息处理函数
0007F6FC |000B0528
0007F700 |00000081 ;WM_NCCREATE消息
0007F704 |00000000
0007F708 |0007F814 ;LPCREATESTRUCT
查看LPCREATESTRUCT数据如下
typedef struct tagCREATESTRUCT {
LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCTSTR lpszName;
LPCTSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCT, *LPCREATESTRUCT;
0007F814 |00000000
0007F818 |01000000 notepad.01000000
0007F81C |00000000
0007F820 |00060182
0007F824 |00000000
0007F828 |00000000
0007F82C |00000000
0007F830 |00000000
0007F834 |88000000
0007F838 |0007F850 UNICODE "Default IME" ;lpszName窗口的名字
0007F83C |0000C026
0007F840 |00000000
0007F688 |77D6C6F9 返回到 USER32.77D6C6F9 来自 IMM32.CtfImmDispatchDefImeMessage
0007F30C |76313B26 返回到 IMM32.76313B26 来自 kernel32.LoadLibraryW
0007F310 |0007F470 UNICODE "C:\WINDOWS\system32\msctfime.ime"
大致过程是进程处理WM_NCCREATE消息---调用IMM32.CtfImmDispatchDefImeMessage---加载msctfime.ime
继续F9,程序运行起来,切换到记事本窗口,按下ctrl+空格,中断在OD里面,在堆栈回溯,发现
0007FE10 |77D18816 返回到 user32.77D18816 来自 user32.77D1870C
0007FE14 |771A3DDA comctl32.771A3DDA ;消息处理函数
0007FE18 |000C03DC
0007FE1C |00000050
0007FE20 |00000001
0007FE24 |E0210804
其中控件消息处理函数771A3DDA,控件应该就是记事本的EDIT控件,使用OD插件窗口工具,可以看到EDIT控件窗口句柄为C03DC,刚好与消息的HWND参数符合,消息码为50H,经查为WM_INPUTLANGCHANGEREQUEST,在MSDN里查找得到如下信息
The WM_INPUTLANGCHANGEREQUEST message is posted to the window with the focus when the user chooses a new input language, either with the hotkey (specified in the Keyboard control panel application) or from the indicator on the system taskbar. An application can accept the change by passing the message to the DefWindowProc function or reject the change (and prevent it from taking place) by returning immediately.
A window receives this message through its WindowProc function.
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_INPUTLANGCHANGEREQUEST
WPARAM wParam, // input locale information
LPARAM lParam // input locale identifier (HKL)
);
也就是当用户使用热键或者点击任务栏上语言栏选择一种新的输入法时,系统会产生该消息发送给焦点所在窗口,其中lParam 为Input locale identifier,E0210804刚好与我们安装搜狗输入法返回的ID相符
让我们看看程序从接收到这个消息开始到最后加载对应输入法过程,
重载程序,F9运行起来,在77d1870c下条件断点(即消息断点),[esp+c]==50h,切换到记事本窗口,按下ctrl+空格,在OD里中断下来,将77D1870C改为直接断点,并更改OD-调试设置选项--中断于新模块,F9运行,中断下来,回溯堆栈发现又是由IMM32加载SOGOUPY.IME文件
0007F5C4 |763071F4 返回到 IMM32.763071F4 来自 kernel32.LoadLibraryW
0007F5C8 |0007F5E0 UNICODE "C:\WINDOWS\system32\SOGOUPY.IME"
查看代码如下:
注意:上传附件及图片大小不得大于30M。
⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。
