找回密码
 注册
搜索
热搜: 回贴

汉王手写输入的系统部分(Palm平台)(20千字),汉王,Palm,逆向工程技术

2010-1-30 18:38| 发布者: admin| 查看: 279| 评论: 0|原作者: 九天玄女


汉王手写输入的系统部分(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;

}


最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏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.

返回顶部