首页
社区
课程
招聘
[原创]输入法故障处理日记
发表于: 2012-2-19 18:31 10749

[原创]输入法故障处理日记

2012-2-19 18:31
10749

输入法故障处理日记
    搜狗输入法经常碰到明明已经切到该输入法了,可是却看不到如下输入法的窗口,在编辑窗口也打不出字,如果刚好碰到和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"
查看代码如下:

763071ED    50              PUSH EAX
763071EE    FF15 3C113076   CALL DWORD PTR DS:[<&KERNEL32.LoadLibrar>; kernel32.LoadLibraryW
763071F4    85C0            TEST EAX,EAX
763071F6    8943 04         MOV DWORD PTR DS:[EBX+4],EAX
763071F9    0F84 F9010000   JE IMM32.763073F8
763071FF    8B35 40113076   MOV ESI,DWORD PTR DS:[<&KERNEL32.GetProc>; kernel32.GetProcAddress
76307205    68 D4753076     PUSH IMM32.763075D4                      ; ASCII "ImeInquire"
7630720A    50              PUSH EAX
7630720B    FFD6            CALL ESI
7630720D    85C0            TEST EAX,EAX
7630720F    8943 54         MOV DWORD PTR DS:[EBX+54],EAX
76307212    0F84 E0010000   JE IMM32.763073F8
76307218    68 C0753076     PUSH IMM32.763075C0                      ; ASCII "ImeConversionList"
7630721D    FF73 04         PUSH DWORD PTR DS:[EBX+4]
76307220    FFD6            CALL ESI
76307222    85C0            TEST EAX,EAX
76307224    8943 58         MOV DWORD PTR DS:[EBX+58],EAX
76307227    0F84 CB010000   JE IMM32.763073F8
7630722D    68 B0753076     PUSH IMM32.763075B0                      ; ASCII "ImeRegisterWord"
76307232    FF73 04         PUSH DWORD PTR DS:[EBX+4]
76307235    FFD6            CALL ESI
76307237    85C0            TEST EAX,EAX
76307239    8943 5C         MOV DWORD PTR DS:[EBX+5C],EAX
7630723C    0F84 B6010000   JE IMM32.763073F8

7630734A    68 D0743076     PUSH IMM32.763074D0                      ; ASCII "ImeGetImeMenuItems"
7630734F    FF73 04         PUSH DWORD PTR DS:[EBX+4]
76307352    FFD6            CALL ESI
0007F81C   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F820   771A3DDA  comctl32.771A3DDA
0007F824   000D03DC
0007F828   00000282               ;282h为WM_IME_NOTIFY ,
0007F82C   00000001               ;IMN_CLOSESTATUSWINDOW   
0007F830   00000000

0007F5CC   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F5D0   7365912A  msctfime.UIWndProc
0007F5D4   000E03D8
0007F5D8   00000282               ;282h为WM_IME_NOTIFY ,
0007F5DC   00000001               ;IMN_CLOSESTATUSWINDOW
0007F5E0   00000000
关闭默认输入法状态窗口
0007F828   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F82C   7365912A  msctfime.UIWndProc
0007F830   000E03D8
0007F834   00000285            ;WM_IME_SELECT
0007F838   00000000            ;为0即取消选择该输入法,为1为选择该输入法
0007F83C   04090409           ;输入法的ID

0007F7E0   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F7E4   7365912A  msctfime.UIWndProc
0007F7E8   000E03D8
0007F7EC   00000002           ;WM_DESTROY
0007F7F0   00000000
0007F7F4   00000000
消除默认输入法客户端窗口

0007F7D8   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F7DC   7365912A  msctfime.UIWndProc
0007F7E0   000E03D8
0007F7E4   00000082             ;WM_NCDESTROY
0007F7E8   00000000
0007F7EC   00000000
消除默认输入法非客户端窗口
调用SOGOUPY.imeselect
0007F8AC   7630346E  返回到 IMM32.7630346E
0007F8B0   5CE50417               ;输入法上下文的句柄
0007F8B4   00000001                ;为1即初始化,为0为卸载,释放资源


0007F044   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F048   100A51E0  SogouPY.100A51E0
0007F04C   000F03D8
0007F050   00000081              ;WM_NCCREATE
0007F054   00000000
0007F058   0007F164               ;LPCREATESTRUCT,查看该结构数据,发现窗口为“SOPY_UI"

0007F088   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F08C   100A51E0  SogouPY.100A51E0
0007F090   000F03D8
0007F094   00000083            ;WM_NCCALCSIZE
0007F098   00000000
0007F09C   0007F18C           ;LPRECT

0007F030   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007F034   100A51E0  SogouPY.100A51E0
0007F038   000F03D8
0007F03C   00000001          ;WM_CREATE
0007F040   00000000
0007F044   0007F150          ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_UI"

0007E828   77D18816  返回到 user32.77D18816 来自 user32.77D1870C
0007E82C   10111060  SogouPY.10111060
0007E830   002609B4
0007E834   00000081         ;WM_NCCREATE
0007E838   00000000
0007E83C   0007E948         ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_HINT"

0007E86C   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007E870   10111060  SOGOUPY.10111060
0007E874   002609B4
0007E878   00000083             ;WM_NCCALCSIZE
0007E87C   00000000
0007E880   0007E970            ;LPRECT

0007E814   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007E818   10111060  SOGOUPY.10111060
0007E81C   002609B4
0007E820   00000001         ;WM_CREATE
0007E824   00000000
0007E828   0007E934         ;LPCREATESTRUCT,查看该结构数据,窗口为“SOPY_HINT"

0007E878   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007E87C   10111060  SOGOUPY.10111060
0007E880   002609B4
0007E884   00000005               ;WM_SIZE
0007E888   00000000               ;SIZE_RESTORED
0007E88C   00000000

0007E878   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007E87C   10111060  SOGOUPY.10111060
0007E880   002609B4
0007E884   00000003              ;WM_MOVE
0007E888   00000000
0007E88C   00000000

0007F828   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F82C   100A51E0  SOGOUPY.100A51E0
0007F830   002809A6
0007F834   00000285              ;WM_IME_SELECT
0007F838   00000001              ;为1为选择该输入法
0007F83C   E0210804             ;输入法的ID

0007F81C   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F820   771A3DDA  COMCTL32.771A3DDA
0007F824   000809A0  
0007F828   00000282           ;282h为WM_IME_NOTIFY ,
0007F82C   00000002           ;IMN_OPENSTATUSWINDOW   
0007F830   00000000

0007F5CC   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F5D0   100A51E0  SOGOUPY.100A51E0
0007F5D4   002809A6
0007F5D8   00000282
0007F5DC   00000002
0007F5E0   00000000

0007FB6C   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007FB70   771A3DDA  COMCTL32.771A3DDA
0007FB74   000809A0    
0007FB78   00000051            ;WM_INPUTLANGCHANGE
0007FB7C   00000086
0007FB80   E0210804

调用SOGOUPY.NotifyIME函数
0007FA08   76303F5F  返回到 IMM32.76303F5F
0007FA0C   5CE50417
0007FA10   00000003
0007FA14   00000000
0007FA18   0000000A

0007F948   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F94C   771A3DDA  COMCTL32.771A3DDA
0007F950   000809A0  
0007F954   00000282           ;282h为WM_IME_NOTIFY 
0007F958   0000000A           ;IMN_SETCOMPOSITIONFONT   设置字体
0007F95C   00000000

0007F6F8   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F6FC   100A51E0  SOGOUPY.100A51E0
0007F700   002809A6
0007F704   00000282
0007F708   0000000A
0007F70C   00000000

0007FA60   76303F5F  返回到 IMM32.76303F5F
0007FA64   5CE50417
0007FA68   00000003
0007FA6C   00000000
0007FA70   0000000C

0007F9A0   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F9A4   771A3DDA  COMCTL32.771A3DDA
0007F9A8   000809A0  
0007F9AC   00000282
0007F9B0   0000000B

0007F750   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F754   100A51E0  SOGOUPY.100A51E0
0007F758   002809A6
0007F75C   00000282
0007F760   0000000B        ; IMN_SETCOMPOSITIONWINDOW
0007F764   00000000

0007F880   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F884   771A3DDA  COMCTL32.771A3DDA
0007F888   000809A0    
0007F88C   00000282
0007F890   00000008
0007F894   00000000

0007F630   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F634   100A51E0  SOGOUPY.100A51E0
0007F638   002809A6
0007F63C   00000282
0007F640   00000008          ;IMN_SETOPENSTATUS
0007F644   00000000

0007F880   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F884   771A3DDA  COMCTL32.771A3DDA
0007F888   000809A0  
0007F88C   00000282
0007F890   00000006
0007F894   00000000

0007F630   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F634   100A51E0  SOGOUPY.100A51E0
0007F638   002809A6
0007F63C   00000282
0007F640   00000006   ;IMN_SETCONVERSIONMODE
0007F644   00000000

0007F880   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F884   771A3DDA  COMCTL32.771A3DDA
0007F888   000809A0  
0007F890   00000007
0007F894   00000000

0007F630   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007F634   100A51E0  SOGOUPY.100A51E0
0007F638   002809A6
0007F63C   00000282
0007F640   00000007    ;IMN_SETSENTENCEMODE
0007F644   00000000

0007FDB4   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007FDB8   01003429  notepad.01003429
0007FDBC   000B0182  
0007FDC0   00000088           ;WM_SYNCPAINT
0007FDC4   00000004
0007FDC8   00000000

0007FCF8   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007FCFC   771A3DDA  COMCTL32.771A3DDA
0007FD00   000809A0  
0007FD04   000000D8      ;EM_SETIMESTATUS
0007FD08   00000001
0007FD0C   00000000

0007FE10   77D18816  返回到 USER32.77D18816 来自 USER32.77D1870C
0007FE14   100A51E0  SOGOUPY.100A51E0
0007FE18   002809A6
0007FE1C   000083F1           ;自定义消息
0007FE20   00000000
0007FE24   00000000

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (1)
雪    币: 120
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主牛啊。。。认真看看。。。学习。
2012-2-19 18:52
0
游客
登录 | 注册 方可回帖
返回
//