最近想看看,OD插件编写,顺手把它翻译了.我英语差,看的懂就行了.:)
还有个问题,我在工具版下的plugin sdk masm编译不通过,不知是什么回事,我用的是masm32v8和radasm.谁能告诉原因.
顺便建议一下,能不能把OD开发的Plugins.hlp翻译了.
Sample.asm:
;//////////////////////////////////////////////////////////////////////////////////
;// //
;// SAMPLE PLUGIN FOR OLLYDBG //
;// //
;// 这个插件允许使用键盘快捷设立10 code bookmarks或者分拆popup菜单和很快的返回 //
;// bookmarks使用的快捷键,popup菜单或者Bookmark窗口.在文件Bookmarks保存session中.//
;// //
;//////////////////////////////////////////////////////////////////////////////////
.386
.model flat, stdcall ; 32 bit 内存模块
option scoped ; local labels被激活, global labels 在里面
; PROC将被用double冒号定义(LABEL::)
option casemap :none ; case sensitive
include windows.inc
include kernel32.inc
include user32.inc
include ..\plugin.inc
includelib kernel32.lib
includelib user32.lib
includelib ..\ollydbg.lib
.data?
hinst HINSTANCE ? ; DLL接口 instance
hwmain HWND ? ;OllDbg主窗口句柄
bookmarkwinclass db 32 dup (?) ;bookmark窗口类的名称
; ollydbg支持和广泛利用特殊的数据收集
; 所谓分类表. 表由广义表(t_table)和数据组成. 所有
; 数据元素具有相同的大小和开始为期3dword header:地址、大小
; 和类型. 由地址自动分类项目表,不允许重叠.
; 我们bookmark表包含类型t_bookmark成分.
t_bookmark struc 1
index dword ? ;bookmark索引(0..9)
size_ dword ? ;索引大小,在我们case总是1
type_ dword ? ;入口的类型,总是0
addr_ dword ? ;bookmark的地址
t_bookmark ends
bookmark t_table <> ;bookmark表
; 在这个文件的函数或多或少"按顺序排列"的命令,
; 即由ollydbg先后次序call. 这就需要向前
; 提交.
Bookmarksortfunc proto C b1:ptr t_bookmark, b2:ptr t_bookmark, sort:dword
Bookmarkwinproc proto hw:HWND, msg:UINT, wp:WPARAM, lp:LPARAM
Createbookmarkwindow proto
;int Bookmarkgettext(char *s,char *mask,int *select,t_sortheader *ph,int column);
;void Createbookmarkwindow(void);
.code
; Entry指向插件DLL. 许多系统调用的DLL接口
; 通过dllentrypoint()作为参数之一. 记住了.
; 首选的方法是放置initializations到ODBG_Plugininit()同时
; 清理odbg_plugindestroy().
DllEntryPoint proc hi:HINSTANCE, reason:dword, res:dword
.IF reason == DLL_PROCESS_ATTACH
m2m hinst, hi ; Mark plugin 接口
.ENDIF
return 1 ; 返回成功
DllEntryPoint endp
; odbg_plugindata()是"必须"有效ollydbg插件. 必须填写
; 插件名称和返回插件接口版本. 如果缺少这个函数,
; 或不兼容的版本,插件将不会被安装. Short name
; 在插件菜单识别它. 这个名称是max. 31包括字母或数字
; 性质或间隔+以'\0'终结. 为使用者简易维护
; 这个名称将被用DLL的名称描述和相关.
ODBG_Plugindata proc C shortname:ptr byte
invoke lstrcpy, shortname, CTEXT("Bookmarks") ; Name of plugin
return PLUGIN_VERSION;
ODBG_Plugindata endp
; ollydbg在一次启动期间必须call这个函数.放置所有
; 一次性初始化这里. 如果所有资源成功分配,
; 函数必须返回0. 错误的话,必须释放部分分配的的资源
; 返回-1,在这种情况下插件将会被取消. 参数ollydbgversion
; 是ollydbg的版本,它被用来告诉你,用你的插件是兼容
; 的; hw是ollydbg主窗口句柄(handle),如果必要保持它.
; 参数features是为日后扩展预留的,不要使用它.
ODBG_Plugininit proc C ollydbgversion:dword, hw:HWND, features:ptr dword
; 测试OllyDbg版本是正确的.
.IF ollydbgversion < PLUGIN_VERSION
jmp @@bad_exit
.ENDIF
; 保持ollydbg主窗口句柄. 这个句柄是必要的,例如
; 显示消息框.
m2m hwmain, hw
; 初始化bookmark数据. 数据以类型t_bookmark为基础组成,
; 为10 elements我们预留空位. 如有必要,表将分配更多
; 空间,但是,我们遇到的最大bookmarks数是10. Elements并不
; 分配内存或其他资源,所以销毁是没有必要的.
invoke Createsorteddata, offset bookmark.data, CTEXT("Bookmarks"),
sizeof t_bookmark, 10, offset Bookmarksortfunc, NULL
.IF eax
jmp @@bad_exit
.ENDIF
; 为MDI窗口注册窗口类,这个将显示插件. 请
; 注意这个类属于主ollydbg编程的接口
; 不是插件DLL. 字符串bookmarkwinclass取得唯一的新类名.
; 保持它到建立窗口和关闭窗口unregister.
invoke Registerpluginclass, offset bookmarkwinclass, NULL, hinst, offset Bookmarkwinproc
.IF eax < 0
; Failure! Destroy sorted data and exit.
invoke Destroysorteddata, offset bookmark.data
jmp @@bad_exit
.ENDIF
; 插件初始化成功. 向日志窗口报告这一行为现在是最好的时机
; . 要符合ollydbg外观,请用两句.
; 第一,在black,说明插件,第二变灰和缩进
; 由两个字符、承担版权说明.
invoke Addtolist, 0, 0, CTEXT("Bookmarks sample plugin v1.08 (plugin demo)")
invoke Addtolist, 0, -1, CTEXT(" Copyright (C) 2001, 2002 Oleh Yuschuk")
; ollydbg用用属性table_savepos保存插件窗口位置
; 到. INI文件,但并不自动恢复他们. 这里让我们加上
; 功能性. 无论是公开信息的窗口,当ollydbg终止时我在olldbg.ini保持信息无论窗口是打开
; . 这一信息是保存在
; odbg_pluginclose. 符合ollydbg标准,若选择打开被激活
; 窗口被恢复.
invoke Plugingetvalue, VAL_RESTOREWINDOWPOS
push eax
invoke Pluginreadintfromini, hinst, CTEXT("Restore bookmarks window"), 0
pop ecx
.IF eax && ecx
invoke Createbookmarkwindow
.ENDIF
return 0
@@bad_exit:
return -1
ODBG_Plugininit endp
; 退出时ollydbg call这个可选函数. 此时,所有由plugin建立的MDI
; 窗口已经被毁造(收到WM_DESTROY
; 消息). 函数必须释放所有内部资源,如
; 窗口类,文件,内存等.
ODBG_Plugindestroy proc C
invoke Unregisterpluginclass, offset bookmarkwinclass
invoke Destroysorteddata, offset bookmark.data
ret
ODBG_Plugindestroy endp
; 当用户需要打开新的或重启动当前程序这个函数被call.
; 插件重新安排内部变量和数据结构为初始状态.
ODBG_Pluginreset proc C
invoke Deletesorteddatarange, offset bookmark.data, 0, 0FFFFFFFFh
ret
ODBG_Pluginreset endp
; 当用户想终止择ollydbg,ollydbg call这个可选函数.
; 所有由插件建立的MDI窗口仍然存在. 如果要安全的终止函数必须返回0
; . 任何非零返回将停止结束序列.
; 不滥用这种可能性! 要告诉用户这个约定为什么
; 终止是不好的,并询问他决定!
ODBG_Pluginclose proc C
; 自动恢复打开窗口,mark在. INI文件
; Bookmarks窗口是否仍然打开.
mov eax, bookmark.hw
.IF eax
mov eax, 1
.ENDIF
invoke Pluginwriteinttoini, hinst, CTEXT("Restore bookmarks window"), eax
return 0
ODBG_Pluginclose endp
; 由一些标准严格分类数据种类,要提供分类函数
; 返回-1如果第一要素是少于二,1如果第一点是
; 包括周围和如果均等的依照分类标准0. 通常
; 在窗口这一标准是零基指数.
Bookmarksortfunc proc C b1:ptr t_bookmark, b2:ptr t_bookmark, sort:dword
LOCAL i:dword
mov ecx, 1
mov esi, b1
mov edi, b2
.IF sort == 1
mov eax, [esi].t_bookmark.addr_
.IF eax < [edi].t_bookmark.addr_
mov ecx, -1
.ELSEIF eax > [edi].t_bookmark.addr_
mov ecx, 1
.ENDIF
.ENDIF
.IF ecx == 1
mov eax, [esi].t_bookmark.index
.IF eax < [edi].t_bookmark.index
mov ecx, -1
.ELSEIF eax > [edi].t_bookmark.index
mov ecx, 1
.ENDIF
.ENDIF
return ecx
Bookmarksortfunc endp
; 标准函数painttable()使得ollydbg调整大部分窗口重新. 你
; 仅需要供应其他编写文本串函数,
; 可选择颜色. 定制窗口方案是比较复杂的,
; 请阅读文件.
Bookmarkgettext proc s:ptr byte, mask_:ptr byte, select:ptr dword, ph:ptr t_sortheader, column:dword
mov eax, column
.IF !eax ;bookmark的名字
; bookmark的栏0包含名在"Alt+n",其中n是
; 数字从0到9. 主要用于示范用途,我展示前缀
; "Alt+"变灰和在正常文本数字. 标准表格窗口
; 不用理会选择.
mov eax, ph
invoke wsprintf, s, CTEXT("Alt+%i"), [eax].t_bookmark.index
mov eax, select
mov dword ptr [eax], DRAW_MASK
invoke RtlFillMemory, mask_, 4, DRAW_GRAY
mov eax, mask_
mov byte ptr [eax + 4], DRAW_NORMAL
invoke lstrlen, s
.ELSEIF eax == 1 ; Address of bookmark
mov eax, ph
invoke wsprintf, s, CTEXT("%08X"), [eax].t_bookmark.addr_
invoke lstrlen, s
.ELSEIF eax == 2 ;分拆(Disassembled)命令
; 函数Disasm()命令calling程序代码到
; 分拆. 读内存代码. 最先确定可能的
; 代码大小.
invoke wsprintf, s, CTEXT("column %d"), eax
invoke lstrlen, s
.ELSEIF eax == 3
mov eax, ph
invoke Findname, [eax].t_bookmark.addr_, NM_COMMENT, s
.ELSE
xor eax, eax
.ENDIF
ret
Bookmarkgettext endp
; 每个窗口类需要自己窗口程序. 无论标准的和定制的
; OllyDbg窗口必须通过一些系统和OllyDbg-defined定义的消息到
Bookmarkwinproc proc hw:HWND, msg:UINT, wp:WPARAM, lp:LPARAM
;LOCAL controlkey, shiftkey:dword
LOCAL menu:HMENU
;LOCAL pb:ptr t_bookmark
mov eax, msg
; 标准消息. 你能及时处理他们,但要有绝对的把握-
; 总是通过他们到tablefunction().
.IF eax == WM_DESTROY || eax == WM_MOUSEMOVE || eax == WM_LBUTTONDOWN || \
eax == WM_LBUTTONDBLCLK || eax == WM_LBUTTONUP || eax == WM_RBUTTONDOWN || \
eax == WM_RBUTTONDBLCLK || eax == WM_HSCROLL || eax == WM_VSCROLL || eax == WM_TIMER || eax == WM_SYSKEYDOWN
invoke Tablefunction, offset bookmark, hw, msg, wp, lp
; 通过信息到defmdichildproc.
; 为卷轴和选择定制可靠消息.用户绘制(User-drawn)
; 窗口必须及时处理,标准ollydbg窗口没有额外
; 功能通知他们到tablefunction().
.ELSEIF eax == WM_USER_SCR || eax == WM_USER_VABS || eax == WM_USER_VREL || \
eax == WM_USER_VBYTE || eax == WM_USER_STS || eax == WM_USER_CNTS || eax == WM_USER_CHGS
invoke Tablefunction, offset bookmark, hw, msg, wp, lp
ret
.ELSEIF eax == WM_USER_MENU
invoke CreatePopupMenu
mov menu, eax
; 查找选定bookmark. 如果存在至少一个bookmark退出及被选定
; 一些用bookmark操作仅仅产生判断. 记录分类数据
; 有特殊分类表只在必要时更新.
; getsortedbyselection()做这个
; 有些数据整理函数
; 不工作,你必须call sortsorteddata(). 阅读文件!
invoke Getsortedbyselection, offset bookmark.data, bookmark.data.selected
mov esi, eax
.IF menu && eax
invoke AppendMenu, menu, MF_STRING, 1, CTEXT("&Follow",9,"Enter")
invoke AppendMenu, menu, MF_STRING, 2, CTEXT("&Delete",9,"Del")
.ENDIF
; 即使菜单无效,call tablefunction仍然有意义.
invoke Tablefunction, offset bookmark, hw, WM_USER_MENU, 0, menu
push eax
mov eax, menu
.IF eax
invoke DestroyMenu, eax
.ENDIF
pop eax
.IF eax == 1 ;在分拆跟随bookmark Follow bookmark in Disassembler
invoke Setcpu, 0, [esi].t_bookmark.addr_, 0, 0, CPU_ASMHIST or CPU_ASMCENTER or CPU_ASMFOCUS
.ELSEIF eax == 2 ; 删除Delete bookmark
invoke Deletesorteddata, offset bookmark.data, [esi].t_bookmark.index
; 无自动更新窗口,你自己do.
invoke InvalidateRect, hw, NULL, FALSE
.ENDIF
return 0
.ELSEIF eax == WM_USER_DBLCLK
; 在分拆双精度行(Doubleclicking row)跟随bookmark.
invoke Getsortedbyselection, offset bookmark.data, bookmark.data.selected
.IF eax
invoke Setcpu, 0,[eax].t_bookmark.addr_, 0, 0, CPU_ASMHIST or CPU_ASMCENTER or CPU_ASMFOCUS
.ENDIF
return 1 ; Doubleclick 处理processed
.ELSEIF eax == WM_USER_CHALL || eax == WM_USER_CHMEM
; 有些改变,重绘窗口.
invoke InvalidateRect, hw, NULL, FALSE
return 0
.ELSEIF eax == WM_PAINT
; 由Painttable()绘制所有ollydbg窗口. 使定制
; 仅仅画出如果你有重要原因这样做.
invoke Painttable, hw, offset bookmark, offset Bookmarkgettext
return 0
.ENDIF
invoke DefMDIChildProc, hw, msg, wp, lp
ret
Bookmarkwinproc endp
; 记录类型在ollydbg和插件中必须是唯一的. 最好
; 保证这是由OllDbg (Oleh Yuschuk)注册标明类型. 注册
; 完全免费,除电子邮件费用:)
TAG_BOOKMARK equ 0236D420Ah ; Bookmark record type in .udd file
; 为了节省时间保存数据到.udd文件! 这是由call pluginsaverecord()
; 为每个数据项必须被保存. 全局性,面向过程的数据必须
; 主要.udd文件(名称由.exe确定); 模块相关资料必须
; 保存在模块文件. 勿忘保存各项相对地址到
; 模块基址, 即使模块变化也能使数据准确被恢复.
ODBG_Pluginsaveudd proc C pmod:ptr t_module, ismainmodule:dword
LOCAL data[2]:dword
.IF !ismainmodule ; 仅仅bookmarks保存到主文件Save bookmarks to main file only
ret
.ENDIF
mov esi, bookmark.data.data
mov ebx, bookmark.data.n
.WHILE ebx > 0
mov eax, [esi].t_bookmark.index
mov data[0], eax
mov eax, [esi].t_bookmark.addr_
mov data[1 * sizeof dword], eax
invoke Pluginsaverecord, TAG_BOOKMARK, sizeof data, addr data
dec ebx
add esi, sizeof t_bookmark
.ENDW
ret
ODBG_Pluginsaveudd endp
; ollydbg恢复数据.udd文件. 如果属于记录插件,它必须
; 处理记录并返回1 否则必须返回0通过纪录
; 其他插件. 注意模块由广义指向不完善的pmod,
; 即不一定都含有信息, 尤其
; 从.udd文件.
ODBG_Pluginuddrecord proc C pmod:ptr t_module, ismainmodule:dword, tag:dword, size_:dword, data:dword
LOCAL mark:t_bookmark
mov eax, ismainmodule
.IF !eax
return eax ; 仅仅bookmarks保存到主文件Bookmarks saved in main file only
.ENDIF
.IF tag != TAG_BOOKMARK
return 0 ;标记符没有验证 Tag is not recognized
.ENDIF
mov ecx, data
mov eax, [ecx]
mov mark.index, eax
mov mark.size_, 1
mov mark.type_, 0
mov eax, [ecx + 4]
mov mark.addr_, eax
invoke Addsorteddata, offset bookmark.data, addr mark
return 1 ;记录进程 Record processed
ODBG_Pluginuddrecord endp
; 当建立标准MDI窗口时ollydbg进行大部分工作. 插件只需要作为一个整体
; 描述栏目数量,窗口的性质和性能.
Createbookmarkwindow proc
; Describe table columns. Note that column names are pointers, so strings
; must exist as long as table itself.
.IF !bookmark.bar.nbar
; Bar still uninitialized.
mov bookmark.bar.name_, CTEXT("Bookmark") ; Name of bookmark
mov bookmark.bar.defdx, 9
mov bookmark.bar.mode, 0
mov bookmark.bar.name_[1 * sizeof dword], CTEXT("Address") ; Bookmark address
mov bookmark.bar.defdx[1 * sizeof dword], 9
mov bookmark.bar.mode[1 * sizeof byte], 0
mov bookmark.bar.name_[2 * sizeof dword], CTEXT("Disassembly") ; Disassembled command
mov bookmark.bar.defdx[2 * sizeof dword], 32
mov bookmark.bar.mode[2 * sizeof byte], BAR_NOSORT
mov bookmark.bar.name_[3 * sizeof dword], CTEXT("Comment") ; Comment
mov bookmark.bar.defdx[3 * sizeof dword], 256
mov bookmark.bar.mode[3 * sizeof byte], BAR_NOSORT
mov bookmark.bar.nbar, 4
mov bookmark.mode, TABLE_COPYMENU or TABLE_SORTMENU or TABLE_APPMENU or TABLE_SAVEPOS;
mov bookmark.drawfunc, offset Bookmarkgettext
.ENDIF
; 如果窗口已经存在,quicktablewindow()不建立新窗口
; 但为了恢复和扩展现有顶步. 这是最简单的方法,
; newtablewindow()更为灵活,更复杂. 没有很重要的理由我不推荐
; 定制(插件绘制)窗口.
invoke Quicktablewindow, offset bookmark, 15, 4, offset bookmarkwinclass, CTEXT("Bookmarks")
ret
Createbookmarkwindow endp
; 如果你定义odbg_pluginmainloop,在ollydbg窗口这个函数将每次从循环主窗口被call.
; 如果这是从调试请求的一些调试事件
; ,debugevent指向它,否则NULL. 非必要
; 不要申明这个函数,因为这可能产生负面影响到
; 整体速度!
;ODBG_Pluginmainloop proc C debugevent:ptr DEBUG_EVENT
;ODBG_Pluginmainloop endp
; 函数添加任一项目到ollydbg主菜单(origin=pm_main)或popup
; 菜单在标准ollydbg窗口之一. 当插件要加上自己的菜单
; 项目,在数据中搜集菜单式样和返回1, 否则必须
; 返回0. 除了静态主菜单,插件不要添加非活动项目.
; 项目指数在0..63范围. 完全相同索引是明确允许的.
ODBG_Pluginmenu proc C uses ebx origin:dword, data:ptr byte, item:dword
LOCAL pb:ptr t_bookmark
LOCAL pd:ptr t_dump
mov eax, origin
; 菜单创作很简单. 你只需填写数据与菜单格式.
; 一些例子:
; 0 Aaa,2 Bbb|3 Ccc|,, - 线性菜单有3项,相对的IDS 0 ,2和
; 3,分隔线在第二和第三项之间,最后
;
; 分隔线和逗号被忽略;
; #A{0Aaa,B{1Bbb|2Ccc}} - 无条件的分隔,popup菜单紧随
; 一两个要件,二是popup用两
; 级分离分子.
.IF eax == PM_MAIN ;Plugin菜单在主窗口 Plugin menu in main window
invoke lstrcpy, data, CTEXT("0 &Bookmarks|1 &About")
;如果你的plugin是有价值,我也推荐到include帮助
; If your plugin is more than trivial, I also recommend to include Help.
return 1
.ELSEIF eax == PM_DISASM ; Popup menu in Disassembler
; 首先检查菜单适用性.
mov eax, item
.IF !eax || ![eax].t_dump.size_
return 0 ; Window空闲,不添加.Window empty, don't add
.ENDIF
; 从二级popup菜单.
; Start second-level popup menu.
invoke wsprintf, data, CTEXT("Bookmark{")
invoke lstrlen, data
add eax, data
mov ebx, eax
; 添加项目"插入bookmark n"如果释放bookmarks及部分
; 选定分拆. 注意ollydbg正确演示
; superfluos逗号,分隔,并在一定程度上失去支撑.
mov esi, bookmark.data.data
xor ecx, ecx
.WHILE ecx < bookmark.data.n
.BREAK .IF [esi].t_bookmark.index != ecx
add esi, sizeof dword
inc ecx
.ENDW
mov esi, item
mov eax, [esi].t_dump.sel1
.IF ecx < 10 && (eax > [esi].t_dump.sel0)
invoke wsprintf, ebx, CTEXT("%i &Insert bookmark %i",9,"Alt+Shift+%i,"), ecx, ecx, ecx
invoke lstrlen, ebx
add ebx, eax
.ENDIF
; 添加项目"删除bookmark n"每次可利用bookmark. 菜单
; 标识不一定连续.
mov esi, bookmark.data.data
xor ecx, ecx
.WHILE ecx < bookmark.data.n
mov eax, [esi].t_bookmark.index
add eax, 10
push ecx
invoke wsprintf, ebx, CTEXT("%i Delete bookmark %i,"), eax, [esi].t_bookmark.index
add esi, sizeof dword
invoke lstrlen, ebx
pop ecx
add ebx, eax
inc ecx
.ENDW
; 加上分隔到菜单.
mov byte ptr [ebx], '|'
inc ebx
; 添加项目"到达bookmark n"每次可利用bookmark. Bookmarks
; 设置在搜集命令司令部不显示.
mov esi, bookmark.data.data
xor ecx, ecx
.WHILE ecx < bookmark.data.n
mov eax, item
mov eax, [eax].t_dump.sel0
.IF eax != [esi].t_bookmark.addr_
mov eax, [esi].t_bookmark.index
add eax, 20
push ecx
invoke wsprintf, ebx, CTEXT("%i Go to bookmark %i",9,"Alt+%i,"), eax, [esi].t_bookmark.index, [esi].t_bookmark.index
add esi, sizeof dword
invoke lstrlen, ebx
pop ecx
add ebx, eax
.ENDIF
inc ecx
.ENDW
; 关闭popup. 如果你忘记这样做,ollydbg将设法纠正
; 你的错误.
mov word ptr [ebx], '}'
return 1
.ENDIF
return 0
ODBG_Pluginmenu endp
; 这个可择函数从在类型起源窗口的插件菜单接受命令.
; 启动行为是从odbg_pluginmenu()的菜单标识符. 如果用户建立
; 启动自动进入主菜单,行动是0.
ODBG_Pluginaction proc C origin:dword, action:dword, item:dword
LOCAL mark:t_bookmark
;LOCAL pb:ptr t_bookmark
;LOCAL pd:ptr t_dump
mov eax, origin
.IF eax == PM_MAIN
mov eax, action
.IF !eax
; 项目菜单"Bookmarks",建立bookmark窗口.
invoke Createbookmarkwindow
.ELSEIF eax == 1
; 菜单项目"About",列出插件信息.
invoke MessageBox, hwmain, CTEXT("Bookmark plugin v1.08",13,10,"(demonstration of plugin capabilities)",13,10,"Copyright (C) 2001, 2002 Oleh Yuschuk",13,10,"MASM32 version by Eviloid, 2oo3"),\
CTEXT("Bookmark plugin"),MB_OK or MB_ICONINFORMATION
.ENDIF
.ELSEIF eax == PM_DISASM
mov eax, action
.IF eax >= 0 && eax < 10 ; Insert bookmark
mov mark.index, eax
mov mark.size_, 1
mov mark.type_, 0
mov eax, item
m2m mark.addr_, [eax].t_dump.sel0
invoke Addsorteddata, offset bookmark.data, addr mark
.IF bookmark.hw
invoke InvalidateRect, bookmark.hw, NULL, FALSE
.ENDIF
.ELSEIF eax >= 10 && eax < 20 ; Delete bookmark
sub eax, 10
mov ebx, eax
invoke Findsorteddata, offset bookmark.data, eax
.IF eax
invoke Deletesorteddata, offset bookmark.data, ebx
.IF bookmark.hw
invoke InvalidateRect, bookmark.hw, NULL, FALSE
.ENDIF
.ENDIF
.ELSEIF eax >= 20 && eax < 30 ; Go to bookmark
sub eax, 20
; mov ebx, eax
invoke Findsorteddata, offset bookmark.data, eax
.IF eax
invoke Setcpu, 0, [eax].t_bookmark.addr_, 0, 0, CPU_ASMHIST or CPU_ASMCENTER or CPU_ASMFOCUS
.ENDIF
.ENDIF
.ENDIF
ret
ODBG_Pluginaction endp
end DllEntryPoint
- 标 题: 【翻译】plugin sdk masm sample注释翻译
- 作 者:layper
- 时 间:2007-02-09 18:55
- 链 接:http://bbs.pediy.com/showthread.php?t=39394