汉王手写输入的系统部分(Palm平台)(20千字),汉王,Palm,逆向工程技术 2008年06月24日 星期二 下午 03:50 汉王手写输入的系统部分 工具: IDA Pro 4.x 平台: Palm OS 3.5, Motorola 68000 指令集 下载: http://www.hwpen.net/download.htm 年初, 下了一个汉王试了一下, 觉得它的浮动菜单做的比较好, 因为它在任何App下都可以冒出来. 要知道Palm是单任务的, 在一个时候只能有一个APP在运行. 当时刚刚接触Palm, 如果要让我实现这些功能, 还真的不知道怎么下手. 于是想到了用IDA试试在非Windows平台的反汇编. 最后得到的这些代码完全说明了它是怎样实现这些功能的. 对于Palm程序员是有参考价值的. 另外, 有几点需要特别说明: 1. 对于它的识别引擎, 我没有做逆向, 因为我对它后面的高深理论不了解也没有兴趣. 2. 因为是为了学习, 而不是破解这套软件, 我没有去逆向它的注册码算法部分. 从支持国产软件方面考虑, 我也不会这样做.(言下之意:汉王你可别找我麻烦 :) ) 3. 这里公布的只是任何Palm书籍上都有的编程的最基础部分, 应该不会对汉王在技术上构成什么危害. 4. 这些可以编译的代码只用于学习目的, 请勿做它用. 5. 用SetTrap的方法挂接HW_SysHandleEvent()而没有其它措施是不安全的,因为系统在特定的时候会移动代码资源, 这肯定会让系统垮掉, 应该使用DmDatabaseProtect()对这段代码资源加以保护. 希望汉王以后会这样做. // #include #include #include #include #define version350 0x3503000 #define HW_MainForm 1000 #define RomIncompatibleAlert 1001 #define HWDefinedCmd 0xddbb #define HW_COMMONCCHAR 0x0001 #define HW_SUBCOMMONCCHAR 0x0002 #define HW_TRA2SIMPLIFIED 0x0008 #define HW_NUMERIC 0x0010 #define HW_ENGLISH 0x0060 #define HW_SYMBOL 0x0180 #define HW_UPPER2LOWER 0x2000 #define HW_LOWER2UPPER 0x4000 #define HW_HALF2FULL 0x8000 // 菜单模式 #define FOLDED 0 // 收成"V" #define LOWER 1 // 在屏幕的下半部 #define UPPER 2 // 在屏幕的上半部 #define HIDDEN 3 // 隐藏 // 手写系统阶段 #define READY 0 // 就绪 #define ENTER 1 // 进入窗口或Form #define LEAVE 2 // 离开窗口或Form #define CHGFLD 3 // 切换到其它字段 typedef struct tagHW_PREF { Boolean bInstallHW; // 是否安装汉王手写输入系统. 0 Int8 al_b1; // 未被使用 1 UInt16 flags; // 标志位 2 UInt16 RecogRange; // 识别范围 4 Int8 RecogWaitTime; // 识别等待时间 6 Int8 PenThickness; // 笔迹粗细 7 Int8 PenColor; // 笔的颜色 8 Int8 al_b9; // 未被使用 9 Int16 ShotcutPenDownX; // 快捷方式的起点屏幕坐标 X a Int16 ShotcutPenDownY; // 快捷方式的起点屏幕坐标 Y c Int16 ShotcutPenUpX; // 快捷方式的终点屏幕坐标 X e Int16 ShotcutPenUpY; // 快捷方式的终点屏幕坐标 Y 10 Boolean bSetting; // 是否正在设置快捷方式 12 Int8 bUsingShortcut; // 是否正在使用快捷方式 13 Boolean bSplitScreen; // 全屏分割 14 Boolean bHalfToFull; // 半角字符转成全角字符 15 Boolean bUpperToLower; // 大写字母转成小写字母 16 Boolean bLowerToUpper; // 小写字母转成大写字母 17 Boolean bMouse; // 是否作为鼠标使用 18 Boolean bReged; // 是否是注册用户: 0xff 是, 0 否. 19 Int8 MenuMode; // 0: FOLDED, 1: LOWER, 2: UPPER, 3: HIDDEN 1a Boolean bMenuFolded; // 菜单是否被收成"V" 1b Boolean bOpenHW; // 是否启动汉王手写输入 1c Boolean bHalfScrnInput; // 是否在半屏手写模式 1d Boolean bRedrawMenu; // 菜单是否需要重画 1e Int8 Phase; // 手写系统阶段 0: READY, 1: ENTER, 2: LEAVE, 3: CHGFLD 1f } HW_PREF; typedef struct tagHW_PENS { UInt16 Cands[20][10]; // 候选字Buffer 0 UInt8 index; // 候选字在候选字Buffer中的下标索引 0x190/400 UInt8 b191; // not used UInt16 InsPtPos; // 插入点偏移, 192h, 402 UInt16 CandiDispOfs; // 候选字显示偏移 194h 404 char* AssocBuffer; // 联想字buf 196h 406 UInt16 AssocNum; // 联想字个数 19a 410 UInt8 AssocOfs; // 联想字偏移 19c 412 UInt8 AssocDispOfs; // 联想字显示偏移 19d 413 } HW_PENS; typedef struct tagHW_TRACE { PointType points[2048]; // 笔迹采样点数组 0 UInt16 PtCount; // 笔迹采样存放位置 2000 UInt32 dw2002; // 2002 UInt8 b2006; // 2006 UInt8 b2007; // 2007 UInt8 b2008; // 2008 } HW_TRACE; int HW_Install(void); void HW_Uninstall(void); UInt16 GetRecogRange(HW_PREF* pPref) { UInt16 flags; if (pPref->RecogRange) flags = pPref->RecogRange; else flags = pPref->flags; if (pPref->bHalfToFull) flags |= 0x8000; if (pPref->bUpperToLower) flags |= 0x2000; if (pPref->bLowerToUpper) flags |= 0x4000; return flags; } Int8 GetMenuMode(void) { Int16 x, y; InsPtGetLocation(&x, &y); if (y > 109) return UPPER; else return LOWER; } char V[] = "V"; void ClearMenu(Int8 MenuMode) { RectangleType rc; if (MenuMode == HIDDEN) return; if (MenuMode == FOLDED) { WinEraseChars(V, 1, 141, 141); return; } if (MenuMode == LOWER) RctSetRectangle(&rc, 0, 118, 160, 30); else if (MenuMode == UPPER) RctSetRectangle(&rc, 0, 78, 160, 30); WinEraseRectangle(&rc, 0/*cornerDiam, 0 for square corners*/); } void RedrawCurForm(void) { FormPtr frm = FrmGetActiveForm(); WindowType* winHandle = FrmGetWindowHandle(frm); if (winGetActiveWindow() == winHandle && FrmValidatePtr(frm)) FrmDrawForm(frm); } void DrawMenu(HW_PREF* pPrefs, HW_PENS* pHWPens) // a3 = pPrefs, a2 = pHWPens { int ofs, x, d5; RectangleType rc; UInt16* ptr; if (pHWPens->index == 0) x = 0; else x = pHWPens->index - 1; if (pPrefs->MenuMode == UPPER) { RctSetRectangle(&rc, 2, 80, 155, 25); WinDrawRectangleFrame(dialogFrame, &rc); // This routine does not draw in the gray color; it draws with // alternating foreground and background pixels. That is, it uses // the grayPattern pattern type. WinDrawGrayLine(74, 93, 74, 104); WinDrawGragLine(2, 92, 156, 92); WinDrawChars("→", 2, 63, 94); WinDrawChars("英", 2, 76, 94); if (pPrefs->RecogRange == HW_ENGLISH) { RctSetRectangle(&rc, 75, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("数", 2, 88, 94); if (pPrefs->RecogRange == HW_NUMERIC) { RctSetRectangle(&rc, 87, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("符", 2, 100, 94); if (pPrefs->RecogRange == HW_SYMBOL) { RctSetRectangle(&rc, 99, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("全", 2, 112, 94); if (pPrefs->bHalfToFull) { RctSetRectangle(&rc, 111, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("窗", 2, 124, 94); WinDrawChars("鼠", 2, 136, 94); if (pPrefs->bMouse) { RctSetRectangle(&rc, 135, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("^", 1, 148, 94); WinDrawChars("←", 2, 132, 81); WinDrawChars("→", 2, 145, 81); d5 = pHWPens->CandiDispOfs * 2; ptr = pHWPens->Cands[x]; // 显示5个候选字 if (ptr[d5] || ptr[d5 1]) { for (ofs = d5; ofs < d5 10; ofs = 2) { if (ptr[ofs]) { WinDrawChars(&ptr[ofs], 2, x, 94); x = 12; } else { if (ptr[d5 1] <= ' ') break; WinDrawChars(&ptr[d5 1], 1, x, 94); x = 12; } } } // 显示10个联想字 if (pHWPens->AssocNum) { x = 3; for (ofs = pHWPens->AssocDispOfs; ofs < pHWPens->AssocOfs 20; ofs = 2) { if (ofs - pHWPens->AssocOfs < pHWPens->AssocNum) break; WinDrawChars(&pHWPens->AssocBuffer[ofs], 2, x, 81); x = 13; } } } else if (pPrefs->MenuMode == LOWER) { RctSetRectangle(&rc, 2, 120, 155, 25); WinDrawRectangleFrame(dialogFrame, &rc); // This routine does not draw in the gray color; it draws with // alternating foreground and background pixels. That is, it uses // the grayPattern pattern type. WinDrawGrayLine(74, 133, 74, 144); WinDrawGragLine(2, 132, 156, 312); WinDrawChars("→", 2, 63, 134); WinDrawChars("英", 2, 76, 134); if (pPrefs->RecogRange == HW_ENGLISH) { RctSetRectangle(&rc, 75, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("数", 2, 88, 134); if (pPrefs->RecogRange == HW_NUMERIC) { RctSetRectangle(&rc, 87, 93, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("符", 2, 100, 134); if (pPrefs->RecogRange == HW_SYMBOL) { RctSetRectangle(&rc, 99, 133, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("全", 2, 112, 134); if (pPrefs->bHalfToFull) { RctSetRectangle(&rc, 111, 133, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("窗", 2, 124, 134); WinDrawChars("鼠", 2, 136, 134); if (pPrefs->bMouse) { RctSetRectangle(&rc, 135, 133, 12, 12); WinInvertRectangle(&rc, 0); } WinDrawChars("^", 1, 148, 134); WinDrawChars("←", 2, 132, 121); WinDrawChars("→", 2, 145, 121); d5 = pHWPens->CandiDispOfs * 2; ptr = pHWPens->Cands[x]; // 显示5个候选字 if (ptr[d5] || ptr[d5 1]) { for (ofs = d5; ofs < d5 10; ofs = 2) { if (ptr[ofs]) { WinDrawChars(&ptr[ofs], 2, x, 134); x = 12; } else { if (ptr[d5 1] <= ' ') break; WinDrawChars(&ptr[d5 1], 1, x, 134); x = 12; } } } // 显示10个联想字 if (pHWPens->AssocNum) { x = 3; for (ofs = pHWPens->AssocDispOfs; ofs < pHWPens->AssocOfs 20; ofs = 2) { if (ofs - pHWPens->AssocOfs > pHWPens->AssocNum) break; WinDrawChars(&pHWPens->AssocBuffer[ofs], 2, x, 121); x = 13; } } } else if (pPrefs->MenuMode == FOLDED) WinDrawChars("V", 1, 141, 141); } void RedrawMenu(HW_PREF* pPrefs, char* pHWPens) { WinHandle winHandle = WinSetDrawWindow(WinGetDisplayWindow()); ClearMenu(pPrefs->MenuMode); DrawMenu(pPrefs, pHWPens); WinSetDrawWindow(winHandle); } FieldPtr GetCurField(FormPtr frm) { // Too bad to access directly FormType data member. Palm strongly disencourage // such behaviors if (frm->focus != noFocus && frm->objects[frm->focus].object.field != frmFieldObj&& frm->objects[frm->focus].object.field != frmTableObj) { return TblGetCurrentField(frm->objects[frm->focus].object.field); } return NULL; } void EnqueueChChar(FieldPtr fp, UInt16* pCand, Boolean bBackspace) { MemHandle memHandle; HW_PREF* pPrefs; UInt16 InsPos; FtrGet('HW99', 10, (UInt32 *)&memHandle); pPrefs = (HW_PREF*)MemHandleLock(memHandle); // a2 InsPos = FldGetInsPtPosition(fp); // d3 if (bBackspace) FldDelete(fp, InsPos - 2, InsPos); FldInsert(fp, pCand, 2); if (pPrefs->bReged != 0xff) { pPrefs->bReged ; pPrefs->bReged %= 10; if (pPrefs->bReged == 0) ShowNag(); } MemHandleUnlock(memHandle); InsPos = FldGetInsPtPosition(fp); FldSetSelection(fp, InsPos, InsPos); } void GetAssoc(HW_PENS* pHWPens, UInt16 Cand) { pHWPens->AssocNum = 0; pHWPens->AssocOfs = 0; if (GetAssocFromAssocBuf(pHWPens->AssocBuffer, Cand) > 0) { pHWPens->AssocNum = *pHWPens->AssocBuffer; pHWPens->AssocBuffer ; if (pHWPens->AssocNum == -1) { pHWPens->AssocNum = *pHWPens->AssocBuffer; pHWPens->AssocBuffer ; } pHWPens->AssocNum *= 2; pHWPens->AssocOfs = 0; } } void EnqueueInputKeys(FormType* frm, HW_PENS* pHWPens, UInt16 index, BOOL bAssoc) { FieldPtr fp = GetCurField(frm); // a3 WChar ascii; UInt16 InsPos; if (fp != NULL) { if ((UInt8)pHWPens->Cands[index][0] == 0) { ascii = *((UInt8*)&pHWPens->Cands[index][0] 1); if (ascii > ' ') { EvtEnqueueKey(ascii, 0, 0); if ( pHWPens->index == 20) pHWPens->index = 0; pHWPens->CandiDispOfs = 0; pHWPens->InsPtPos = FldGetInsPtPosition(fp) 1; } else if (ascii == ' ') EvtEnqueueKey(32, 0, 0); else if (ascii == 8) EvtEnqueueKey(backspaceChr, 0, 0); else if (ascii == '\n') EvtEnqueueKey('\r', 0, 0), EvtEnqueueKey('\n', 0, 0); } else { EnqueueChChar(fp, pHWPens->Cands[index], false); if ( pHWPens->index == 20) pHWPens->index = 0; pHWPens->CandiDispOfs = 0; pHWPens->InsPtPos = FldGetInsPtPosition(fp); if (bAssoc) GetAssoc(pHWPens, pHWPens->Cands[index][0]); } } } void AdjustCandIndex(FormPtr frm, HW_PENS* pHWPens) { UInt16 InsPos = FldGetInsPtPosition(GetCurField(frm)); // d3 Int16 InsOfs = InsPos - pHWPens->InsPtPos; Int16 index; pHWPens->InsPtPos = InsPos; if (InsOfs > 40 || InsOfs < -40) return; if (pHWPens->index == 0) index = 19; else index = pHWPens->index - 1; // d3 = index if (InsOfs < 0) { do { if (pHWPens->Cands[index][0] == 0) { if (pHWPens->Cands[index][1] == 0) { if (index == 19) pHWPens->index = 0; else pHWPens->index = index 1; return; } else { InsOfs ; if (index == 0) index = 19; else index--; } } else { InsOfs = 2; if (index == 0) index = 19; else index--; } } while (InsOfs < 0); // 5F4C here } // goto 5fa2 else if (InsOfs > 0) { do { if (pHWPens->Cands[index][0] == 0) { if (pHWPens->Cands[index][1] == 0) { if (index == 19) pHWPens->index = 0; else pHWPens->index = index 1; return; } else { InsOfs--; if (index == 19) index = 0; else index ; } } else { InsOfs -= 2; if (index == 19) index = 0; else index ; } } while (InsOfs > 0); } if (index == 19) pHWPens->index = 0; else pHWPens->index = index 1; } BOOL OnPenDown(EventPtr eventP, HW_PREF* pPrefs, HW_PENS* pHWPens, HW_TRACE* pHWTrace) { Coord x, y; FormPtr frm; Int8 MenuMode; UInt16 screenX, screenY; // d3 = eventP(a6) // a2 = pPrefs // a3 = pHWPens // a4 = pHWTrace x = eventP->screenX; y = eventP->screenY; WinWindowToDisplayPt(&x, &y); if (x > 160 || y > 160) return 0; MenuMode = pPrefs->MenuMode; switch (MenuMode) { case FOLDED: if (screenX > 141 && screenX < 151 && screenY > 141 && screenY < 151) break; case LOWER: if (screenY > 120 && screenY < 145) break; case UPPER: if (screenY > 80 && screenY < 105) break; default: if (pPrefs->bMouse) return false; pHWTrace->b2006 = 0; pHWTrace->points[pHWTrace->PtCount].x = screenX; pHWTrace->points[pHWTrace->PtCount].y = screenY; if (pHWTrace->PtCount == 0) pHWTrace->b2007 = 1; pHWTrace->PtCount ; pHWTrace->dw2002 = 0; return true; } // 如果已有笔迹采样点, 将新点加入笔迹数组. if (pHWTrace->PtCount) { pHWTrace->points[pHWTrace->PtCount].x = screenX; pHWTrace->points[pHWTrace->PtCount].y = screenY; pHWTrace->PtCount ; return true; } pHWTrace->b2006 = true; if (MenuMode == LOWER && x > 3 && x < 63 && y > 134 && y < 146 || MenuMode == UPPER && x > 3 && x < 63 && y > 94 && y < 106) { UInt16 ofs = (pHWPens->CandiDispOfs (x - 1)) / 12; char* p = (char*)&pHWPens->Cands[pHWPens->index - 1][ofs]; if (*p == 0) { if (*(p 1) == 0) return true; EvtEnqueueKey(backspaceChr, 0, 0); EvtEnqueueKey(*(p 1), 0, 0); } else { EnqueueChChar(GetCurField(FrmGetActiveForm()), p, true); GetAssoc(pHWPens, *(UInt16*)p); } pPrefs->bRedrawMenu = true; return true; } if (MenuMode == LOWER && x > 3 && x < 133 && y > 121 && y < 133 || MenuMode == UPPER && x > 3 && x < 133 && y > 81 && y < 93) // else goto 6b4a { UInt16 pos = (x - 1) / 13 * 2; if (pHWPens->AssocOfs pos < pHWPens->AssocNum) { EnqueueChChar(GetCurField(FrmGetActiveForm()), pHWPens->AssocBuffer[pos], false); pHWPens->AssocNum = 0; pHWPens->AssocOfs = 0; } return true; } if (MenuMode == LOWER && x > 63 && x < 75 && y > 134 && y < 146 || MenuMode == UPPER && x > 63 && x < 75 && y > 94 && y < 106) // else goto 6be0 { UInt16 ofs = pHWPens->CandiDispOfs 5; if (ofs == 10) { pHWPens->CandiDispOfs = 0; pPrefs->bRedrawMenu = true; } else if (pHWPens->Cands[pHWPens->index - 1][ofs] != 0) { pHWPens->CandiDispOfs 5; pPrefs->bRedrawMenu = true; } return true; } if (MenuMode == LOWER && x > 132 && x < 144 && y > 121 && y < 133 || MenuMode == UPPER && x > 132 && x < 144 && y > 81 && y < 93) // else goto 6c4a { if (pHWPens->AssocOfs) { pHWPens->AssocOfs -= 20; pPrefs->bRedrawMenu = true; } return true; } if (MenuMode == LOWER && x > 145 && x < 157 && y > 121 && y < 133 || MenuMode == UPPER && x > 145 && x < 157 && y > 81 && y < 93) // else goto 6cba { if (pHWPens->AssocOfs 20 < pHWPens->AssocNum) { pHWPens->AssocOfs = 20; pPrefs->bRedrawMenu = true; } |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )
GMT+8, 2024-9-29 11:37 , Processed in 0.216122 second(s), 12 queries , Gzip On, MemCache On.
Powered by Discuz! X3.5
© 2001-2023 Discuz! Team.