<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/xsl/rss.xsl" type="text/xsl" media="screen"?>
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:ppp="http://blog.sohu.com/rss/module/ppp/"
	>

	<channel>
		<title>深蓝无忌</title>
		<link>http://itmed.blog.sohu.com/</link>
		<description><![CDATA[--专注医疗信息化]]></description>
		<pubDate>Fri, 4 Jul 2008 17:21:56 +0800</pubDate>
		<generator>搜狐博客</generator>
		<ppp:ebi>cbf74e6792</ppp:ebi>
		<image>
			<title>http://blog.sohu.com</title>
			<url>http://js.pp.sohu.com/ppp/blog/images/common/logo_150_60.gif</url>
			<link>http://blog.sohu.com/</link>
			<width>100</width>
			<height>43</height>
			<description>搜狐博客</description>
		</image>
		<item>
			<title>如何编程导入*.srw </title>
			<link>http://itmed.blog.sohu.com/93682685.html</link>
			<comments>http://itmed.blog.sohu.com/93682685.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 4 Jul 2008 17:17:59 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/93682685.html</guid>
			<description><![CDATA[<p>如何编程导入*.srw </p>
<p>http://www.google.com/search?q=PowerBuilder+ORCA+API&amp;hl=zh-CN&amp;lr=&amp;start=10&amp;sa=N&nbsp;&nbsp; <br /></p>
<p>可以应用PB的库列表函数来进行 &nbsp; <br />&nbsp; ls_entries &nbsp; = &nbsp; LibraryDirectory( &nbsp; &quot;c:\pb\dwTemp.pbl&quot;, &nbsp; DirWindow! &nbsp; ) &nbsp; <br />&nbsp; 根据ls_entries读出每一个窗口名字 &nbsp; <br />&nbsp; 写循环进行处理 &nbsp; <br />&nbsp; do &nbsp; while &nbsp; rtncode=0 &nbsp; <br />&nbsp; ls_wsyn &nbsp; = &nbsp; LibraryExport(&quot;c:\pb\dwTemp.pbl&quot;,&quot;窗口名字&quot;, &nbsp; ExportWindow!) &nbsp; <br />&nbsp; rtncode &nbsp; = &nbsp; LibraryImport(&quot;c:\pb\dwTemp.pbl&quot;, &nbsp; &quot;窗口名字&quot;, &nbsp; ImportWindow!, &nbsp; &amp; &nbsp; <br />&nbsp; ls_wsyn, &nbsp; ErrorBuffer &nbsp; ) &nbsp; <br />&nbsp; loop&nbsp;&nbsp; <br /></p>]]></description>
		</item>
		    
		
		<item>
			<title>pb反编译研究</title>
			<link>http://itmed.blog.sohu.com/93681921.html</link>
			<comments>http://itmed.blog.sohu.com/93681921.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 4 Jul 2008 17:21:56 +0800</pubDate>
			<category>pb研究</category>
			<guid>http://itmed.blog.sohu.com/93681921.html</guid>
			<description><![CDATA[<p>pb代码维护的应用程序 http://www.mypcera.com/SOFTXUE/20073/pb/xljz/024.htm</p>
<p>api hook可以看一下这里<br /><a href="http://www.autodebug.com/">http://www.autodebug.com/</a></p>
<p>function long LMI_OpenLibrary60(long pbstg_begin,string path,long flag,long l) library 'pbvm60' alias for &quot;LMI_OpenLibrary&quot;<br /><br />参数1是pbstg_begin的返回，参数2是pbl或pbd路径，3是1，4是0，有兴趣的可以试下参数3、4调换别的值，如果不怕pb狂死的话。<br />会返回一个libraryhandle（库的句柄，俺命的名）</p>
<p>function long LMI_CloseLibrary60(long libraryhandle) library 'pbvm60' alias for &quot;LMI_CloseLibrary&quot;</p>
<p>参数只有一个就是刚刚的句柄，返回0成功。</p>
<p>function long pbstg_alc(long pbstg_begin,long l,long p) library 'pbvm60' </p>
<p>第一个还是pbstg_begin的返回，第二个是5，第三个是0。顺便说下，这些参数的值是pb调用该函数时候传的，<br />参数的含义一概不知，而且，还没有到乱试的阶段&hellip;&hellip;，这函数啥意义我也不知道，具体后述</p>
<p>function long LMI_ListEntriesExtended(long libraryhandle,long l) library 'pbvm60'</p>
<p>说实话这函数还不能确定它是两个参数&hellip;&hellip;说白了，现阶段一调这函数似乎就进入了死循环&hellip;&hellip;</p>
<p>基本上pb显示一个pbl或者pbd里边的对象列表调用的函数顺序都是：<br />LMI_OpenLibrary<br />pbstg_alc//似乎是分配什么东西，pbstg_begin也有stg，stg到底是什么？shooting game&hellip;&hellip;?<br />LMI_ListEntriesExtended<br />LMI_CloseLibrary<br />也就是说，今天只实现了打开关闭一个库文件&hellip;&hellip;<br />现在仔细考虑的话，lmi万一是ListManageInteface的话，一切都是绕远啊&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;<br />我现在还是想要不然先解决导入？导入似乎比列表简单些？<br />列表导入都实现了，然后就差最后一步了，真的能实现么&hellip;&hellip;</p>
<p><span>&nbsp; </span></p>
<p>原理大概是开api hook，截获pb自身如何导入sr*到pbl中，这就解决了libraryimport只能import数据窗的缺陷<br />至于如何生成sr*&hellip;&hellip;，同样想办法截吧~~<br />顺便说下截获两个字说起来容易，实质上俺的pb至少非法被关闭30次了&hellip;&hellip;<br />太难，只能阶段性放上成果，现阶段找到了4个函数<br />lmi_openlibrary<br />lmi_libraryinformation//改pbl的注释&hellip;&hellip;<br />lmi_closelibrary<br />lmi_createlibrary<br />其中lmi_createlibrary顾名思义就是创建一个新pbl用的，声明为：<br />function long LMI_CreateLibrary(long l,string path,long flag) library 'pbvm60'<br />第一个参数似乎必须写23920744，啥含义我也不知道，反正我机子上写这个就能成功<br />第二个参数就是要创建的pbl的路径，如：C:\test_pb\pbd2pbl\test.pbl<br />第三个参数写0吧，别问我为什么&hellip;&hellip;</p>
<p>返回值0是正确，-2是文件已经存在，-19也遇到了，当时是第一个参数写0,今天先到这里吧。</p>]]></description>
		</item>
		    
		
		<item>
			<title>PB动态脚本解释器(转载)</title>
			<link>http://itmed.blog.sohu.com/93681006.html</link>
			<comments>http://itmed.blog.sohu.com/93681006.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 4 Jul 2008 16:58:28 +0800</pubDate>
			<category>pb研究</category>
			<guid>http://itmed.blog.sohu.com/93681006.html</guid>
			<description><![CDATA[<p align="center">PB动态脚本解释器(转载)</p>
<div>
<div style="WIDTH: 760px">当你看到VB、VFP等开发语言提供的强大的宏执行功能，是不是很羡慕呢？当你寻遍 PB的帮助、关于PB开发的书籍或网站而不可得的时候，是不是感到有一丝的遗憾？如果你看到这篇文章，你应该感到振奋，因为你终于可以解决这个问题，而且解决问题的思路既是如此简单、代码既是如此简短。如果再加上你的智慧，应该比我的解决方法更漂亮。 
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>先让我们来了解一些基本知识。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>一．</span>代码的载体</div>
<div style="TEXT-INDENT: 21pt">在PB中，只有三个地方可以存放代码，那就是函数、事件、属性。这里所指的函数包括有返回值的通常意义下的函数和无返回值的过程以及声明的WINAPI函数，所指的事件指在对象中定义的处理程序，所指的属性指PB系统属性之外的实例变量、共享变量、全局变量。函数和事件是可以用来调用执行的，属性则只能用来赋值和取值。通常我们是在函数或事件中编写代码。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>二．</span>对象的创建</div>
<div style="TEXT-INDENT: 21pt">如果对象类型是已知的，可以使用CREATE objecttype 来创建对象，如果对象类型是动态的，可以使用CREATE USING objecttypestring来创建对象。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>三．</span>对象函数的调用方式</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>如果调用一个已知类型的对象的函数或事件，通常采用静态模式，也可采用动态模式，如果调用一个动态创建的对象的函数或事件，则必须采用动态模式，否则编译出错。采用动态模式调用函数是在函数前加dynamic 关键字。读者可查阅PB帮助。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>四．</span>库文件的搜索</div>
<div style="TEXT-INDENT: 21pt">PB中用于编程的对象是保存在PBL、PBD、DLL中的，如果想要使库文件中的对象在应用程序运行时有效，常用的方法是直接将该PBL编译进去或者说使该PBL在库搜索列表中。如果需要在运行状态下改变库文件搜索列表，PB提供了 SetLibraryList和AddToLibraryList两个函数。SetLibraryList函数只能在应用对象的open事件脚本中使用，否则应用程序会崩溃，AddToLibraryList为PB9新增的函数，用于将新文件加入到库文件搜索列表中，这两个函数都是只能在编译环境下有效。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>五．</span>PB库文件的创建与销毁</div>
<div style="TEXT-INDENT: 21pt">PB提供了LibraryCreate函数用于创建库文件，提供LibraryDelete、FileDelete函数用于删除库文件。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>六．</span>PB实体的导入</div>
<div style="TEXT-INDENT: 21pt">PB提供了LibraryImport函数用于根据对象语法创建PB实体并导入到库文件中，但该函数目前只支持数据窗口对象类型的导入。不过，PB提供了相应的WINAPI函数支持其它类型实体的导入，这些相关的WINAPI包括在 PBORCX0.DLL中（不同的PB版本有不同的文件名称，如PBORC90.DLL、PBORC80.DLL）。有关实体的导入的WINAPI包括 PBORCA_SessionOpen、PBORCA_SessionClose、PBORCA_SessionSetLibraryList、 PBORCA_SessionSetCurrentAppl、PBORCA_CompileEntryImport等，读者可以到Sybase网站找 ORCA Guide相应文章寻求支持。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>七．</span>PB实体的查找</div>
<div style="TEXT-INDENT: 21pt">使用FindClassDefinition或FindFunctionDefinition或LibraryDirectory可以在库文件中查找PB实体是否存在，使用FindClassDefinition或FindFunctionDefinition性能要好。</div>
<div style="TEXT-INDENT: 21pt">以下讲开发思路。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>一．</span>创建临时库文件</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>1.<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>取临时目录作为库文件的存放目录</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>2.<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>取待创建的临时库文件名称，保证不与已有文件重名</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>3.<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>使用LibraryCreate函数创建临时库文件</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>二．</span>构造用于导入库文件的临时PB实体语法</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>1．&nbsp;</span>取临时PB实体名称，保证不与库文件列表中已有PB实体重名</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>2．&nbsp;</span>构造临时PB实体语法，区分函数和过程</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>三．</span>将临时PB实体导入临时库文件</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>1．&nbsp;</span>取库文件列表和应用对象所在pbl</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>2．&nbsp;</span>将实际不存在的库文件从库文件列表中删除，目的是使调用PBORCA_SessionSetLibraryList成功</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>3．&nbsp;</span>调用PBORCA_CompileEntryImport将临时PB实体导入临时库文件</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>四．</span>将临时库文件加入到库文件搜索列表</div>
<div style="MARGIN-LEFT: 21pt">1．调用AddToLibraryList加入新文件到库文件搜索列表</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>五．</span>创建临时PB实体所对应的对象并调用其函数以执行动态脚本</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>1．&nbsp;</span>使用CREATE USING objecttypestring语句创建对象</div>
<div style="MARGIN-LEFT: 39pt; TEXT-INDENT: -18pt"><span>2．&nbsp;</span>通过动态调用对象的of_exec函数执行动态脚本，区分返回值类型</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>六．</span>销毁所有临时对象</div>
<div style="MARGIN-LEFT: 21pt">1．调用LibraryDelete函数删除创建的临时库文件</div>
<div style="TEXT-INDENT: 21pt">以下讲我在开发时遇到的一些矛盾或问题。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>一．</span>代码是逐行解释还是让PB编译器去解释</div>
<div style="TEXT-INDENT: 21pt">有些开发人员试图对动态脚本自行逐行解释，这是很困难的事情。一行代码如果脱离它的语境去执行，可能会产生错误的结果，即便你对PB所支持的函数全部做出解释，使用PB开发出来的对象、函数、事件等，你又如何去解释？这等同于你要花很大力气去编写一个PB编译器，除非你与PB编译器的开发团队合作，否则你很难获得成功。所以你必须想办法让PB编译器去解释。既然每行代码不能脱离其它代码而执行，那就创建一个函数或事件，让这个函数或事件包括你想写的所有代码。而函数或事件又不能脱离对象而存在，所以你必须想办法动态创建对象以及函数或事件，对象的声明必须依赖于库文件中的PB实体，由此推出关键是创建PB实体。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>二．</span>如何创建PB实体</div>
<div style="TEXT-INDENT: 21pt">前面已讲过要使用PBORCX0.DLL中的WINAPI函数来创建并导入实体，这项技术并不难，在sybase的网站或随便狗狗（百度）一下就能出来一大把。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>三．</span>创建的PB实体是存放在现有库文件中还是新文件中再导入</div>
<div style="TEXT-INDENT: 21pt">我最初的想法是放在现有库文件中，这样就不必花费时间在创建库文件和删除库文件的执行上，结果发现，创建是成功，但运行时PB就是不&ldquo;认识&rdquo;我创建的PB实体，一创建该实体的对象就报错，想来PB在程序启动时就读取库文件中有哪些实体形成列表，在没有改变库文件列表之前，其实体列表不会改变，这样对新建的实体就视而不见了。所以我不得不试着新建一个PBL，在新建的PBL中创建PB实体，然后使用AddToLibraryList将新建的PBL包括进来，这一试果然成功。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>四．</span>使用数据窗口的Describe调用全局函数还是其它方式来取得返回值</div>
<div style="TEXT-INDENT: 21pt">大家都知道，使用数据窗口的Describe函数可以调用全局函数，但是它有很多的局限性，全局函数必须有简单类型的返回值，所有参数只能是简单数据类型而且不能通过参考传值。如果在需要调用的地方直接使用新建对象的函数将不受这些限制。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>五．</span>如何进行垃圾对象的清理</div>
<div style="TEXT-INDENT: 21pt">既然每次执行动态脚本要创建PB实体，如果执行得多了，就有很多垃圾对象，所以应进行清理。可以通过LibraryDelete函数或FileDelete删除库文件。有意思的是，一旦创建PB实体，即便你删除了，使用 FindClassDefinition或FindFunctionDefinition还是能够找到，但你想使用该实体创建对象则失败，这再次说明PB 在程序启动时就读取库文件中有哪些实体形成列表，在没有改变库文件列表之前，其实体列表不会改变。</div>
<div style="TEXT-INDENT: 21pt">以下是所附代码的几点说明</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>一．</span>所附代码是在PB9环境下开发的，程序运行时必须有PBORC90.DLL，如果改成PB其它版本，请将nvo_pbcompiler中WINAPI函数所使用的动态库做相应修改。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>二．</span>nvo_pbcompiler 用于创建PB实体，这是PB动态脚本解释器的核心函数；f_execpbscript()用于执行一段PB脚本的样例代码函数，返回值类型为字符串，如果要使用到其它场合，读者可自行编写函数，思路类似；w_pbcompiler_test为一个用来执行PB脚本的样例界面窗口；其它函数有各自功能。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>三．</span>如果想运行PB动态脚本编译器，请先将所有代码分对象导入库文件，然后编译，PB动态脚本编译器在PB开发环境下无效。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>四．</span>为了程序方面的简化，有些所使用的全局函数请参考作者的其它文章。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>五．</span>所附代码仅为脚本没有参数的情况下有效，如果你想代码有参数，只需要简单地对脚本语法作些改变就可，当然前台需要用户定义参数。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>六．</span>本PB动态脚本解释器可执行所有有效的PB代码，例如访问全局变量、使用PB所有的系统函数、使用程序员开发的自定义函数、打开窗口、访问菜单、使用数据窗口等。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>七．</span>通常将本PB动态脚本解释器嵌入到现有的使用PB开发出来的系统而不是单独使用，这样可以加载很多免编译的外挂程序。</div>
<div style="MARGIN-LEFT: 42pt; TEXT-INDENT: -21pt"><span>八．</span>如果再拓宽它的应用范围，你甚至可以做到只需要一个框架程序，其它代码全部动态加载和执行，这样就只需一次编译，升级和维护就变得非常简单，不过你要考虑系统的可用性、系统性能和系统的稳定性等。</div>附完整源代码 
<div style="MARGIN-LEFT: 21pt">一．pbcompiler</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$pbcompiler.sra<br />$PBExportComments$PB动态脚本解释器应用对象</div>
<div style="MARGIN-LEFT: 21pt">forward<br />global type pbcompiler from application<br />end type<br />global transaction sqlca<br />global dynamicdescriptionarea sqlda<br />global dynamicstagingarea sqlsa<br />global error error<br />global message message<br />end forward</div>
<div style="MARGIN-LEFT: 21pt">global variables</div>
<div style="MARGIN-LEFT: 21pt">end variables<br />global type pbcompiler from application<br />string appname = &quot;pbcompiler&quot;<br />end type<br />global pbcompiler pbcompiler</div>
<div style="MARGIN-LEFT: 21pt">on pbcompiler.create<br />appname=&quot;pbcompiler&quot;<br />message=create message<br />sqlca=create transaction<br />sqlda=create dynamicdescriptionarea<br />sqlsa=create dynamicstagingarea<br />error=create error<br />end on</div>
<div style="MARGIN-LEFT: 21pt">on pbcompiler.destroy<br />destroy(sqlca)<br />destroy(sqlda)<br />destroy(sqlsa)<br />destroy(error)<br />destroy(message)<br />end on</div>
<div style="MARGIN-LEFT: 21pt">event open;open(w_pbcompiler_test)<br />end event</div>
<div style="MARGIN-LEFT: 21pt">二.f_execpbscript</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$f_execpbscript.srf<br />$PBExportComments$执行动态脚本的样例函数</div>
<div style="MARGIN-LEFT: 21pt">global type f_execpbscript from function_object<br />end type</div>
<div style="MARGIN-LEFT: 21pt">forward prototypes<br />global function string f_execpbscript (string as_returntype, string as_pbscript)<br />end prototypes</div>
<div style="MARGIN-LEFT: 21pt">global function string f_execpbscript (string as_returntype, string as_pbscript);/*******************************************************************<br />函数名称：f_execpbscript()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; as_returntype string 返回值类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; as_pbscript string 动态代码<br />返回值：&nbsp; string 用户自定义或错误信息<br />功能描述：执行动态代码(只返回字符串)<br />创建人：&nbsp; 康剑民<br />创建日期：2007-02-12<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />nvo_pbcompiler lnv_pbcompiler<br />nonvisualobject luo_pbcompiler<br />string ls_entryname,ls_libraryname<br />string ls_return<br />any la_return</div>
<div style="MARGIN-LEFT: 21pt">lnv_pbcompiler = create nvo_pbcompiler<br />//创建实体对象<br />if lnv_pbcompiler.of_createentry(as_returntype,as_pbscript,ls_libraryname,ls_entryname) = 1 then<br />&nbsp;if not isnull(FindClassDefinition(ls_entryname) ) then<br />&nbsp;&nbsp;luo_pbcompiler = create using ls_entryname<br />&nbsp;&nbsp;choose case lower(as_returntype)<br />&nbsp;&nbsp;case 'any','blob','boolean','char','character','date','datetime','dec','decimal','double','int','integer','long','real','string','time','uint','ulong','unsignedint','unsignedinteger','unsignedlong'<br />&nbsp;&nbsp;&nbsp;la_return = luo_pbcompiler.dynamic of_exec()//执行动态代码<br />&nbsp;&nbsp;&nbsp;ls_return = string(la_return)<br />&nbsp;&nbsp;case '','none'<br />&nbsp;&nbsp;&nbsp;luo_pbcompiler.dynamic of_exec()//执行动态代码<br />&nbsp;&nbsp;&nbsp;ls_return = &quot;none&quot;<br />&nbsp;&nbsp;case else<br />&nbsp;&nbsp;&nbsp;luo_pbcompiler.dynamic of_exec()//执行动态代码<br />&nbsp;&nbsp;&nbsp;ls_return = &quot;result is disabled&quot;<br />&nbsp;&nbsp;end choose<br />&nbsp;&nbsp;if isvalid(luo_pbcompiler) then destroy luo_pbcompiler<br />&nbsp;else<br />&nbsp;&nbsp;ls_return = &quot;error&quot;<br />&nbsp;end if<br />else<br />&nbsp;ls_return = &quot;error&quot;<br />end if<br />if isvalid(lnv_pbcompiler) then destroy lnv_pbcompiler</div>
<div style="MARGIN-LEFT: 21pt">LibraryDelete(ls_libraryname)</div>
<div style="MARGIN-LEFT: 21pt">return ls_return<br />end function</div>
<div style="MARGIN-LEFT: 21pt">三.f_parse</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$f_parse.srf<br />$PBExportComments$分解字符串到数组</div>
<div style="MARGIN-LEFT: 21pt">global type f_parse from function_object<br />end type</div>
<div style="MARGIN-LEFT: 21pt">forward prototypes<br />global function long f_parse (readonly string as_text, readonly string as_sep, ref string as_list[])<br />end prototypes</div>
<div style="MARGIN-LEFT: 21pt">global function long f_parse (readonly string as_text, readonly string as_sep, ref string as_list[]);/*******************************************************************<br />函数名称：f_parse()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; as_text string 来源字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; as_sep string 分隔字符<br />&nbsp;&nbsp;&nbsp; as_list[] ref string 分析后形成的字符串数组<br />返回值：&nbsp; long 分析后形成的数组元素个数<br />功能描述：分析字符串到一个数组中<br />创建人：&nbsp; 康剑民<br />创建日期：2002-11-19<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />long i,ll_pos<br />string ls_null[],ls_text</div>
<div style="MARGIN-LEFT: 21pt">ls_text = as_text<br />as_list = ls_null<br />i=0<br />ll_pos = posw(lower(ls_text),lower(as_sep))<br />do while ll_pos &gt; 0&nbsp;<br />&nbsp;i ++&nbsp;<br />&nbsp;as_list[i]=leftw(ls_text,ll_pos - 1)<br />&nbsp;ls_text=midw(ls_text,ll_pos + lenw(as_sep),lenw(ls_text))<br />&nbsp;ll_pos = posw(lower(ls_text),lower(as_sep))&nbsp;<br />loop<br />as_list[i + 1] = ls_text</div>
<div style="MARGIN-LEFT: 21pt">return upperbound(as_list[])<br />end function</div>
<div style="MARGIN-LEFT: 21pt">四.f_replacetext</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$f_replacetext.srf<br />$PBExportComments$替换字符串</div>
<div style="MARGIN-LEFT: 21pt">global type f_replacetext from function_object<br />end type</div>
<div style="MARGIN-LEFT: 21pt">forward prototypes<br />global function string f_replacetext (readonly string as_source, readonly string as_oldtag, readonly string as_newtag, readonly long al_seq)<br />end prototypes</div>
<div style="MARGIN-LEFT: 21pt">global function string f_replacetext (readonly string as_source, readonly string as_oldtag, readonly string as_newtag, readonly long al_seq);/*******************************************************************<br />函数名称：f_replacetext()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; as_source string 源字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; as_oldtag string 待替换特征字符串<br />&nbsp;&nbsp;&nbsp; as_newtag string 替换后特征字符串<br />&nbsp;&nbsp;&nbsp; al_seq long 第几个特征替换字符串需替换，0表示全部<br />返回值：&nbsp; string 替换后字符串<br />功能描述：用一特征字符串替换指定字符串中的特征字符串,参数al_seq=0时表示全部替换<br />创建人：&nbsp; 康剑民<br />创建日期：2002-11-19<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />long ll_start_pos=1,ll_len_old_tag,i = 0<br />string ls_left,ls_return='',ls_source=''</div>
<div style="MARGIN-LEFT: 21pt">ls_source = as_source<br />ll_len_old_tag = lenw(as_oldtag)<br />ll_start_pos = posw(lower(ls_source),lower(as_oldtag),1)<br />if al_seq = 0 then<br />&nbsp;DO WHILE ll_start_pos &gt; 0<br />&nbsp;&nbsp;ls_left = leftw(ls_source,ll_start_pos - 1) + as_newtag<br />&nbsp;&nbsp;ls_return = ls_return + ls_left<br />&nbsp;&nbsp;ls_source = midw(ls_source,ll_start_pos + lenw(as_oldtag),lenw(ls_source))<br />&nbsp;&nbsp;ll_start_pos = posw(lower(ls_source),lower(as_oldtag),1)<br />&nbsp;LOOP<br />elseif al_seq &gt; 0 then<br />&nbsp;DO WHILE ll_start_pos &gt; 0<br />&nbsp;&nbsp;i ++<br />&nbsp;&nbsp;if al_seq = i then <br />&nbsp;&nbsp;&nbsp;ls_left = leftw(ls_source,ll_start_pos - 1) + as_newtag<br />&nbsp;&nbsp;&nbsp;ls_return = ls_return + ls_left<br />&nbsp;&nbsp;&nbsp;ls_source = midw(ls_source,ll_start_pos + lenw(as_oldtag),lenw(ls_source))<br />&nbsp;&nbsp;&nbsp;ll_start_pos = posw(lower(ls_source),lower(as_oldtag),1)<br />&nbsp;&nbsp;end if<br />&nbsp;loop<br />end if<br />ls_return = ls_return + ls_source</div>
<div style="MARGIN-LEFT: 21pt">return ls_return</div>
<div style="MARGIN-LEFT: 21pt">end function</div>
<div style="MARGIN-LEFT: 21pt">五.nvo_pbcompiler</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$nvo_pbcompiler.sru<br />$PBExportComments$PB动态脚本解释器</div>
<div style="MARGIN-LEFT: 21pt">forward<br />global type nvo_pbcompiler from nonvisualobject<br />end type<br />end forward</div>
<div style="MARGIN-LEFT: 21pt">global type nvo_pbcompiler from nonvisualobject<br />end type<br />global nvo_pbcompiler nvo_pbcompiler</div>
<div style="MARGIN-LEFT: 21pt">type prototypes<br />//打开一个会话<br />Function long SessionOpen () Library &quot;PBORC90.DLL&quot; Alias for &quot;PBORCA_SessionOpen&quot;<br />//关闭一个会话<br />Subroutine SessionClose ( long hORCASession ) Library &quot;PBORC90.DLL&quot; Alias for &quot;PBORCA_SessionClose&quot;<br />//设置当前会话的库清单<br />Function int SessionSetLibraryList ( long hORCASession, ref string pLibNames[], int iNumberOfLibs) Library &quot;PBORC90.DLL&quot; Alias for &quot;PBORCA_SessionSetLibraryList&quot;<br />//设置当前会话对应的应用<br />Function int SessionSetCurrentAppl ( long hORCASession, string lpszApplLibName, string lpszApplName ) Library &quot;PBORC90.DLL&quot; Alias for &quot;PBORCA_SessionSetCurrentAppl&quot;<br />//导入并编译实体<br />Function int CompileEntryImport ( long hORCASession, string lpszLibraryName, string lpszEntryName, long otEntryType, string lpszComments, string lpszEntrySyntax, long lEntrySyntaxBuffSize, long pCompErrorProc, long pUserData ) Library &quot;PBORC90.DLL&quot; Alias for &quot;PBORCA_CompileEntryImport&quot;<br />//取临时目录<br />Function long GetTempPath(long nBufferLength, ref string lpBuffer)&nbsp; Library &quot;kernel32&quot; Alias for &quot;GetTempPathA&quot; <br />//获取一个已装载模板的完整路径名称<br />FUNCTION ulong GetModuleFileName(ulong hModule,ref string lpFileName,ulong nSize) LIBRARY &quot;kernel32.dll&quot; ALIAS FOR &quot;GetModuleFileNameA&quot;</div>
<div style="MARGIN-LEFT: 21pt">end prototypes</div>
<div style="MARGIN-LEFT: 21pt">type variables</div>
<div style="MARGIN-LEFT: 21pt">end variables<br />forward prototypes<br />public function string of_gettemppath ()<br />public function string of_getapppath ()<br />public function integer of_createentry (string as_returntype, string as_pbscript, ref string as_libraryname, ref string as_entryname)<br />end prototypes</div>
<div style="MARGIN-LEFT: 21pt">public function string of_gettemppath ();/*******************************************************************<br />函数名称：of_gettemppath()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; 无<br />返回值：&nbsp; string 临时路径<br />功能描述：取临时路径<br />创建人：&nbsp; 康剑民<br />创建日期：2006-12-26<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />string ls_path<br />ulong lu_size=256</div>
<div style="MARGIN-LEFT: 21pt">ls_path=space(256)<br />GetTempPath(lu_size,ls_path)<br />return trimw(ls_path)<br />end function</div>
<div style="MARGIN-LEFT: 21pt">public function string of_getapppath ();/*******************************************************************<br />函数名称：of_getapppath()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; 无<br />返回值：&nbsp; string 应用程序路径<br />功能描述：取应用程序路径<br />创建人：&nbsp; 康剑民<br />创建日期：2002-11-22<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />string ls_apppath</div>
<div style="MARGIN-LEFT: 21pt">ls_apppath=space(256)<br />GetModuleFileName(Handle(GetApplication()),ls_apppath,256)<br />ls_apppath=Reverse(ls_apppath)<br />ls_apppath=Reverse(midw(ls_apppath,posw(ls_apppath,'\',1)))</div>
<div style="MARGIN-LEFT: 21pt">return ls_apppath<br />end function</div>
<div style="MARGIN-LEFT: 21pt">public function integer of_createentry (string as_returntype, string as_pbscript, ref string as_libraryname, ref string as_entryname);/*******************************************************************<br />函数名称：of_createentry()<br />参数:&nbsp;&nbsp;&nbsp;&nbsp; as_returntype string 返回值类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; as_pbscript string 动态代码<br />&nbsp;&nbsp;&nbsp; as_libraryname ref string 创建的库文件名称<br />&nbsp;&nbsp;&nbsp; as_entryname ref string 创建的实体名称<br />返回值：&nbsp; long 是否成功(1表示成功,-1表示失败)<br />功能描述：根据动态代码创建实体<br />创建人：&nbsp; 康剑民<br />创建日期：2007-02-12<br />版本号：&nbsp; V1.0<br />*******************************************************************/<br />long ll_sid//会话编号<br />long ll_index//对象序号<br />string ls_librarylist[]//库文件列表<br />string ls_librarylist_tmp[]//库文件列表(临时)<br />string ls_temp_libraryname//临时库文件名称<br />string ls_temp_path//临时目录<br />string ls_syntax//实体语法<br />string ls_app_libraryname//应用程序所在库文件名称<br />integer li_result//结果<br />string ls_entryname//对象名称<br />classdefinition lcd_app//应用程序类定义对象<br />string ls_librarylist_files//库文件<br />integer i,j//临时变量</div>
<div style="MARGIN-LEFT: 21pt">//开发环境下直接退出<br />if handle(GetApplication()) &lt;= 0 then return -1<br />//取库文件列表<br />ls_librarylist_files = getlibrarylist ()<br />//取应用对象所在pbl<br />lcd_app = getapplication().classdefinition<br />ls_app_libraryname = lcd_app.libraryname</div>
<div style="MARGIN-LEFT: 21pt">ls_temp_path = this.of_gettemppath( )//取临时目录<br />//取待创建的临时库文件名称<br />ll_index = 1<br />ls_temp_libraryname = ls_temp_path + &quot;temp&quot;+string(ll_index) + &quot;.pbl&quot;<br />do while fileexists(ls_temp_libraryname) or posw(&quot;,&quot;+ls_librarylist_files+&quot;,&quot;,&quot;,&quot;+ls_temp_libraryname+&quot;,&quot;) &gt; 0<br />&nbsp;ll_index ++<br />&nbsp;ls_temp_libraryname = ls_temp_path + &quot;temp&quot;+string(ll_index) + &quot;.pbl&quot;<br />loop<br />//创建临时库文件<br />LibraryCreate(ls_temp_libraryname,&quot;临时库文件&quot;)</div>
<div style="MARGIN-LEFT: 21pt">f_parse(ls_librarylist_files,',',ls_librarylist)//分解字符串到数组<br />//判断库文件是否存在并形成新列表<br />j = 0<br />for i = 1 to upperbound(ls_librarylist)<br />&nbsp;if fileexists(ls_librarylist[i]) then<br />&nbsp;&nbsp;j ++<br />&nbsp;&nbsp;ls_librarylist_tmp[j] = ls_librarylist[i]<br />&nbsp;end if<br />next<br />ls_librarylist = ls_librarylist_tmp<br />ls_librarylist[upperbound(ls_librarylist)+1] = ls_temp_libraryname</div>
<div style="MARGIN-LEFT: 21pt">ll_sid = SessionOpen()//打开一个会话<br />//设置当前会话的库清单<br />li_result = SessionSetLibraryList (ll_sid, ls_librarylist, upperbound(ls_librarylist))<br />if li_result = 0 then&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;//设置当前会话对应的应用<br />&nbsp;li_result = SessionSetCurrentAppl (ll_sid, ls_app_libraryname, getapplication().appname )<br />&nbsp;&nbsp; if li_result = 0 then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;//取实体名称(保证不重复)<br />&nbsp;&nbsp;ll_index = 1<br />&nbsp;&nbsp;do while not isnull(FindClassDefinition(&quot;nvo_&quot;+string(ll_index)))<br />&nbsp;&nbsp;&nbsp;ll_index ++<br />&nbsp;&nbsp;loop<br />&nbsp;&nbsp;ls_entryname = &quot;nvo_&quot;+string(ll_index)<br />&nbsp;&nbsp;//实体声明<br />&nbsp;&nbsp;ls_syntax = &quot;$PBExportHeader$&quot;+ls_entryname+&quot;.sru&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;forward&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;global type &quot;+ls_entryname+&quot; from nonvisualobject&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end type&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end forward&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;global type &quot;+ls_entryname+&quot; from nonvisualobject&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end type&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;global &quot;+ls_entryname+&quot; &quot;+ls_entryname+&quot;&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;~r~n&quot;&amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;forward prototypes&quot;+&quot;~r~n&quot;&nbsp;<br />&nbsp;&nbsp;//区分函数还是过程<br />&nbsp;&nbsp;if trimw(lower(as_returntype)) = 'none' or trimw(lower(as_returntype)) = '' then<br />&nbsp;&nbsp;&nbsp;ls_syntax = ls_syntax + &quot;public subroutine of_exec ()&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end prototypes&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;public subroutine of_exec ();&quot;+as_pbscript+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end subroutine&quot;<br />&nbsp;&nbsp;else<br />&nbsp;&nbsp;&nbsp;ls_syntax = ls_syntax + &quot;public function &quot; + as_returntype + &quot; of_exec ()&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end prototypes&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;public function &quot; + as_returntype + &quot; of_exec ();&quot;+as_pbscript+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;+ &quot;end function&quot;<br />&nbsp;&nbsp;end if<br />&nbsp;&nbsp;//实体语法尾部<br />&nbsp;&nbsp;ls_syntax = ls_syntax + &quot;~r~n&quot; + &quot;on &quot; + ls_entryname + &quot;.create&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;call super::create&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;TriggerEvent( this, ~&quot;constructor~&quot; )&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;end on&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;on &quot; + ls_entryname + &quot;.destroy&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;TriggerEvent( this, ~&quot;destructor~&quot; )&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;call super::destroy&quot;+&quot;~r~n&quot;&amp;<br />&nbsp;&nbsp;&nbsp;+ &quot;end on&quot;<br />&nbsp;&nbsp;//导入并编译实体<br />&nbsp;&nbsp;li_result = CompileEntryImport (ll_sid, ls_temp_libraryname, ls_entryname, 6 , &quot;comment - new object&quot;, ls_syntax, len(ls_syntax), 0, 0 )<br />&nbsp;&nbsp; end if<br />end if<br />SessionClose(ll_sid)//关闭一个会话</div>
<div style="MARGIN-LEFT: 21pt">as_libraryname = ls_temp_libraryname<br />as_entryname=ls_entryname</div>
<div style="MARGIN-LEFT: 21pt">//加入新文件到库文件搜索列表<br />AddToLibraryList(ls_temp_libraryname)</div>
<div style="MARGIN-LEFT: 21pt">if li_result = 0 then<br />&nbsp;return 1<br />else<br />&nbsp;return -1<br />end if<br />end function</div>
<div style="MARGIN-LEFT: 21pt">on nvo_pbcompiler.create<br />call super::create<br />TriggerEvent( this, &quot;constructor&quot; )<br />end on</div>
<div style="MARGIN-LEFT: 21pt">on nvo_pbcompiler.destroy<br />TriggerEvent( this, &quot;destructor&quot; )<br />call super::destroy<br />end on</div>
<div style="MARGIN-LEFT: 21pt">六.w_pbcompiler_test</div>
<div style="MARGIN-LEFT: 21pt">$PBExportHeader$w_pbcompiler_test.srw<br />$PBExportComments$PB动态脚本解释器测试窗口</div>
<div style="MARGIN-LEFT: 21pt">forward<br />global type w_pbcompiler_test from window<br />end type<br />type st_returnvalue from statictext within w_pbcompiler_test<br />end type<br />type st_returntype from statictext within w_pbcompiler_test<br />end type<br />type st_script from statictext within w_pbcompiler_test<br />end type<br />type sle_returnvalue from singlelineedit within w_pbcompiler_test<br />end type<br />type cb_exit from commandbutton within w_pbcompiler_test<br />end type<br />type sle_returntype from singlelineedit within w_pbcompiler_test<br />end type<br />type mle_script from multilineedit within w_pbcompiler_test<br />end type<br />type cb_ok from commandbutton within w_pbcompiler_test<br />end type<br />end forward</div>
<div style="MARGIN-LEFT: 21pt">global type w_pbcompiler_test from window<br />integer width = 1979<br />integer height = 1100<br />boolean titlebar = true<br />string title = &quot;PB脚本解释器(测试)&quot;<br />boolean controlmenu = true<br />boolean minbox = true<br />boolean maxbox = true<br />boolean resizable = true<br />long backcolor = 67108864<br />string icon = &quot;AppIcon!&quot;<br />boolean center = true<br />st_returnvalue st_returnvalue<br />st_returntype st_returntype<br />st_script st_script<br />sle_returnvalue sle_returnvalue<br />cb_exit cb_exit<br />sle_returntype sle_returntype<br />mle_script mle_script<br />cb_ok cb_ok<br />end type<br />global w_pbcompiler_test w_pbcompiler_test</div>
<div style="MARGIN-LEFT: 21pt">type prototypes</div>
<div style="MARGIN-LEFT: 21pt">end prototypes<br />type variables</div>
<div style="MARGIN-LEFT: 21pt">end variables<br />on w_pbcompiler_test.create<br />this.st_returnvalue=create st_returnvalue<br />this.st_returntype=create st_returntype<br />this.st_script=create st_script<br />this.sle_returnvalue=create sle_returnvalue<br />this.cb_exit=create cb_exit<br />this.sle_returntype=create sle_returntype<br />this.mle_script=create mle_script<br />this.cb_ok=create cb_ok<br />this.Control[]={this.st_returnvalue,&amp;<br />this.st_returntype,&amp;<br />this.st_script,&amp;<br />this.sle_returnvalue,&amp;<br />this.cb_exit,&amp;<br />this.sle_returntype,&amp;<br />this.mle_script,&amp;<br />this.cb_ok}<br />end on</div>
<div style="MARGIN-LEFT: 21pt">on w_pbcompiler_test.destroy<br />destroy(this.st_returnvalue)<br />destroy(this.st_returntype)<br />destroy(this.st_script)<br />destroy(this.sle_returnvalue)<br />destroy(this.cb_exit)<br />destroy(this.sle_returntype)<br />destroy(this.mle_script)<br />destroy(this.cb_ok)<br />end on</div>
<div style="MARGIN-LEFT: 21pt">type st_returnvalue from statictext within w_pbcompiler_test<br />integer x = 9<br />integer y = 608<br />integer width = 297<br />integer height = 60<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />long backcolor = 67108864<br />string text = &quot;返回值:&quot;<br />boolean focusrectangle = false<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type st_returntype from statictext within w_pbcompiler_test<br />integer x = 9<br />integer y = 476<br />integer width = 297<br />integer height = 60<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />long backcolor = 67108864<br />string text = &quot;返回值类型:&quot;<br />boolean focusrectangle = false<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type st_script from statictext within w_pbcompiler_test<br />integer x = 9<br />integer y = 12<br />integer width = 206<br />integer height = 60<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />long backcolor = 67108864<br />string text = &quot;PB脚本:&quot;<br />boolean focusrectangle = false<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type sle_returnvalue from singlelineedit within w_pbcompiler_test<br />integer x = 334<br />integer y = 608<br />integer width = 1582<br />integer height = 104<br />integer taborder = 30<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />borderstyle borderstyle = stylelowered!<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type cb_exit from commandbutton within w_pbcompiler_test<br />integer x = 1664<br />integer y = 856<br />integer width = 242<br />integer height = 104<br />integer taborder = 50<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />string text = &quot;退出&quot;<br />end type</div>
<div style="MARGIN-LEFT: 21pt">event clicked;close(parent)<br />end event</div>
<div style="MARGIN-LEFT: 21pt">type sle_returntype from singlelineedit within w_pbcompiler_test<br />integer x = 334<br />integer y = 476<br />integer width = 1582<br />integer height = 104<br />integer taborder = 20<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />borderstyle borderstyle = stylelowered!<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type mle_script from multilineedit within w_pbcompiler_test<br />integer x = 334<br />integer y = 12<br />integer width = 1582<br />integer height = 432<br />integer taborder = 10<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />long textcolor = 33554432<br />boolean vscrollbar = true<br />boolean autovscroll = true<br />borderstyle borderstyle = stylelowered!<br />end type</div>
<div style="MARGIN-LEFT: 21pt">type cb_ok from commandbutton within w_pbcompiler_test<br />integer x = 1417<br />integer y = 856<br />integer width = 242<br />integer height = 104<br />integer taborder = 40<br />integer textsize = -9<br />integer weight = 400<br />fontcharset fontcharset = ansi!<br />fontpitch fontpitch = variable!<br />fontfamily fontfamily = swiss!<br />string facename = &quot;Arial&quot;<br />string text = &quot;执行&quot;<br />end type</div>
<div style="MARGIN-LEFT: 21pt">event clicked;sle_returnvalue.text = f_execpbscript(sle_returntype.text,mle_script.text)<br />end event</div>
<div style="MARGIN-LEFT: 21pt"><br /><br />转载自：<a href="http://blog.csdn.net/pbdesigner/archive/2007/03/31/1547706.aspx" target="_blank">http://blog.csdn.net/pbdesigner/archive/2007/03/31/1547706.aspx</a></div></div></div>]]></description>
		</item>
		    
		
		<item>
			<title>pborcl研究2</title>
			<link>http://itmed.blog.sohu.com/93680052.html</link>
			<comments>http://itmed.blog.sohu.com/93680052.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 4 Jul 2008 16:46:47 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/93680052.html</guid>
			<description><![CDATA[自动生成pbr文件的东东，思路如下 &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 1.用GetLibraryList() 得到WorkSpace中所有PBL列表，并进行分解 &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 2.创建数据窗口，用dw_1.ImportString(LibraryDirectoryEx(pbl, &nbsp; DirAll!))将用某PBL中所有对象名导入到dw_1 &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 3.作出类型判断： &nbsp; <br />&nbsp; choose &nbsp; case &nbsp; dw_1.GetItemString(j, &nbsp; &quot;type&quot;) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Application&quot;; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportApplication!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;DataWindow&quot;; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportDataWindow!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Function&quot;; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportFunction!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Menu&quot;; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; &nbsp; ExportMenu!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Pipeline&quot;; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportPipeline!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Project&quot;; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportProject!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Query&quot;; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportQuery!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Structure&quot;; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportStructure!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;UserObject&quot;; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportUserObject!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; &quot;Window&quot;; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; syntax &nbsp; = &nbsp; LibraryExport(pbl, &nbsp; name, &nbsp; ExportWindow!) &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case &nbsp; else &nbsp; <br />&nbsp; end &nbsp; choose &nbsp; <br />&nbsp; &nbsp; <br />&nbsp; 4.具体对象的相关信息，保存在syntax变量中。]]></description>
		</item>
		    
		
		<item>
			<title>pborcl资料</title>
			<link>http://itmed.blog.sohu.com/93679963.html</link>
			<comments>http://itmed.blog.sohu.com/93679963.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 4 Jul 2008 16:45:39 +0800</pubDate>
			<category>pb研究</category>
			<guid>http://itmed.blog.sohu.com/93679963.html</guid>
			<description><![CDATA[<p>你希望实现的功能需要使用PowerBuilder提供的ORCA接口来完成，在http://manuals.sybase.com/onlinebooks/group-pb/adt0650e/orca/@Generic__BookView;lang=zh有ORCA的详细资料，我也有一个别人用ORCA接口做管理PBL的例子的PB源码，如果你需要请来信：marsor@263.net<a href="http://topic.csdn.net/t/20041206/11/3618373.html#">Top</a></p>
<h3><strong><a name="r_26270193">20 楼</a>marsor（阿东）</strong><span>回复于 2004-12-08 10:38:20 得分 0 </span></h3>
<p>//以下是PBORCA中的部分常用函数声明，全部函数请参考Sybase网站 &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：启动连接回话 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function &nbsp; Ulong PBORCA_SessionOpen() &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：关闭连接会话 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Ulong PBORCA_SessionClose(Ulong &nbsp; hSession) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：创建库文件 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryCreate(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszLibComments) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：删除库文件 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryDelete(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszLibName) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：设置应用库列表 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function &nbsp; Int PBORCA_SessionSetLibraryList(Ulong &nbsp; hSession, &nbsp; String &nbsp; pLIbnames[], &nbsp; &amp; &nbsp; <br />&nbsp; int &nbsp; nNoOfLibs) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：设置当前应用，此函数在setlibrarylist函数之后，而在任何编译和查询之 &nbsp; <br />&nbsp; * &nbsp; 前调用 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_SessionSetCurrentAppl(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszApplLibName,&amp; &nbsp; <br />&nbsp; String &nbsp; lpszApplName) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *?用途：浏览库目录，查看全部内容 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryDirectory(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszLibName,&amp; &nbsp; <br />&nbsp; String &nbsp; lpszLibComments, &nbsp; int &nbsp; nBufferSize, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; pListProc, &nbsp; String &nbsp; pUserData) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：导入对象 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_CompileEntryImport(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszLibname, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszEntryName, &nbsp; Ulong &nbsp; otEntryType, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszComments, &nbsp; String &nbsp; lpszEntrySyntax, &nbsp; &amp; &nbsp; <br />&nbsp; long &nbsp; lBufferSize, &nbsp; string &nbsp; pCompErrorProc, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; pUserData) &nbsp; Library &nbsp; &quot;pborc80.dll&quot; &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：导出对象 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryEntryExport(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszEntryName, &nbsp; Ulong &nbsp; otEntryType, &nbsp; &amp; &nbsp; <br />&nbsp; ref &nbsp; String &nbsp; lpszExportBuffer, &nbsp; long &nbsp; lExportBufferSize)&amp; &nbsp; <br />&nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：库间拷贝对象 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function &nbsp; Int PBORCA_LibraryEntryCopy(ULong &nbsp; hSession, &nbsp; String &nbsp; lpszSourceLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpsDestLibName, &nbsp; String &nbsp; lpszEntryName, &nbsp; &amp; &nbsp; <br />&nbsp; Ulong &nbsp; otEntryType) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：库间拷贝移动 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryEntryMove(ULong &nbsp; hSession, &nbsp; String &nbsp; lpszSourceLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpsDestLibName, &nbsp; String &nbsp; lpszEntryName, &nbsp; &amp; &nbsp; <br />&nbsp; Ulong &nbsp; otEntryType) &nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：删除库对象 &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_LibraryEntryDelete(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszSourceLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszEntryName, &nbsp; Ulong &nbsp; otEntryType) &nbsp; &amp; &nbsp; <br />&nbsp; Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：Check-Out &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_CheckOutEntry(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszEntryName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszSourceLibName, &nbsp; String &nbsp; lpszDestLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszUserID, &nbsp; Ulong &nbsp; otEntryType, &nbsp; &amp; &nbsp; <br />&nbsp; Int &nbsp; bMakeCopy) Library &nbsp; 'pborc80.dll' &nbsp; <br />&nbsp; /************************************************************************ &nbsp; <br />&nbsp; *用途：Check-In &nbsp; <br />&nbsp; ************************************************************************/ &nbsp; <br />&nbsp; Function Int PBORCA_CheckInEntry(Ulong &nbsp; hSession, &nbsp; String &nbsp; lpszEntryName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszSourceLibName, &nbsp; String &nbsp; lpszDestLibName, &nbsp; &amp; &nbsp; <br />&nbsp; String &nbsp; lpszUserID, &nbsp; Ulong &nbsp; otEntryType, &nbsp; &amp; &nbsp; <br />&nbsp; Int &nbsp; bMoveEntry) Library &nbsp; 'pborc80.dll'</p>]]></description>
		</item>
		    
		
		<item>
			<title>teb,peb研究</title>
			<link>http://itmed.blog.sohu.com/91030887.html</link>
			<comments>http://itmed.blog.sohu.com/91030887.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Wed, 25 Jun 2008 08:58:56 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/91030887.html</guid>
			<description><![CDATA[<p>0:000&gt; dt ntdll!_ldr_data_table_entry<br />ntdll!_LDR_DATA_TABLE_ENTRY<br />&nbsp;&nbsp; +0x000 InLoadOrderLinks : _LIST_ENTRY<br />&nbsp;&nbsp; +0x008 InMemoryOrderLinks : _LIST_ENTRY<br />&nbsp;&nbsp; +0x010 InInitializationOrderLinks : _LIST_ENTRY<br />&nbsp;&nbsp; +0x018 DllBase&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x01c EntryPoint&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x020 SizeOfImage&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x024 FullDllName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _UNICODE_STRING<br />&nbsp;&nbsp; +0x02c BaseDllName&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _UNICODE_STRING<br />&nbsp;&nbsp; +0x034 Flags&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x038 LoadCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint2B<br />&nbsp;&nbsp; +0x03a TlsIndex&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint2B<br />&nbsp;&nbsp; +0x03c HashLinks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _LIST_ENTRY<br />&nbsp;&nbsp; +0x03c SectionPointer&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x040 CheckSum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x044 TimeDateStamp&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x044 LoadedImports&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x048 EntryPointActivationContext : Ptr32 Void<br />&nbsp;&nbsp; +0x04c PatchInformation : Ptr32 Void<br /></p>
<p>0:000&gt; dt ntdll!_peb<br />ntdll!_PEB<br />&nbsp;&nbsp; +0x000 InheritedAddressSpace : UChar<br />&nbsp;&nbsp; +0x001 ReadImageFileExecOptions : UChar<br />&nbsp;&nbsp; +0x002 BeingDebugged&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0x003 SpareBool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0x004 Mutant&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x008 ImageBaseAddress : Ptr32 Void<br />&nbsp;&nbsp; +0x00c Ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _PEB_LDR_DATA<br />&nbsp;&nbsp; +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS<br />&nbsp;&nbsp; +0x014 SubSystemData&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x018 ProcessHeap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x01c FastPebLock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _RTL_CRITICAL_SECTION<br />&nbsp;&nbsp; +0x020 FastPebLockRoutine : Ptr32 Void<br />&nbsp;&nbsp; +0x024 FastPebUnlockRoutine : Ptr32 Void<br />&nbsp;&nbsp; +0x028 EnvironmentUpdateCount : Uint4B<br />&nbsp;&nbsp; +0x02c KernelCallbackTable : Ptr32 Void<br />&nbsp;&nbsp; +0x030 SystemReserved&nbsp;&nbsp; : [1] Uint4B<br />&nbsp;&nbsp; +0x034 AtlThunkSListPtr32 : Uint4B<br />&nbsp;&nbsp; +0x038 FreeList&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _PEB_FREE_BLOCK<br />&nbsp;&nbsp; +0x03c TlsExpansionCounter : Uint4B<br />&nbsp;&nbsp; +0x040 TlsBitmap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x044 TlsBitmapBits&nbsp;&nbsp;&nbsp; : [2] Uint4B<br />&nbsp;&nbsp; +0x04c ReadOnlySharedMemoryBase : Ptr32 Void<br />&nbsp;&nbsp; +0x050 ReadOnlySharedMemoryHeap : Ptr32 Void<br />&nbsp;&nbsp; +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void<br />&nbsp;&nbsp; +0x058 AnsiCodePageData : Ptr32 Void<br />&nbsp;&nbsp; +0x05c OemCodePageData&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x060 UnicodeCaseTableData : Ptr32 Void<br />&nbsp;&nbsp; +0x064 NumberOfProcessors : Uint4B<br />&nbsp;&nbsp; +0x068 NtGlobalFlag&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x070 CriticalSectionTimeout : _LARGE_INTEGER<br />&nbsp;&nbsp; +0x078 HeapSegmentReserve : Uint4B<br />&nbsp;&nbsp; +0x07c HeapSegmentCommit : Uint4B<br />&nbsp;&nbsp; +0x080 HeapDeCommitTotalFreeThreshold : Uint4B<br />&nbsp;&nbsp; +0x084 HeapDeCommitFreeBlockThreshold : Uint4B<br />&nbsp;&nbsp; +0x088 NumberOfHeaps&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x08c MaximumNumberOfHeaps : Uint4B<br />&nbsp;&nbsp; +0x090 ProcessHeaps&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Ptr32 Void<br />&nbsp;&nbsp; +0x094 GdiSharedHandleTable : Ptr32 Void<br />&nbsp;&nbsp; +0x098 ProcessStarterHelper : Ptr32 Void<br />&nbsp;&nbsp; +0x09c GdiDCAttributeList : Uint4B<br />&nbsp;&nbsp; +0x0a0 LoaderLock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x0a4 OSMajorVersion&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x0a8 OSMinorVersion&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x0ac OSBuildNumber&nbsp;&nbsp;&nbsp; : Uint2B<br />&nbsp;&nbsp; +0x0ae OSCSDVersion&nbsp;&nbsp;&nbsp;&nbsp; : Uint2B<br />&nbsp;&nbsp; +0x0b0 OSPlatformId&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x0b4 ImageSubsystem&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x0b8 ImageSubsystemMajorVersion : Uint4B<br />&nbsp;&nbsp; +0x0bc ImageSubsystemMinorVersion : Uint4B<br />&nbsp;&nbsp; +0x0c0 ImageProcessAffinityMask : Uint4B<br />&nbsp;&nbsp; +0x0c4 GdiHandleBuffer&nbsp; : [34] Uint4B<br />&nbsp;&nbsp; +0x14c PostProcessInitRoutine : Ptr32&nbsp;&nbsp;&nbsp;&nbsp; void <br />&nbsp;&nbsp; +0x150 TlsExpansionBitmap : Ptr32 Void<br />&nbsp;&nbsp; +0x154 TlsExpansionBitmapBits : [32] Uint4B<br />&nbsp;&nbsp; +0x1d4 SessionId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x1d8 AppCompatFlags&nbsp;&nbsp; : _ULARGE_INTEGER<br />&nbsp;&nbsp; +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER<br />&nbsp;&nbsp; +0x1e8 pShimData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x1ec AppCompatInfo&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x1f0 CSDVersion&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _UNICODE_STRING<br />&nbsp;&nbsp; +0x1f8 ActivationContextData : Ptr32 Void<br />&nbsp;&nbsp; +0x1fc ProcessAssemblyStorageMap : Ptr32 Void<br />&nbsp;&nbsp; +0x200 SystemDefaultActivationContextData : Ptr32 Void<br />&nbsp;&nbsp; +0x204 SystemAssemblyStorageMap : Ptr32 Void<br />&nbsp;&nbsp; +0x208 MinimumStackCommit : Uint4B<br /></p>
<p>0:000&gt; dt ntdll!_teb<br />ntdll!_TEB<br />&nbsp;&nbsp; +0x000 NtTib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _NT_TIB<br />&nbsp;&nbsp; +0x01c EnvironmentPointer : Ptr32 Void<br />&nbsp;&nbsp; +0x020 ClientId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _CLIENT_ID<br />&nbsp;&nbsp; +0x028 ActiveRpcHandle&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x02c ThreadLocalStoragePointer : Ptr32 Void<br />&nbsp;&nbsp; +0x030 ProcessEnvironmentBlock : Ptr32 _PEB<br />&nbsp;&nbsp; +0x034 LastErrorValue&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x038 CountOfOwnedCriticalSections : Uint4B<br />&nbsp;&nbsp; +0x03c CsrClientThread&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x040 Win32ThreadInfo&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x044 User32Reserved&nbsp;&nbsp; : [26] Uint4B<br />&nbsp;&nbsp; +0x0ac UserReserved&nbsp;&nbsp;&nbsp;&nbsp; : [5] Uint4B<br />&nbsp;&nbsp; +0x0c0 WOW32Reserved&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x0c4 CurrentLocale&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x0c8 FpSoftwareStatusRegister : Uint4B<br />&nbsp;&nbsp; +0x0cc SystemReserved1&nbsp; : [54] Ptr32 Void<br />&nbsp;&nbsp; +0x1a4 ExceptionCode&nbsp;&nbsp;&nbsp; : Int4B<br />&nbsp;&nbsp; +0x1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK<br />&nbsp;&nbsp; +0x1bc SpareBytes1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : [24] UChar<br />&nbsp;&nbsp; +0x1d4 GdiTebBatch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _GDI_TEB_BATCH<br />&nbsp;&nbsp; +0x6b4 RealClientId&nbsp;&nbsp;&nbsp;&nbsp; : _CLIENT_ID<br />&nbsp;&nbsp; +0x6bc GdiCachedProcessHandle : Ptr32 Void<br />&nbsp;&nbsp; +0x6c0 GdiClientPID&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x6c4 GdiClientTID&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x6c8 GdiThreadLocalInfo : Ptr32 Void<br />&nbsp;&nbsp; +0x6cc Win32ClientInfo&nbsp; : [62] Uint4B<br />&nbsp;&nbsp; +0x7c4 glDispatchTable&nbsp; : [233] Ptr32 Void<br />&nbsp;&nbsp; +0xb68 glReserved1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : [29] Uint4B<br />&nbsp;&nbsp; +0xbdc glReserved2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbe0 glSectionInfo&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbe4 glSection&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbe8 glTable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbec glCurrentRC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbf0 glContext&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xbf4 LastStatusValue&nbsp; : Uint4B<br />&nbsp;&nbsp; +0xbf8 StaticUnicodeString : _UNICODE_STRING<br />&nbsp;&nbsp; +0xc00 StaticUnicodeBuffer : [261] Uint2B<br />&nbsp;&nbsp; +0xe0c DeallocationStack : Ptr32 Void<br />&nbsp;&nbsp; +0xe10 TlsSlots&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : [64] Ptr32 Void<br />&nbsp;&nbsp; +0xf10 TlsLinks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _LIST_ENTRY<br />&nbsp;&nbsp; +0xf18 Vdm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xf1c ReservedForNtRpc : Ptr32 Void<br />&nbsp;&nbsp; +0xf20 DbgSsReserved&nbsp;&nbsp;&nbsp; : [2] Ptr32 Void<br />&nbsp;&nbsp; +0xf28 HardErrorsAreDisabled : Uint4B<br />&nbsp;&nbsp; +0xf2c Instrumentation&nbsp; : [16] Ptr32 Void<br />&nbsp;&nbsp; +0xf6c WinSockData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xf70 GdiBatchCount&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0xf74 InDbgPrint&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0xf75 FreeStackOnTermination : UChar<br />&nbsp;&nbsp; +0xf76 HasFiberData&nbsp;&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0xf77 IdealProcessor&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0xf78 Spare3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0xf7c ReservedForPerf&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xf80 ReservedForOle&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xf84 WaitingOnLoaderLock : Uint4B<br />&nbsp;&nbsp; +0xf88 Wx86Thread&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _Wx86ThreadState<br />&nbsp;&nbsp; +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void<br />&nbsp;&nbsp; +0xf98 ImpersonationLocale : Uint4B<br />&nbsp;&nbsp; +0xf9c IsImpersonating&nbsp; : Uint4B<br />&nbsp;&nbsp; +0xfa0 NlsCache&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xfa4 pShimData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0xfa8 HeapVirtualAffinity : Uint4B<br />&nbsp;&nbsp; +0xfac CurrentTransactionHandle : Ptr32 Void<br />&nbsp;&nbsp; +0xfb0 ActiveFrame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _TEB_ACTIVE_FRAME<br />&nbsp;&nbsp; +0xfb4 SafeThunkCall&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0xfb5 BooleanSpare&nbsp;&nbsp;&nbsp;&nbsp; : [3] UChar<br /></p>
<p>0:000&gt; dt ntdll!_peb_ldr_data<br />ntdll!_PEB_LDR_DATA<br />&nbsp;&nbsp; +0x000 Length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x004 Initialized&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : UChar<br />&nbsp;&nbsp; +0x008 SsHandle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 Void<br />&nbsp;&nbsp; +0x00c InLoadOrderModuleList : _LIST_ENTRY<br />&nbsp;&nbsp; +0x014 InMemoryOrderModuleList : _LIST_ENTRY<br />&nbsp;&nbsp; +0x01c InInitializationOrderModuleList : _LIST_ENTRY<br />&nbsp;&nbsp; +0x024 EntryInProgress&nbsp; : Ptr32 Void</p>
<p><br />0:000&gt; dt _LIST_ENTRY<br />ntdll!_LIST_ENTRY<br />&nbsp;&nbsp; +0x000 Flink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _LIST_ENTRY<br />&nbsp;&nbsp; +0x004 Blink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 _LIST_ENTRY<br /></p>
<p>&nbsp;PEB.Ldr&nbsp;指向&nbsp;PEB_LDR_DATA&nbsp;，PEB_LDR_DATA.InLoadOrderModuleList.Flink&nbsp;就指向我们关心的&nbsp;LDR_DATA_TABLE_ENTRY&nbsp;表。<br /></p>]]></description>
		</item>
		    
		
		<item>
			<title>☆ 通过TEB/PEB枚举当前进程空间中用户模块列表</title>
			<link>http://itmed.blog.sohu.com/90954280.html</link>
			<comments>http://itmed.blog.sohu.com/90954280.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Tue, 24 Jun 2008 11:56:41 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/90954280.html</guid>
			<description><![CDATA[<p><strong>☆ 通过TEB/PEB枚举当前进程空间中用户模块列表<br /><br /></strong>作者：scz &lt;scz@nsfocus.com&gt;<br />主页：<a href="http://www.nsfocus.net">http://www.nsfocus.net</a></p>
<p>来源:http://blog.csdn.net/anui/archive/2006/03/25/638417.aspx<br /><br />这只是我一篇巨长无比的笔记中的一小节，因此只列了本节所引参考资源，可我还是<br />很乐意向大家推荐[8]、[10]。如果对你有用，是否也可以给我订份小礼物，呵，小<br />玩笑啦。<br /><br />☆ 通过TEB/PEB枚举当前进程空间中用户模块列表<br /><br />实在没精力找出最早介绍该项技术的文章，尽管很想知道答案。29A杂志中大量使用<br />该技术([8])，并辅以文字说明，推荐阅读。下面操作是在windbg中进行的，提前在<br />注册表中设置好AeDebug，执行vulnerable_0.exe，进入windbg调试状态。也可通过<br />其它办法进入windbg调试状态。<br /><br />段选择子FS所对应的段即当前线程TEB(Thread Environment Block)，即FS:0指向TEB。<br /><br />&gt; dg @fs<br />Selector&nbsp;&nbsp; Base&nbsp;&nbsp;&nbsp;&nbsp; Limit&nbsp;&nbsp;&nbsp;&nbsp; Type&nbsp;&nbsp;&nbsp;&nbsp;DPL&nbsp;&nbsp; Size&nbsp;&nbsp;Gran Pres<br />-------- -------- -------- ---------- --- ------- ---- ----<br />&nbsp;&nbsp;0038&nbsp;&nbsp; 7ffde000 00000fff Data RW Ac&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;Big&nbsp;&nbsp; Byte&nbsp;&nbsp;P<br />&gt; r $teb<br />$teb=7ffde000<br /><br />TEB[0x30]是一个指向当前进程PEB(Process Environment Block)的指针。大家都这<br />么说，可他们如何知道这个偏移的，你该上哪去找TEB的数据结构定义，不同系统上<br />该结构定义一致吗。有这么多疑问，可绝大多数文章没有告诉你捞鱼的办法，只给你<br />鱼，你一定有种意尤未尽的郁闷。呵，了解，下面就是捞鱼的办法，windbg的dt命令:<br /><br />&gt; dt ntdll!*teb* (列出匹配通配符的结构名)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ntdll!_TEB<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;... ...<br />&gt; dt -v -r ntdll!_TEB<br />struct _TEB, 64 elements, 0xfb4 bytes<br />&nbsp;&nbsp; +0x000 NtTib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: struct _NT_TIB, 8 elements, 0x1c bytes<br />&nbsp;&nbsp; +0x01c EnvironmentPointer : Ptr32 to Void<br />&nbsp;&nbsp; +0x020 ClientId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : struct _CLIENT_ID, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x028 ActiveRpcHandle&nbsp;&nbsp;: Ptr32 to Void<br />&nbsp;&nbsp; +0x02c ThreadLocalStoragePointer : Ptr32 to Void<br />&nbsp;&nbsp; +0x030 ProcessEnvironmentBlock : Ptr32 to struct _PEB, 66 elements, 0x210 bytes<br />&nbsp;&nbsp; ... ...<br /><br />偏移、名称、类型、大小等等一应俱全地列举在此。万事不求人是不对的，指望别人<br />老来求自己更是不对的，藏着掖着是要一起挨米国鬼子打的。无论你用什么系统，去<br />下载相应版本的windbg，然后用上述办法自己核实偏移。MS一贯擅长保持向后兼容性，<br />这是它巨大成功的基础，类似0x30这样的偏移，被改动的可能性并不大。<br /><br />号称新版Platform SDK的ntpsapi.h文件中直接给出了TEB的数据结构，我的不够新，<br />没找着这个文件。反正dt命令够我用了，懒得深究。<br /><br />顺便提个事。肯定有人见过这样的代码，之后eax将指向PEB:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,fs:[18h]<br />&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,[eax+30h]<br /><br />看完本文&quot;新&quot;的介绍，你肯定在疑惑中，这样的代码居然也能成功获取PEB地址，惟<br />一的解释就是fs:[18h]与fs:[0h]指向同一处。TEB结构第一成员是NT_TIB结构，后者<br />的Self成员指向自身这个NT_TIB结构，&quot;碰巧&quot;这个NT_TIB结构是TEB结构第一成员，<br />于是可以认为Self指向TEB。Self的偏移是0x18，就这么简单。<br /><br />&gt; dt -v _NT_TIB $teb<br />struct _NT_TIB, 8 elements, 0x1c bytes<br />&nbsp;&nbsp; +0x000 ExceptionList&nbsp;&nbsp;&nbsp;&nbsp;: 0x0012ffb0 struct _EXCEPTION_REGISTRATION_RECORD, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x004 StackBase&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0x00130000<br />&nbsp;&nbsp; +0x008 StackLimit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0x0012b000<br />&nbsp;&nbsp; +0x00c SubSystemTib&nbsp;&nbsp;&nbsp;&nbsp; : (null)<br />&nbsp;&nbsp; +0x010 FiberData&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0x00001e00<br />&nbsp;&nbsp; +0x010 Version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0x1e00<br />&nbsp;&nbsp; +0x014 ArbitraryUserPointer : (null)<br />&nbsp;&nbsp; +0x018 Self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0x7ffde000 struct _NT_TIB, 8 elements, 0x1c bytes<br /><br />换句话说，ds:[7ffde000h]与fs:[0h]这两个不同的逻辑地址对应同一个线性地址。<br />参看&lt;&lt;IA-32 Software Developer's Manual. Volume 3&gt;&gt;([12])的3.1小节，下面是<br />Intel的标准定义:<br /><br />逻辑地址<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;段选择子(16-bits):段内偏移(32-bits)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;也叫远指针。程序中寻址时只能使用逻辑地址。没有办法禁用段机制，但有办法<br />&nbsp;&nbsp;&nbsp;&nbsp;禁用分页机制。<br /><br />线性地址<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;逻辑地址经GDT、LDT转换后得到线性地址。<br /><br />只需一条代码即可获取PEB地址:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;eax,fs:[30h]<br /><br />&gt; dd @fs:30 L1<br />0038:00000030&nbsp;&nbsp;7ffdf000<br />&gt; dt ntdll!_TEB 7ffde000<br />&nbsp;&nbsp; +0x000 NtTib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: _NT_TIB<br />&nbsp;&nbsp; +0x01c EnvironmentPointer : (null)<br />&nbsp;&nbsp; +0x020 ClientId&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _CLIENT_ID<br />&nbsp;&nbsp; +0x028 ActiveRpcHandle&nbsp;&nbsp;: (null)<br />&nbsp;&nbsp; +0x02c ThreadLocalStoragePointer : (null)<br />&nbsp;&nbsp; +0x030 ProcessEnvironmentBlock : 0x7ffdf000<br />&nbsp;&nbsp; ... ...<br />&gt; !teb<br />TEB at 7ffde000<br />&nbsp;&nbsp;&nbsp;&nbsp;ExceptionList:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0012ffb0<br />&nbsp;&nbsp;&nbsp;&nbsp;... ...<br />&nbsp;&nbsp;&nbsp;&nbsp;PEB Address:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7ffdf000<br />&nbsp;&nbsp;&nbsp;&nbsp;... ...<br />&gt; r $peb<br />$peb=7ffdf000<br />&gt; dd $teb+30 L1 (当前基是16进制)<br />7ffde030&nbsp;&nbsp;7ffdf000<br /><br />无数种办法可以得到指向PEB的指针0x7ffdf000。<br /><br />Inside 2K([9])&lt;&lt;Table 7-6 Windows 2000 User Process Address Space Layout&gt;&gt;<br />中直接将TEB、PEB定位在0x7ffde000、0x7ffdf000。一般来说是这样的，可是不建议<br />依赖硬编码地址。这就看当前最紧要的是广泛兼容性还是压缩代码空间。注意，讨论<br />前提是编写exploit、shellcode、virus，最终可能要汇编化的，而非常规编程。<br /><br />PEB[0x0c]指向PEB_LDR_DATA结构，该结构有三个成员均可用于枚举当前进程空间中<br />的模块列表，区别在于加载顺序、内存顺序、初始化顺序。这是三个双向循环链表，<br />遍历时留神。<br /><br />&gt; dt -v -r ntdll!_PEB<br />struct _PEB, 66 elements, 0x210 bytes<br />&nbsp;&nbsp; +0x000 InheritedAddressSpace : UChar<br />&nbsp;&nbsp; +0x001 ReadImageFileExecOptions : UChar<br />&nbsp;&nbsp; +0x002 BeingDebugged&nbsp;&nbsp;&nbsp;&nbsp;: UChar<br />&nbsp;&nbsp; +0x003 SpareBool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: UChar<br />&nbsp;&nbsp; +0x004 Mutant&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 to Void<br />&nbsp;&nbsp; +0x008 ImageBaseAddress : Ptr32 to Void<br />&nbsp;&nbsp; +0x00c Ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: Ptr32 to struct _PEB_LDR_DATA, 7 elements, 0x28 bytes<br />&nbsp;&nbsp; ... ...<br />&gt; dt -v -r ntdll!_PEB_LDR_DATA<br />struct _PEB_LDR_DATA, 7 elements, 0x28 bytes<br />&nbsp;&nbsp; +0x000 Length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Uint4B<br />&nbsp;&nbsp; +0x004 Initialized&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: UChar<br />&nbsp;&nbsp; +0x008 SsHandle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Ptr32 to Void<br />&nbsp;&nbsp; +0x00c InLoadOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x014 InMemoryOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x01c InInitializationOrderModuleList : struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x024 EntryInProgress&nbsp;&nbsp;: Ptr32 to Void<br />&gt; dt -v -r ntdll!_LIST_ENTRY<br />struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x000 Flink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&nbsp;&nbsp; +0x004 Blink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes<br />&gt; dd $peb+c L1<br />7ffdf00c&nbsp;&nbsp;00241e90<br />&gt; dt ntdll!_PEB_LDR_DATA 00241e90<br />&nbsp;&nbsp; +0x000 Length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 0x28<br />&nbsp;&nbsp; +0x004 Initialized&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0x1 ''<br />&nbsp;&nbsp; +0x008 SsHandle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : (null)<br />&nbsp;&nbsp; +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x241ec0 - 0x2429d8 ]<br />&nbsp;&nbsp; +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x241ec8 - 0x2429e0 ]<br />&nbsp;&nbsp; +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x241f28 - 0x2429e8 ]<br />&nbsp;&nbsp; +0x024 EntryInProgress&nbsp;&nbsp;: (null)<br />&gt; dl 241f28 ffff 2 (注意Flink形成循环链表)<br />00241f28&nbsp;&nbsp;00241fd0 00241eac<br />00241fd0&nbsp;&nbsp;00242118 00241f28<br />00242118&nbsp;&nbsp;00242258 00241fd0<br />00242258&nbsp;&nbsp;002423a0 00242118<br />002423a0&nbsp;&nbsp;00242300 00242258<br />00242300&nbsp;&nbsp;002424e0 002423a0<br />002424e0&nbsp;&nbsp;00242440 00242300<br />00242440&nbsp;&nbsp;00242770 002424e0<br />00242770&nbsp;&nbsp;002428a8 00242440<br />002428a8&nbsp;&nbsp;00242808 00242770<br />00242808&nbsp;&nbsp;002429e8 002428a8<br />002429e8&nbsp;&nbsp;00241eac 00242808<br />00241eac&nbsp;&nbsp;00241f28 002429e8<br />&gt; dlb 2429e8 ffff 2 (注意Blink形成循环链表)<br />002429e8&nbsp;&nbsp;00241eac 00242808<br />00242808&nbsp;&nbsp;002429e8 002428a8<br />002428a8&nbsp;&nbsp;00242808 00242770<br />00242770&nbsp;&nbsp;002428a8 00242440<br />00242440&nbsp;&nbsp;00242770 002424e0<br />002424e0&nbsp;&nbsp;00242440 00242300<br />00242300&nbsp;&nbsp;002424e0 002423a0<br />002423a0&nbsp;&nbsp;00242300 00242258<br />00242258&nbsp;&nbsp;002423a0 00242118<br />00242118&nbsp;&nbsp;00242258 00241fd0<br />00241fd0&nbsp;&nbsp;00242118 00241f28<br />00241f28&nbsp;&nbsp;00241fd0 00241eac<br />00241eac&nbsp;&nbsp;00241f28 002429e8<br /><br />单从windbg所给出的信息，只能看出三个双向循环链表的存在，每个链表结点上只有<br />前向指针、后向指针，如何获取最终的模块信息呢。其实这是很关键的问题，遗憾的<br />是某些文章不知出于什么动机刻意回避该问题。<br /><br />Reactos与Tomasz Nowak提供了未公开的LDR_MODULE数据结构，我把偏移标出来了，<br />方便计算:<br /><br />typedef struct _LDR_MODULE<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InLoadOrderModuleList;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x00<br />&nbsp;&nbsp;&nbsp;&nbsp;LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InMemoryOrderModuleList;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x08<br />&nbsp;&nbsp;&nbsp;&nbsp;LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InInitializationOrderModuleList;&nbsp;&nbsp;// +0x10<br />&nbsp;&nbsp;&nbsp;&nbsp;PVOID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BaseAddress;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x18<br />&nbsp;&nbsp;&nbsp;&nbsp;PVOID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EntryPoint;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // +0x1c<br />&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SizeOfImage;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x20<br />&nbsp;&nbsp;&nbsp;&nbsp;UNICODE_STRING&nbsp;&nbsp;&nbsp;&nbsp;FullDllName;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x24<br />&nbsp;&nbsp;&nbsp;&nbsp;UNICODE_STRING&nbsp;&nbsp;&nbsp;&nbsp;BaseDllName;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x2c<br />&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x34<br />&nbsp;&nbsp;&nbsp;&nbsp;SHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LoadCount;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x38<br />&nbsp;&nbsp;&nbsp;&nbsp;SHORT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TlsIndex;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // +0x3a<br />&nbsp;&nbsp;&nbsp;&nbsp;LIST_ENTRY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HashTableEntry;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // +0x3c<br />&nbsp;&nbsp;&nbsp;&nbsp;ULONG&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TimeDateStamp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x44<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// +0x48<br />} LDR_MODULE, *PLDR_MODULE;<br /><br />郑重推荐&lt;&lt;The Undocumented Functions For Microsoft Windows NT/2000&gt;&gt;，逆反<br />心理促使我一定要让大家都知道这个数据结构引自何处([10])。<br /><br />说点题外话，Google是你的朋友。Windows底层编程在中国不知因为什么而显得资料<br />罕见，结果以前给我一个错觉，Windows底层编程举步维艰。后来因工作原因Google<br />时向Windows做了点偏移，发现国外此类编程资料并非如想像的那般罕见，有些人共<br />享出完整源代码后只是说如果感觉有帮助能否在网上订份小礼物给他，我是没境外信<br />用卡，否则一定订份小礼物给他。我还发现一件有意思的事，有人注明&quot;原创&quot;的时候<br />居然没有任何参考资源，不巧的是我看过的英文文章实在有点烂多，当创意、技巧、<br />代码片段重合得太多时，就有种无奈的感概。有鉴于此，己所不欲、勿施与人，写此<br />类型文章时一概不敢宣称是原创、翻译，撑死了是笔记，还生怕漏了引自何处。也可<br />能是我水平低，才如此。水平一高，就不便引他人之文了，谁知道呢。呵，很小的时<br />候听爹说过一句话，吃饭的永远不要责怪做饭的，确实如此，所以就不多评价了。<br /><br />建议大家写文章时认真负责地给参考资源，有URL的都注明URL，不费什么事。<br /><br />扯远了，回到LDR_MODULE结构上来，三个双向循环链表的结点正是该结构。<br /><br />按加载顺序遍历:<br /><br />!list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+24&quot; 241ec0<br />!list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+2c&quot; 241ec0<br /><br />按内存顺序遍历:<br /><br />!list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+1c&quot; 241ec8<br />!list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+24&quot; 241ec8<br /><br />按初始化顺序遍历:<br /><br />&gt; !list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+14&quot; 241f28<br />String(58,520) at 00241f3c: D:\WINDOWS\System32\ntdll.dll<br />String(64,66) at 00241fe4: D:\WINDOWS\system32\kernel32.dll<br />... ...<br />&gt; !list -t _LIST_ENTRY.Flink -x &quot;!ustr&quot; -a &quot;+1c&quot; 241f28<br />String(18,20) at 00241f44: ntdll.dll<br />String(24,26) at 00241fec: kernel32.dll<br />... ...<br /><br />一般前向遍历链表时，第一个节点对应ntdll.dll，第二个结点对应kernel32.dll，<br />我们不太关心其它模块。<br /><br />编程枚举用户模块列表时，重点显示BaseAddress、FullDllName成员。总结一下全过<br />程:<br /><br />a. 从fs:[30h]获取PEB地址<br /><br />b. 从PEB[0x0c]获取Ldr地址<br /><br />c. 从Ldr[0x0c]获取InLoadOrderModuleList.Flink<br /><br />d. 从InLoadOrderModuleList.Flink开始前向遍历循环链表<br /><br />e. 显示LDR_MODULE结构的BaseAddress、FullDllName成员。<br /><br />下面是完整的C语言演示程序，汇编化留到编写完整shellcode时进行。<br /><br />--------------------------------------------------------------------------<br />/*<br />* -----------------------------------------------------------------------<br />* Compile : For x86/EWindows XP SP1 &amp; VC 7<br />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : cl EnumModule.c /nologo /Os /G6 /W3 /D &quot;WIN32&quot; /D &quot;NDEBUG&quot; /D &quot;_CONSOLE&quot; /link /RELEASE<br />*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :<br />* Create&nbsp;&nbsp;: 2003-08-12 11:36<br />* Modify&nbsp;&nbsp;: <br />* -----------------------------------------------------------------------<br />*/<br /><br />/*<br />* 按加载顺序遍历双向循环链表<br />*/<br /><br />#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br /><br />#pragma comment( linker, &quot;/INCREMENTAL:NO&quot;&nbsp;&nbsp;&nbsp;&nbsp;)<br />#pragma comment( linker, &quot;/subsystem:console&quot; )<br /><br />int __cdecl main ( int argc, char * argv[] )<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;void *PEB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Flink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *BaseAddress = NULL,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *FullDllName = NULL;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;__asm<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; eax,fs:[0x30]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp; PEB,eax<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;PEB&nbsp;&nbsp; = 0x%08X\n&quot;, PEB );<br />&nbsp;&nbsp;&nbsp;&nbsp;Ldr&nbsp;&nbsp; = *( ( void ** )( ( unsigned char * )PEB + 0x0c ) );<br />&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;Ldr&nbsp;&nbsp; = 0x%08X\n&quot;, Ldr );<br />&nbsp;&nbsp;&nbsp;&nbsp;Flink = *( ( void ** )( ( unsigned char * )Ldr + 0x0c ) );<br />&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;Flink = 0x%08X\n&quot;, Flink );<br />&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;&nbsp;&nbsp;&nbsp; = Flink;<br />&nbsp;&nbsp;&nbsp;&nbsp;do<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BaseAddress = *( ( void ** )( ( unsigned char * )p + 0x18 ) );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FullDllName = *( ( void ** )( ( unsigned char * )p + 0x28 ) );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf( &quot;p&nbsp;&nbsp;&nbsp;&nbsp; = 0x%08X 0x%08X &quot;, p, BaseAddress );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wprintf( L&quot;%s\n&quot;, FullDllName );<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p = *( ( void ** )p );<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;while ( Flink != p );<br />&nbsp;&nbsp;&nbsp;&nbsp;return( EXIT_SUCCESS );<br />}&nbsp;&nbsp;/* end of main */<br />--------------------------------------------------------------------------<br /><br />执行效果如下。可以看出，尽管是循环链表，也可通过判断BaseAddress是否为NULL<br />来结束遍历。<br /><br />&gt; EnumModule<br />PEB&nbsp;&nbsp; = 0x7FFDF000<br />Ldr&nbsp;&nbsp; = 0x00241E90<br />Flink = 0x00241EC0<br />p&nbsp;&nbsp;&nbsp;&nbsp; = 0x00241EC0 0x00400000 X:\EnumModule.exe<br />p&nbsp;&nbsp;&nbsp;&nbsp; = 0x00241F18 0x77F50000 X:\XP\System32\ntdll.dll<br />p&nbsp;&nbsp;&nbsp;&nbsp; = 0x00241FC0 0x77E60000 X:\XP\system32\kernel32.dll<br />p&nbsp;&nbsp;&nbsp;&nbsp; = 0x00241E9C 0x00000000<br />&gt;<br /><br />☆ 参考资源<br /><br />[ 8] http://vx.netlux.org/vx.php?id=z001 (29A杂志)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Virus Writing Guide 1.00 for Win32 - Billy Belceb<br />&nbsp;&nbsp;&nbsp;&nbsp; 29A-4.202<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; A guide to the latest methods to retrieve API's in a Win32 environment - LethalMind<br />&nbsp;&nbsp;&nbsp;&nbsp; 29A-4.227<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Gaining important datas from PEB under NT boxes - Ratter<br />&nbsp;&nbsp;&nbsp;&nbsp; 29A-6.024<br /><br />[ 9] &lt;&lt;Inside Microsoft Windows 2000 Third Edition&gt;&gt; - David A. Solomon, Mark E. Russinovich<br /><br />[10] The Undocumented Functions For Microsoft Windows NT/2000<br />&nbsp;&nbsp;&nbsp;&nbsp; http://undocumented.ntinternals.net/ntundoc.chm<br /><br />[12] Intel Architecture Software Developer's Manual. Volume 1<br />&nbsp;&nbsp;&nbsp;&nbsp; ftp://download.intel.com/design/PentiumII/manuals/24319002.pdf<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Intel Architecture Software Developer's Manual. Volume 2<br />&nbsp;&nbsp;&nbsp;&nbsp; ftp://download.intel.com/design/PentiumII/manuals/24319102.pdf<br /><br />&nbsp;&nbsp;&nbsp;&nbsp; Intel Architecture Software Developer's Manual. Volume 3<br />&nbsp;&nbsp;&nbsp;&nbsp; <a href="ftp://download.intel.com/design/PentiumII/manuals/24319202.pdf">ftp://download.intel.com/design/PentiumII/manuals/24319202.pdf</a></p>]]></description>
		</item>
		    
		
		<item>
			<title> pe header explore</title>
			<link>http://itmed.blog.sohu.com/90926699.html</link>
			<comments>http://itmed.blog.sohu.com/90926699.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Tue, 24 Jun 2008 11:09:49 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/90926699.html</guid>
			<description><![CDATA[<p>;----------------<br />;编译模式=&quot;CON&quot;<br />;----------------<br />.386<br />.model flat, stdcall<br />option casemap :none</p>
<p>include windows.inc<br />include user32.inc<br />include kernel32.inc<br />include masm32.inc</p>
<p>includelib user32.lib<br />includelib kernel32.lib<br />includelib masm32.lib<br />;-------------------------------------------------------</p>
<p>.DATA<br />&nbsp;szMsg db &quot;Hello World!&quot;,13,10,0<br />&nbsp;crcl&nbsp; db 0dh,0ah</p>
<p>.CODE<br />START:</p>
<p>&nbsp;xor edx,edx<br />&nbsp;assume fs:nothing <br />&nbsp;mov ebx,fs:[edx+30h]<br />&nbsp;mov ecx,[ebx+0ch]<br />&nbsp;mov ecx,[ecx+1ch]<br />&nbsp;mov ecx,[ecx]<br />&nbsp;mov ebp,[ecx+8] ;base address of kernel32.dll<br />&nbsp;mov eax,[ebp+3ch]&nbsp; ;start of pe header<br />&nbsp;mov ecx,[ebp+eax+78h] ;relative offset of export table<br />&nbsp;add ecx,ebp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;absolute addr of export table<br />&nbsp;mov ebx,[ecx+20h] ; relative offset of names table<br />&nbsp;add ebx,ebp&nbsp; ;absolute addr of names tables<br />&nbsp;xor edi,edi</p>
<p>xxx:<br />&nbsp;mov esi,[ebx+edi*4]<br />&nbsp;cmp esi,0<br />&nbsp;jz yyy<br />&nbsp;add esi,ebp<br />&nbsp;invoke StdOut,esi<br />&nbsp;invoke StdOut,addr crcl<br />&nbsp;inc edi<br />&nbsp;jmp xxx</p>
<p>yyy:</p>
<p><br />&nbsp;;cdq</p>
<p>&nbsp;;invoke locate,2,2&nbsp;&nbsp;;输出文本的坐标<br />&nbsp;invoke StdOut,ADDR szMsg<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;invoke ExitProcess,0</p>
<p>end START</p>]]></description>
		</item>
		    
		
		<item>
			<title>完成不可能完成的任务---修复60万计算机(7)</title>
			<link>http://itmed.blog.sohu.com/90670397.html</link>
			<comments>http://itmed.blog.sohu.com/90670397.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 20 Jun 2008 22:31:57 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/90670397.html</guid>
			<description><![CDATA[<p align="center"><font face="黑体" size="5"><strong>完成不可能完成的任务---修复60万计算机(7)</strong></font></p>
<p><br />&nbsp;&nbsp;&nbsp; 饭后又和simens的工程师一块回petct中心研究去了。每当有不易完全的任务，我心里都特别兴奋，有一种挑战感，这种感觉很好啊，我很喜欢。工程师还在打求助电话，看着他们也不能掌控全程的感觉，心里也很郁闷。如果连自己也不能完全搞定，也真没有成就感啊！他们也很无奈，小郭提议windows系统恢复，我认为意义不大，果不其然，恢复了几个时间点，没有！还把我的设置弄丢了，因为网卡1坏了，那么它的IP地址在windows里也找不到了，所以恢复了也是找不到的，现在就怀疑IP地址的配置了，配成了192.168.0.4对不对呢？我们只是猜想。工程师打电话问原来的安装工程师，那家伙更喜剧，记不得了。工程师又问华西，配置和我们的不一致，小郭问广总，没能问着，时间一分一分地过去，现在就是要找着那个正确的IP地址了，其它的问题比如启动电路、license我们都克服了，我也很无奈，因为当初安装时自己就不知道，直到周五才看见它们的全貌，无奈啊！心中彻底无语。只有让他们去找相同配置的设备的IP地址了，刚好科里有事，先闪会，给工程师招呼，如果弄好了，打个电话通知一下我，也让我高兴下。回到科里，忙去了。17：40接小孩准备回家时，碰见小孩同学的妈妈急急的赶过来接小孩，告诉我，&ldquo;弄好了弄好了，那个工程师说你起了关键性的作用！工程师说维修维修就是大家一起围着修，我们大家一起想办法，修好了，我要着了广总的IP地址，你绕过了那个注册码，最关键的一步。&rdquo;忙问IP地址是什么，原来是0.20，shit!这件事情终于完美解决了，不能不说这是本周一的最开心的事。 <br />&nbsp;&nbsp;&nbsp; 总结了一下，问题也是一步一步解决的，没有解决不了问题，simens要求换整机，出于商业利益考虑，只是太贵了点，60万，就因为启动电路故障，也许是虚焊问题，网卡mac1确确实实坏了，质量问题？才使用多长时间？可爱的人民币啊！</p>
<p>&nbsp;</p>]]></description>
		</item>
		    
		
		<item>
			<title>完成不可能完成的任务---修复60万计算机(6)</title>
			<link>http://itmed.blog.sohu.com/90668195.html</link>
			<comments>http://itmed.blog.sohu.com/90668195.html#comment</comments>
			<dc:creator>深蓝无忌</dc:creator>
			<pubDate>Fri, 20 Jun 2008 22:08:23 +0800</pubDate>
			<guid>http://itmed.blog.sohu.com/90668195.html</guid>
			<description><![CDATA[<p align="center"><font face="黑体" size="5"><strong>完成不可能完成的任务---修复60万计算机(6)</strong></font></p>
<p><br />&nbsp;&nbsp;&nbsp; 周六周日没有等来simens公司的维修人员，可怜没能进城去玩呢，陪着计算机过了2天。<br />&nbsp;&nbsp;&nbsp; 周一交班过后，事情多啊！9:43小孩同学的妈妈打电话过来说，simens公司的人来了，让我赶紧过去。到了petct中心，终于见着传说中的simens公司的牛人了，40来岁，很实在的一个工程师，给我印象很好。他先用电烙铁焊好了我们周五用土办法整出来的启动电路，不得不说，那办法还挺好，好得让人佩服！原启动电路有虚焊，不可能因为启动电路故障而换整机吧，60万元哦。他启动机器后，故障依旧，需要license.又和simens公司联系，嘿嘿，效率不是盖的，很快发来2组注册码，在ACS上可用，但在故障机上还是无法通过，工程师解释说这个注册码要美国才能产生，因为时差关系，美国现在还是半夜呢，还要公司申请。又解释了一通simens的序列号有一个庞大的机构在动作，很多的人在为此心碌，我彻底地无语......我注意了一个细节，他打电话时把机箱立了起来，查找机箱上的序列号，还要网卡的mac号，报的是mac1，天，注册码还与网卡地址有关！那要是网卡坏了，那不是连换一块网块的可能都没有？这也太狠了，我心里又要开始问候simens的那三代人了！好象周五时换了网卡口的，是不是原来那个网卡mac1坏了，马上运行ipconfig/all，果然，这个mac地址不是mac1的地址，原来真是网卡也坏了。这次问题多了，启动电路故障，网卡坏了一个，问题多了。又刚好平时对这个mac地址很有研究，以前做网络安全设计时设想通过IP地址找到mac地址，可以准确找到机器，知道在windows中可以克隆网卡地址，我想如果我把现在的备用网卡的mac地址克隆成原mac1的地址，难道不行吗？说干就干，马上克隆，嘿嘿，居然服务启动了，没有要license，也没有说invalid license了，过了，骗过了！怀着激动的心情，又全部重新启动了一遍，真的通过license了，但机架还是无法存取！但我们离成功又大大前进了一步，心中非常高兴。整了这么长时间，12点了，只好先饭饭去了。<br /></p>]]></description>
		</item>
		    
		
	</channel>
</rss>
