﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-空穴来风-随笔分类-Develop</title><link>http://www.cppblog.com/bigsml/category/2847.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 20 Dec 2008 02:38:24 GMT</lastBuildDate><pubDate>Sat, 20 Dec 2008 02:38:24 GMT</pubDate><ttl>60</ttl><item><title>Pythong logging 到 Logging4cplus 的适配器</title><link>http://www.cppblog.com/bigsml/archive/2008/12/19/69856.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Fri, 19 Dec 2008 10:13:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/12/19/69856.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/69856.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/12/19/69856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/69856.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/69856.html</trackback:ping><description><![CDATA[<p>Python 的logging 模块的Socket 和 Logging4cplus 的 socket 的格式是不一样的,&nbsp;现实中需要将日志发送到logging4cplus 的服务器, 不得已, 写了个 Python logging 模块到 logging4cplus的Adapter <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #008000">#</span><span style="COLOR: #008000">!/usr/bin/env&nbsp;python</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #008000">#</span><span style="COLOR: #008000">-*-&nbsp;coding:&nbsp;gbk&nbsp;-*-</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #0000ff">from</span><span style="COLOR: #000000">&nbsp;struct&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;pack,&nbsp;unpack&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BufferPack(object):&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800080">__init__</span><span style="COLOR: #000000">(self):<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">''</span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addChar(self,&nbsp;s,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;pack(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;b</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;c</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;s&nbsp;)<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addShort(self,&nbsp;s,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;pack(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;H</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;h</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;s&nbsp;)<br></span><span style="COLOR: #008080">14</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">15</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addInt(self,&nbsp;s,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">16</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;pack(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;I</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;i</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;s&nbsp;)<br></span><span style="COLOR: #008080">17</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">18</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addLong(self,&nbsp;s,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">19</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;pack(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;L</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;l</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;s&nbsp;)<br></span><span style="COLOR: #008080">20</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">21</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addString(self,&nbsp;s):<br></span><span style="COLOR: #008080">22</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.addInt(&nbsp;len(s)&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">23</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;s&nbsp;<br></span><span style="COLOR: #008080">24</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">25</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;addBuffer(self,&nbsp;s):<br></span><span style="COLOR: #008080">26</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;s.buffer&nbsp;<br></span><span style="COLOR: #008080">27</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">28</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BufferUnpack(object):<br></span><span style="COLOR: #008080">29</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;char_bits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;len(&nbsp;pack(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;b</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;0)&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">31</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;short_bits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;len(&nbsp;pack(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;H</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;0)&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">32</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;int_bits&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;len(&nbsp;pack(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;I</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;0)&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">33</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;long_bits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;len(&nbsp;pack(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&gt;L</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;0)&nbsp;)&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">34</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">35</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800080">__init__</span><span style="COLOR: #000000">(self,&nbsp;buffer):<br></span><span style="COLOR: #008080">36</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;buffer&nbsp;<br></span><span style="COLOR: #008080">37</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pos&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;0<br></span><span style="COLOR: #008080">38</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">39</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;_read_item(self,&nbsp;unpackstr,&nbsp;len):<br></span><span style="COLOR: #008080">40</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;unpack(unpackstr,&nbsp;self.buffer[self.pos:self.pos</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">len]&nbsp;)<br></span><span style="COLOR: #008080">41</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pos&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;len&nbsp;<br></span><span style="COLOR: #008080">42</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;v&nbsp;<br></span><span style="COLOR: #008080">43</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">44</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;readChar(self,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">45</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;self._read_item(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;b</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;c</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;self.char_bits)<br></span><span style="COLOR: #008080">46</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">47</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;readShort(self,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">48</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;self._read_item(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;H</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;h</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;self.short_bits&nbsp;)<br></span><span style="COLOR: #008080">49</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">50</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;readInt(self,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">51</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;self._read_item(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;I</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;i</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;self.int_bits&nbsp;)<br></span><span style="COLOR: #008080">52</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">53</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;readLong(self,&nbsp;unsigned</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">False):<br></span><span style="COLOR: #008080">54</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;self._read_item(unsigned&nbsp;</span><span style="COLOR: #0000ff">and</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;L</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">or</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">&lt;l</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;self.long_bits&nbsp;)<br></span><span style="COLOR: #008080">55</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">56</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;readString(self):<br></span><span style="COLOR: #008080">57</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;self.readInt()<br></span><span style="COLOR: #008080">58</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;self.buffer[self.pos:self.pos</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">len]&nbsp;<br></span><span style="COLOR: #008080">59</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pos&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;len<br></span><span style="COLOR: #008080">60</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;v&nbsp;<br></span><span style="COLOR: #008080">61</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">62</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">def</span><span style="COLOR: #000000">&nbsp;PackMessage(&nbsp;record&nbsp;):<br></span><span style="COLOR: #008080">63</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;BufferPack()<br></span><span style="COLOR: #008080">64</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addChar(</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">,&nbsp;True)&nbsp;<br></span><span style="COLOR: #008080">65</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addChar(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;True)&nbsp;<br></span><span style="COLOR: #008080">66</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">67</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">{log.servername}</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">68</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(record.name)&nbsp;<br></span><span style="COLOR: #008080">69</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addInt(record.levelno</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">1000</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">70</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(</span><span style="COLOR: #800000">""</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">71</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(record.msg)<br></span><span style="COLOR: #008080">72</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(str(record.threadName))<br></span><span style="COLOR: #008080">73</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(str(record.process))<br></span><span style="COLOR: #008080">74</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addInt(&nbsp;record.created&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">75</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addInt(&nbsp;record.msecs&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">76</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addString(record.filename)<br></span><span style="COLOR: #008080">77</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;bp.addInt(&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">78</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">79</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;pkg&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;BufferPack()<br></span><span style="COLOR: #008080">80</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;pkg.addInt(len(bp.buffer),&nbsp;True)&nbsp;<br></span><span style="COLOR: #008080">81</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;pkg.addBuffer(&nbsp;bp&nbsp;)&nbsp;<br></span><span style="COLOR: #008080">82</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">83</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;pkg.buffer<br></span><span style="COLOR: #008080">84</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">85</span>&nbsp;<span style="COLOR: #000000"></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #800080">__name__</span><span style="COLOR: #000000">==</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">__main__</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">:<br></span><span style="COLOR: #008080">86</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000">&nbsp;logging,&nbsp;logging.handlers&nbsp;<br></span><span style="COLOR: #008080">87</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">88</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;logger&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;logging.getLogger()<br></span><span style="COLOR: #008080">89</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;logging.handlers.SocketHandler.makePickle&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">lambda</span><span style="COLOR: #000000">&nbsp;self,rc&nbsp;:&nbsp;PackMessage(rc)&nbsp;<br></span><span style="COLOR: #008080">90</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">91</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;hdlr&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;logging.handlers.SocketHandler(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">{logserver.ip}</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">8888</span><span style="COLOR: #000000">)&nbsp;<br></span><span style="COLOR: #008080">92</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;formatter&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;logging.Formatter(</span><span style="COLOR: #800000">'</span><span style="COLOR: #800000">%(asctime)s&nbsp;%(levelname)s&nbsp;%(message)s</span><span style="COLOR: #800000">'</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">93</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;hdlr.setFormatter(formatter)<br></span><span style="COLOR: #008080">94</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;logger.addHandler(hdlr)<br></span><span style="COLOR: #008080">95</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;logger.setLevel(logging.NOTSET)<br></span><span style="COLOR: #008080">96</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">97</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;logger.info(</span><span style="COLOR: #800000">"</span><span style="COLOR: #800000">hello</span><span style="COLOR: #800000">"</span><span style="COLOR: #000000">)</span></div>
<br>使用的时候.<br>1. 在logging 创建SocketHandler 的时候, 需要修改logging.handlers.SocketHandler.makePickle 为方法 PackMessage <br>logging.handlers.SocketHandler.makePickle = lambda self,rc : PackMessage(rc) <br><br>2. 需要修改代码中的两部分内容 {log.servername} 和 {logserver.ip}<br>
<img src ="http://www.cppblog.com/bigsml/aggbug/69856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-12-19 18:13 <a href="http://www.cppblog.com/bigsml/archive/2008/12/19/69856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BHO基础</title><link>http://www.cppblog.com/bigsml/archive/2008/12/04/68573.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Thu, 04 Dec 2008 09:26:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/12/04/68573.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/68573.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/12/04/68573.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/68573.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/68573.html</trackback:ping><description><![CDATA[<p>BHO就是Browser Helper Object(浏览器辅助对象)</p>
<p><strong>BHO关联原理</strong> (BHO关联的是SHDOCVW,也就是说不只关联IE,下面全部用IE来说明) <br>1.IE的窗口打开时,先寻找HKLM下的SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\ 里的CLSID,这些CLSID,都对应着相应的BHO插件，然后根据这个CLSID到HKCR下的CLSIDs里找到此插件的信息，包括文件位置等。<br>2.IE根据找到的CLSID信息创建 BHO 对象,并且查找 IObjectWithSite 接口. (这个接口非常简单,只有SetSite和GetSite两个方法)<br>3.IE把IWebBrowser2(浏览器插件)传到 BHO 的 SetSite 方法，用户在此方法中可挂载自己的事件处理方法。<br>4.窗口关闭时,IE把 null 传到 BHO 的 SetSite 方法，此方法用来去掉挂载的事件处理方法。</p>
<p><strong>编写BHO流程<br></strong>1.创建IObjectWithSite显式接口，创建 COM 类型，实现继承IObjectWithSite接口<br>2.实现此接口并在SetSite方法里加上所要挂载的事件<br>3.处理事件<br>4.注册此BHO到注册表中HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects;(HKCR下的CLSIDs是根据上面的路径自动注册的)<br>5、.net 下须设置此BHO项目的 配置属性_&gt;生成 中为Interop注册为True，这样才能将.net 类库文件注册到COM</p>
<p><strong>删除BHO</strong> <br>打开注册表项到:HKLM下的Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Browser Helper Objects 可以看到下面有一些CLSID值,这些值对应相关的插件,点击可以在默认值后看到相关插件的名称!可以复制相关CLSID到注册表中搜索相关CLSID,找到后打开InprocServer32可以看到相关文件的路径,至于DLL文件等可以用UEDIT32.exe工具打开查看具体信息,当然也可以用修改程序类的eXeScope.exe研究一下! <br>请根据具体情况删除相关键值和相关文件! <br><br>REF: <br>BHO 的编写&nbsp;<br><a href="http://www.vckbase.com/document/listdoc.asp?sclsid=1711">VCKBase 关于IE 编程文档中心</a> <br><a href="http://www.builder.com.cn/2007/1027/583322.shtml">C++中使用BHO来屏蔽特定网站</a><br><a href="http://dev.csdn.net/develop/article/48/48483.shtm">浏览器集成教学 自定义浏览器</a><br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/68573.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-12-04 17:26 <a href="http://www.cppblog.com/bigsml/archive/2008/12/04/68573.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解Effictive C++ "条款38: 决不要重新定义继承而来的缺省参数值" </title><link>http://www.cppblog.com/bigsml/archive/2008/10/06/63327.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Mon, 06 Oct 2008 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/10/06/63327.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/63327.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/10/06/63327.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/63327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/63327.html</trackback:ping><description><![CDATA[<p>看条款38 的时候不是很理解, 于是写了个测试代码 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">#include</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000">&nbsp;std;&nbsp;<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;A{<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">145</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">A:&nbsp;a=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">a</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br>};&nbsp;<br><br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;B:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;A&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b)<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">B:&nbsp;b=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">b</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>};&nbsp;<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;C:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;B&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">999</span><span style="COLOR: #000000">)<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">C:&nbsp;c=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">c</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">endl;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>};<br></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;D:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;C&nbsp;<br>{&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;show()<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">D:\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};&nbsp;<br><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pp;<br>&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;a;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;c;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;d;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;a.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">a;&nbsp;&nbsp;&nbsp;&nbsp;pp</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;b.show();&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;error&nbsp;C2660:&nbsp;'B::show'&nbsp;:&nbsp;function&nbsp;does&nbsp;not&nbsp;take&nbsp;0&nbsp;arguments</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">b;&nbsp;&nbsp;&nbsp;&nbsp;pp</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;c.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">c;&nbsp;&nbsp;&nbsp;&nbsp;pp</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;d.show();<br>&nbsp;&nbsp;&nbsp;&nbsp;pp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">d;&nbsp;&nbsp;&nbsp;&nbsp;pp</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pc</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">d;<br>&nbsp;&nbsp;&nbsp;&nbsp;pc</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">pause</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;<br>}&nbsp;&nbsp;&nbsp;<br></span></div>
输出结果是<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">A:&nbsp;a=145<br>A:&nbsp;a=145<br>B:&nbsp;b=145<br>C:&nbsp;c=999<br>C:&nbsp;c=145<br>D:<br>C:&nbsp;c=145<br>C:&nbsp;c=999</span></div>
<br>回顾条款&nbsp;<br>虚函数是动态绑定而缺省参数值是静态绑定的.&nbsp; 为什么C++坚持这种有违常规的做法呢？答案和运行效率有关。如果缺省参数值被动态绑定，编译器就必须想办法为虚函数在运行时确定合适的缺省值，这将比现在采用的在编译阶段确定缺省值的机制更慢更复杂。做出这种选择是想求得速度上的提高和实现上的简便，所以大家现在才能感受得到程序运行的高效； <br><br>所以 <br>a. 静态绑定 .vs. 动态绑定 <br>A *pp&nbsp;<span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;new B;</span><span style="COLOR: #000000"><br></span>这里 pp 静态绑定是 A* , 而动态绑定却是 B*<br>B *pb = new B;<br>这里 pb 静态绑定和动态绑定是一样的都是 B* <br><br>b. 缺省值是静态绑定的, 而非动态绑定 <br>所以 <br>d.show() 输出 D:&nbsp; 因为show 被 D override <br><br>pp&nbsp;<span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">d;&nbsp;&nbsp;&nbsp;&nbsp;pp</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">show();&nbsp;&nbsp; <br>pp 被动态绑定到D *, 但是show 的缺省值却是A* 的 145, 所以输出的是 C:&nbsp;c=145, 而不是999 ( 函数 show 被C 给override 了)&nbsp; <br></span><span style="COLOR: #000000"><br>而&nbsp;C *pc = &amp;d; pc-&gt;show() , pc 静态绑定为C*, 而动态绑定为 D* , 所以输出的是 C:&nbsp;c=999 , 999 是 C* 静态绑定的缺省值 <br><br></span>c.&nbsp;所以调用b.show 的时候出现了如下的错误 <br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;b.show();&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;error&nbsp;C2660:&nbsp;'B::show'&nbsp;:&nbsp;function&nbsp;does&nbsp;not&nbsp;take&nbsp;0&nbsp;arguments</span><span style="COLOR: #008000"><br></span>因为 B* 没有静态绑定的函数 <br><br>结论就是<strong> 决不要重新定义继承而来的缺省参数值&nbsp;<br></strong><br>ref:&nbsp;<br>从这里学了不少:)&nbsp;<a href="http://bbs.chinaunix.net/viewthread.php?tid=439188">http://bbs.chinaunix.net/viewthread.php?tid=439188</a>&nbsp;<br>
<img src ="http://www.cppblog.com/bigsml/aggbug/63327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-10-06 17:19 <a href="http://www.cppblog.com/bigsml/archive/2008/10/06/63327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>小觑IE 浏览器ActiveX 控件创建过程</title><link>http://www.cppblog.com/bigsml/archive/2008/07/30/57550.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Wed, 30 Jul 2008 11:55:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/07/30/57550.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/57550.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/07/30/57550.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/57550.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/57550.html</trackback:ping><description><![CDATA[<p>1. Activex 控件是怎么安装的<br>一个HTML 中嵌入控件的例子 <br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">object&nbsp;</span><span style="COLOR: #ff0000">classid</span><span style="COLOR: #0000ff">="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"</span><span style="COLOR: #ff0000">&nbsp;codebase</span><span style="COLOR: #0000ff">="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0"</span><span style="COLOR: #ff0000">&nbsp;width</span><span style="COLOR: #0000ff">="400"</span><span style="COLOR: #ff0000">&nbsp;height</span><span style="COLOR: #0000ff">="300"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="movie"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="flash/flash.swf"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="quality"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="high"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">embed&nbsp;</span><span style="COLOR: #ff0000">src</span><span style="COLOR: #0000ff">="flash/flash.swf"</span><span style="COLOR: #ff0000">&nbsp;quality</span><span style="COLOR: #0000ff">="high"</span><span style="COLOR: #ff0000">&nbsp;pluginspage</span><span style="COLOR: #0000ff">="http://www.macromedia.com/go/getflashplayer"</span><span style="COLOR: #ff0000">&nbsp;type</span><span style="COLOR: #0000ff">="application/x-shockwave-flash"</span><span style="COLOR: #ff0000">&nbsp;width</span><span style="COLOR: #0000ff">="400"</span><span style="COLOR: #ff0000">&nbsp;height</span><span style="COLOR: #0000ff">="300"</span><span style="COLOR: #0000ff">&gt;&lt;/</span><span style="COLOR: #800000">embed</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">object</span><span style="COLOR: #0000ff">&gt;</span></div>
<p>当用IE 打开这个页面的时候, IE 首先根据 classid&nbsp;在注册表中(HKEY_CLASS_ROOT)查找其安装信息, 如果未找到, 则IE 根据codebase 去看是否有对应的控件存在; 如果还是不行, 则会一些控件注册服务器联系(列表在 HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings\CodeBaseSearchPath 可以找到&nbsp;), 一般是 <a href="http://activex.microsoft.com/objects/ocget.dll">http://activex.microsoft.com/objects/ocget.dll</a>&nbsp;, <a href="http://codecs.microsoft.com/isapi/ocget.dll">http://codecs.microsoft.com/isapi/ocget.dll</a>&nbsp; , 然后服务器会告诉IE 从哪里去下载.&nbsp;<br><br>FROM : <a href="http://oreilly.com/catalog/malmobcode/chapter/ch11.html">http://oreilly.com/catalog/malmobcode/chapter/ch11.html</a><br><br><br>2. ActiveX 控件是如何启动的 <br>创建一个控件有很多种方法 <br>CoCreateInstance, CoGetInstanceFromFile, CoGetInstanceFromIStorage <br>CoCreateInstanceEx<br>CoGetClassObjectFromURL , CoGetClassObject&nbsp; <br>CoGetObject, DllGetClassObject 等 <br>基本调用顺序好像是 <br>(CoGetInstanceFromFile, CoGetInstanceFromIStorage ) -&gt; CoCreateInstance<br>CoCreateInstanceEx<br>CoGetClassObjectFromURL&nbsp;-&gt; CoGetClassObject&nbsp; <br>其他没有测试过... :9<br><br>IE 创建控件的时候会调用 CoGetClassObjectFromURL -&gt; CoGetClassObject 的顺序进行, 而不是直接调用(CoCreateInstance 或者 CoCreateInstanceEx) , 但是免不了控件会自己调用 CoCreateInstanceEx, 比如Real 控件在创建的时候会调用Dx 的组件等. </p>
<img src ="http://www.cppblog.com/bigsml/aggbug/57550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-07-30 19:55 <a href="http://www.cppblog.com/bigsml/archive/2008/07/30/57550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>获取IE (控件)的所有链接(包括Frameset, iframe) </title><link>http://www.cppblog.com/bigsml/archive/2008/07/30/57548.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Wed, 30 Jul 2008 11:17:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/07/30/57548.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/57548.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/07/30/57548.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/57548.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/57548.html</trackback:ping><description><![CDATA[<p>IE 顶层 body 节点通过IHTMLElement-&gt;get_all 方法无法获取iframe 里面的节点列表 </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">CComPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLElement</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;body;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><img src="http://www.cppblog.com/Images/dot.gif">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CComPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IDispatch</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spDispCollection;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>body</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_all(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">spDispCollection);</span></div>
<br>所以要获取iframe/frame(frameset) 里面的节点列表的话, 则需要根据body/doc 找到frames, 然后从frames -&gt;&nbsp;IHTMLWindow2 -&gt; IHTMLDocument2 .&nbsp;主要有2个方法, 下面是代码片段 <br>方法一: <br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">IHTMLDocument2&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pDoc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;浏览器的Document(IWebBrowser2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">IDispatch</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">IHTMLDocument2);&nbsp;<br>IHTMLWindow2&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pHTMLWnd&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;&nbsp;<br>IHTMLDocument2&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pFrameDoc</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;&nbsp;<br>IHTMLFramesCollection2&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pFramesCollection</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;&nbsp;<br>LPDISPATCH&nbsp;lpDispatch;&nbsp;<br><br></span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;p;&nbsp;<br>VARIANT&nbsp;varindex,varresult;&nbsp;<br>varresult.vt</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">VT_DISPATCH;&nbsp;<br>varindex.vt&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;VT_I4;&nbsp;<br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(pDoc</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;HRESULT&nbsp;hr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">pDoc</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_frames(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pFramesCollection);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(SUCCEEDED(hr)</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">pFramesCollection</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hr</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">pFramesCollection</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_length(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">p);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(SUCCEEDED(hr))&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">p;&nbsp;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;varindex.lVal&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;i;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(pFramesCollection</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">item(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">varindex,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">varresult)&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">S_OK)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpDispatch</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">(LPDISPATCH)varresult.ppdispVal;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(SUCCEEDED(lpDispatch</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryInterface(IID_IHTMLWindow2,&nbsp;(LPVOID&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pHTMLWnd)))&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<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;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(SUCCEEDED(pHTMLWnd</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_document(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">pFrameDoc)))&nbsp;<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;<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;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">work&nbsp;with&nbsp;the&nbsp;pFrameDoc<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&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;<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;pHTMLWnd</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();&nbsp;<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;pHTMLWnd</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">NULL;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pFramesCollection</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;pDoc</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Release();&nbsp;<br>}</span></div>
<br>方法二:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLElement</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;pElem&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;; // 可以递归上面的 CComPtr<span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IDispatch</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spDispCollection 来得到 </span><br>CComBSTR&nbsp;bstrTagName;<br>pElem</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_tagName(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">bstrTagName);<br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(&nbsp;lstrcmpiW(L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">IFRAME</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;bstrTagName)</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lstrcmpiW(L</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">FRAME</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;bstrTagName)</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLFrameBase2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;_framebase2;<br>&nbsp;&nbsp;&nbsp;&nbsp;CComPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLWindow2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_framewindow;<br>&nbsp;&nbsp;&nbsp;&nbsp;CComPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLDocument2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_framedoc;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;(_framebase2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spItem)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;SUCCEEDED(&nbsp;_framebase2</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_contentWindow(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">_framewindow)&nbsp;)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;_framewindow</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;SUCCEEDED(&nbsp;_framewindow</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_document(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">_framedoc)&nbsp;)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;_framedoc</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;对&nbsp;_framedoc&nbsp;节点进行处理</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br>}</span></div>
<p><br>iframe 跨域访问(cross frame)&nbsp;&nbsp;zz from : <a href="http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html">http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html</a>&nbsp;<br>由于安全性限制, 为防止跨域脚本攻击, 当frames 跨域的时候, IHTMLWindow2::get_document&nbsp;调用将返回 E_ACCESSDENIED . <br>下面函数 HtmlWindowToHtmlDocument&nbsp; 对于跨域的frame 通过 IHTMLWindow2 -&gt; IID_IWebBrowserApp -&gt; IHTMLWindow2 绕过了限制. </p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Converts&nbsp;a&nbsp;IHTMLWindow2&nbsp;object&nbsp;to&nbsp;a&nbsp;IHTMLDocument2.&nbsp;Returns&nbsp;NULL&nbsp;in&nbsp;case&nbsp;of&nbsp;failure.<br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;It&nbsp;takes&nbsp;into&nbsp;account&nbsp;accessing&nbsp;the&nbsp;DOM&nbsp;across&nbsp;frames&nbsp;loaded&nbsp;from&nbsp;different&nbsp;domains.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLDocument2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;HtmlWindowToHtmlDocument(CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLWindow2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spWindow)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ATLASSERT(spWindow&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLDocument2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spDocument;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HRESULT&nbsp;hRes&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spWindow</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_document(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">spDocument);<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;((S_OK&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;hRes)&nbsp;</span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000">&nbsp;(spDocument&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;The&nbsp;html&nbsp;document&nbsp;was&nbsp;properly&nbsp;retrieved.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;spDocument;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;hRes&nbsp;could&nbsp;be&nbsp;E_ACCESSDENIED&nbsp;that&nbsp;means&nbsp;a&nbsp;security&nbsp;restriction&nbsp;that<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;prevents&nbsp;scripting&nbsp;across&nbsp;frames&nbsp;that&nbsp;loads&nbsp;documents&nbsp;from&nbsp;different&nbsp;internet&nbsp;domains.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IWebBrowser2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;spBrws&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;HtmlWindowToHtmlWebBrowser(spWindow);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(spBrws&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLDocument2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Get&nbsp;the&nbsp;document&nbsp;object&nbsp;from&nbsp;the&nbsp;IWebBrowser2&nbsp;object.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IDispatch</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spDisp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hRes&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spBrws</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">get_Document(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">spDisp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spDocument&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spDisp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;spDocument;<br>}<br><br><br></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;Converts&nbsp;a&nbsp;IHTMLWindow2&nbsp;object&nbsp;to&nbsp;a&nbsp;IWebBrowser2.&nbsp;Returns&nbsp;NULL&nbsp;in&nbsp;case&nbsp;of&nbsp;failure.</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IWebBrowser2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;HtmlWindowToHtmlWebBrowser(CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IHTMLWindow2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spWindow)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ATLASSERT(spWindow&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;NULL);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IServiceProvider</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;spServiceProvider&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spWindow;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(spServiceProvider&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IWebBrowser2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IWebBrowser2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;spWebBrws;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HRESULT&nbsp;hRes&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;spServiceProvider</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">QueryService(IID_IWebBrowserApp,&nbsp;IID_IWebBrowser2,&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">**</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">spWebBrws);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(hRes&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;S_OK)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;CComQIPtr</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">IWebBrowser2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;spWebBrws;<br>}</span></div>
<br><br>附: <br>IE(控件/接口)中主要有4个部分, Browser,&nbsp;Document, Frame/IFrame, Element , 其对应接口分别是 <br>Browser&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;IWebBrowser2<br>Document&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;IHTMLDocument2<br>Frame/IFrame-&nbsp;&nbsp;&nbsp;&nbsp;IHTMLWindow2<br>Element&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;&nbsp;&nbsp;&nbsp;IHTMLElement<br>可以通过下面方法互相获取 <br>browser&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; document&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IWebBrowser2::get_Document<br>document&nbsp;&nbsp;&nbsp;&nbsp; -&gt; frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IHTMLDocument2::get_parentWindow<br>frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; document&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IHTMLWindow2::get_document<br>frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; parent frame&nbsp;&nbsp;&nbsp; IHTMLWindow2::get_parent<br>frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; children frames IHTMLWindow2::get_frames<br>element&nbsp;&nbsp;&nbsp;&nbsp; -&gt; Frame&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IHTMLElement-&gt;QI(IHTMLFrameBase2) -&gt; IHTMLFrameBase2-&gt;get_contentWindow -&gt; IHTMLWindow2 <br><br>ref: <br><a href="http://topic.csdn.net/t/20020722/20/894158.html">在多Frame的网页中怎么取出各个Frame的IHTMLDocument2的接口！急用.(高分)</a><br>在文章 <a href="http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html">When IHTMLWindow2::get_document returns E_ACCESSDENIED</a> 解决了iframe 跨域访问的问题 <br><br>
<img src ="http://www.cppblog.com/bigsml/aggbug/57548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-07-30 19:17 <a href="http://www.cppblog.com/bigsml/archive/2008/07/30/57548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++ 的预处理变量,宏 和 预定义宏</title><link>http://www.cppblog.com/bigsml/archive/2008/06/06/52363.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Fri, 06 Jun 2008 06:10:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/06/06/52363.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/52363.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/06/06/52363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/52363.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/52363.html</trackback:ping><description><![CDATA[<p>== 预处理指令(Preprocessor Directives) ==</p>
<p><br>== 预处理操作符(Preprocessor Operators) ==<br>Stringizing operator (#) <br>Causes the corresponding actual argument to be enclosed in double quotation marks <br>将参数变成字符串 : #x -&gt; "x" </p>
<p>Charizing operator (#@)<br>Causes the corresponding argument to be enclosed in single quotation marks and to be treated as a character (Microsoft Specific) <br>将参数变成字符变量 : #x -&gt; 'x' </p>
<p>Token-pasting operator (##) <br>Allows tokens used as actual arguments to be concatenated to form other tokens <br>将参数和前面的符号结合 : token##x -&gt; tokenx</p>
<p><br>== 预定义宏(Predefined Macros) ==</p>
<p>__FILE__<br>__LINE__</p>
<p>#define LINE1(x) #x<br>#define LINE(x) LINE1(x)<br>#define TODO(msg)&nbsp;&nbsp; message ( __FILE__ "(" LINE(__LINE__)&nbsp; "): [TODO] " #msg )<br>#define NOTE(msg)&nbsp;&nbsp; message ( __FILE__ "(" LINE(__LINE__)&nbsp; "): [NOTE] " #msg )<br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/52363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-06-06 14:10 <a href="http://www.cppblog.com/bigsml/archive/2008/06/06/52363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz 自定义浏览器控件 </title><link>http://www.cppblog.com/bigsml/archive/2008/04/18/47547.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Fri, 18 Apr 2008 14:29:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/04/18/47547.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/47547.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/04/18/47547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/47547.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/47547.html</trackback:ping><description><![CDATA[<p>同自动化浏览器（<a title=http://blog.joycode.com/jiangsheng/archive/2005/10/20/65489.aspx href="http://blog.joycode.com/jiangsheng/archive/2005/10/20/65489.aspx"><font color=#000080><u>http://blog.joycode.com/jiangsheng/archive/2005/10/20/65489.aspx</u></font></a>）相比，自动化浏览器控件(WebBrowser Control) 在应用程序中更加常用。从Outlook的预览窗格到Maxthon这样的基于IE引擎的浏览器，从无界面的HTML分析器到Norton Antivirusd的主界面，浏览器控件在众多领域被用作各种各样的用途。这也使得有必要根据具体的用户需求自定义浏览器控件的行为。</p>
<h1>在应用程序中加入浏览器控件</h1>
<p>集成浏览器控件的最简单的方法是找一个支持ActiveX的集成开发环境，在工具箱中加入Microsoft Web Browser这个控件，往表单上拖一个这个控件就可以完成工作。你甚至可以用集成开发环境添加ActiveX的事件处理函数。如果要直接导入ActiveX的话，建议使用mehrcpp的vbMHWB控件（<a href="http://www.codeproject.com/atl/vbmhwb.asp"><font color=#000080><u>http://www.codeproject.com/atl/vbmhwb.asp</u></font></a>）。这个控件在浏览器控件的基础上进行了扩展，暴露了很多底层接口。</p>
<p>通常导入ActiveX就可以满足大部分需求&nbsp; ，但是有些类库中也集成了浏览器控件，并且提供了更多的功能，例如MFC的CHTMLView和CDHtmlDialog，ATL的HTML Control，以及.Net 2.0中的Windows.Forms.WebBrowser。如果使用Visual C++来进行非托管编程，那么建议使用MFC或者ATL的封装类，或者使用vbMHWB控件。托管编程中当然首选Windows.Forms.WebBrowser。除非这些类的BUG影响到了应用程序的开发，否则建议使用这些功能更加强大的封装类。</p>
<p>在使用浏览器控件及其封装类的时候要注意一些已知问题</p>
<ul>
    <li>最后一个包含浏览器的窗口关闭时会话信息可能会丢失（<a href="http://support.microsoft.com/kb/311072"><u><font color=#0000ff>http://support.microsoft.com/kb/311072</font></u></a>）
    <li>MFC6.0版本的CHTMLView中一些方法没有释放获得的BSTR字符串，造成内存泄漏（<a href="http://support.microsoft.com/kb/241750"><u><font color=#0000ff>http://support.microsoft.com/kb/241750</font></u></a>）。
    <li>MFC6.0版本的CHTMLView缺少WS_CLIPCHILDREN风格，使得其中的浏览器控件重画不正常（<a href="http://support.microsoft.com/kb/220021"><u><font color=#0000ff>http://support.microsoft.com/kb/220021</font></u></a>）
    <li>Windows.Forms.WebBrowser的WebBrowserSite类不能通过重载来自定义其行为（<a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115198"><u><font color=#0000ff>https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115198</font></u></a>） </li>
</ul>
<h1>常见任务</h1>
<p>在集成浏览器控件之后，可以完成基本的网页浏览，但是对于不同的任务，也需要进一步的处理，例如设置控件的属性、为控件添加事件处理、操作HTML文档等等。</p>
<h2>修改浏览器控件的属性 </h2>
<p>这在集成开发环境中可以很容易地设置，也可以自己实现容器来设置，但是CHTMLView这样的封装类没有这个选项（<a href="http://support.microsoft.com/kb/197921"><u><font color=#0000ff>http://support.microsoft.com/kb/197921</font></u></a>）。</p>
<ul>
    <li>链接目标解析。对于用浏览器控件来做浏览器的场合来说，需要将浏览器的RegisterAsBrowser属性设置为true。这使得Internet Explorer在解析HTML链接的target属性指定的目标窗口时可以找到这个窗口。
    <li>禁用拖放。对于使用浏览器控件来做预览窗格的场合来说，需要将浏览器的RegisterAsDropTarget属性设置为false。这使得窗口不接受拖进来的文件和链接。
    <li>禁用消息框。对于用浏览器控件来做HTML分析器的场合来说，有时需要屏蔽脚本产生的消息框以避免阻塞程序运行。这可以通过设置浏览器的Silent属性来实现，或者实现IDocHostShowUI::ShowMessage。 </li>
</ul>
<h2>捕获浏览器控件的事件 </h2>
<p>集成开发环境中可以也很容易地添加浏览器的事件处理函数。比较常用的事件包括</p>
<ul>
    <li>NewWindow2或者NewWindow3事件。默认情况下，浏览器控件中创建的新窗口会是一个Internet Explorer的窗口。这通常不是预期的行为，对于浏览器程序来说更是这样。需要处理浏览器的NewWindow2或者NewWindow3（在Windows XP SP2或者Windows 2003 SP1之后可用）事件来让新的浏览器窗口在应用程序提供的窗口中运行。
    <li>WindowClosing事件。浏览器控件需要处理WindowClosing事件来在浏览器控件被脚本关闭时关闭浏览器控件的宿主窗口（<a href="http://support.microsoft.com/kb/253219"><u><font color=#0000ff>http://support.microsoft.com/kb/253219</font></u></a>）。
    <li>BeforeNavigate2事件。可以在自己的网页中加入自定义的协议，之后在BeforeNavigate2事件中扫描URL来进行网页和应用程序之间的交互（<a href="http://www.microsoft.com/msj/0100/c/c0100.aspx"><u><font color=#0000ff>http://www.microsoft.com/msj/0100/c/c0100.aspx</font></u></a>）。当然，自定义的网络协议也可以用Asynchronous Pluggable Protocol来处理(参见<a href="http://support.microsoft.com/kb/303740"><u><font color=#0000ff>http://support.microsoft.com/kb/303740</font></u></a>)，vbMHWB控件就实现了这个功能。但是更加常用的是在弹出广告过滤器程序中用BeforeNavigate2来判断在NewWindow2事件中创建的窗口是否需要关闭。 </li>
</ul>
<h2>操作MSHTML文档</h2>
<p>通常HTML分析和浏览器自动化程序都需要分析网页的结构，找到需要操作的元素。这需要对网页的结构进行分析，找到目标元素的标识方法。 一些常用的操作包括： </p>
<ul>
    <li>设置HTML元素的属性，例如html、style、value等等。注意有些属性是只读的，甚至是程序无法访问的（例如input元素在类型为文件时其value属性不可访问）。
    <li>分析网页的结构来保存网页数据，例如拆取Web 页一文介绍的方案（<a href="http://www.microsoft.com/china/msdn/Archives/workshop/scrape.asp"><u><font color=#0000ff>http://www.microsoft.com/china/msdn/Archives/workshop/scrape.asp</font></u></a>）
    <li>处理HTML元素的事件。这需要分析浏览器控件中的MSHTML文档对象，定位被操作的元素，以及在元素的连接点上挂接自定义的事件处理程序(<a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/tutorials/sink.asp"><u><font color=#0000ff>http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/tutorials/sink.asp</font></u></a>)。
    <li>添加/删除HTML元素。注意设置有时设置outHtml属性并不能正确创建元素（<a href="http://support.microsoft.com/kb/185140"><u><font color=#0000ff>http://support.microsoft.com/kb/185140</font></u></a>），一个的方法是用HTMLDocument对象的CreateElememt方法。
    <li>调用HTML元素的方法，这和在脚本中操作HTML类似。可操作的元素/接口可以参考Interfaces and Scripting Objects（<a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp"><u><font color=#0000ff>http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp</font></u></a>），操作方法可以参考Introduction to Dynamic HTML（<a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp"><u><font color=#0000ff>http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/mshtml/reference/ifaces/interface.asp</font></u></a>）
    <li>以上的功能都可以通过直接在网页中加入脚本实现（<a href="http://support.microsoft.com/kb/185128"><u><font color=#0000ff>http://support.microsoft.com/kb/185128</font></u></a>），而且脚本也可以通过应用程序实现的扩展接口来和应用程序本身交互。另外，脚本还可以被用来自定义一些事件，例如在需要重载自定义的ShowModalDialog的时候就可以用IDispatchEx给window对象添加一个属性，其值为一个自定义的ShowModalDialog函数(<a href="http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_thread/thread/e5eeb4a9111b16af/4bc2709aeb2bb444?lnk=raot"><u><font color=#0000ff>http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_thread/thread/e5eeb4a9111b16af/4bc2709aeb2bb444?lnk=raot</font></u></a>)，也可以用加入脚本的办法来捕获网页中的错误（<a href="http://support.microsoft.com/kb/317024"><u><font color=#0000ff>http://support.microsoft.com/kb/317024</font></u></a>）。 </li>
</ul>
<p>&nbsp;在页面包含框架的时候，可能需要跨框架访问HTML文档。可以通过查询框架元素所支持的IWebBrowser2接口或者IHTMLWindow2接口来访问框架中的文档（<a href="http://support.microsoft.com/kb/196340"><u><font color=#0000ff>http://support.microsoft.com/kb/196340</font></u></a>），但是也有可能因为安全设置而无法访问(<a href="http://support.microsoft.com/kb/167796"><u><font color=#0000ff>http://support.microsoft.com/kb/167796</font></u></a>)。</p>
<p>在浏览器控件中显示其它类型的文档时，可以用IWebBrowser2的document属性来访问ActiveX文档，例如在显示Microsoft Word时，IWebBrowser2的document属性就是Word的文档对象，在显示文件夹的时候，IWebBrowser2的document属性就是文件夹对象等等。</p>
<h2>扩展浏览器的宿主 </h2>
<p>浏览器控件在创建时会查询ActiveX容器的IOleClientSite的实现的如下接口：<strong>IDocHostUIHandler</strong>, <strong>IDocHostUIHandler2</strong> and <strong>IDocHostShowUI</strong>。</p>
<p>虽然在无法自定义ActiveX容器的情况下可以用ICustomDoc::SetUIHandler来挂接IDocHostUIHandler到浏览器控件，但是这样也会造成内存泄漏（<a href="http://support.microsoft.com/kb/893629"><u><font color=#0000ff>http://support.microsoft.com/kb/893629</font></u></a>）。一些类库，例如MFC、ATL和.Net类库都实现了IDocHostUIHandler接口。</p>
<p>除了专门用于浏览器用途的程序之外，通常都需要自定义浏览器控件的上下文菜单。这需要实现IDocHostUIHandler::ShowContextMenu。通常的实现包括完全禁用上下文菜单、完全替换上下文菜单、以及修改部分上下文菜单。经常被从上下文菜单中移除的菜单项包含查看源代码、刷新和属性。一种替代的方案是在容器中过滤右键消息（<a href="http://support.microsoft.com/kb/231578"><u><font color=#0000ff>http://support.microsoft.com/kb/231578</font></u></a>）。</p>
<p>与浏览器相比，一些Internet Explorer的宿主功能在浏览器控件中并不是默认启用。在某些场合，默认启用的宿主功能可能并非预期。这时需要实现IDocHostUIHandler::GetHostInfo。可以通过实现IDocHostUIHandler::GetHostInfo来自定义的功能包括： </p>
<ul>
    <li>自动完成功能。对于用浏览器控件来做浏览器的场合来说，这个功能是有必要启用的。启用的方法是设置DOCHOSTUIFLAG_ENABLE_FORMS_AUTOCOMPLETE位
    <li>如果浏览器中的链接网址包含非ASCII的字符，那么需要实现IDocHostUIHandler::GetHostInfo，并且在返回的DOCHOSTUIINFO结构中设置dwFlags成员的DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8位。这使得网址会在发送之前用UTF-8编码。
    <li>3D边框、滚动条，禁用文字选择功能和禁用页面上的脚本。
    <li>对于使用浏览器控件来做HTML编辑器的场合来说，有时需要修改默认的页面样式。这都需要实现IDocHostUIHandler::GetHostInfo（<a href="http://support.microsoft.com/kb/328803"><u><font color=#0000ff>http://support.microsoft.com/kb/328803</font></u></a>）。注意在有些版本的IE中IDocHostUIHandler::GetHostInfo只在MSHTML被初始化的时候被调用，所以如果你需要在MSHTML被初始化之后使你的修改生效，你需要浏览到一个Word之类的非HTML Active document文档，之后再浏览回来。 </li>
</ul>
<p>在使用浏览器控件来做数据录入界面的场合，需要更改浏览器控件默认的Tab键处理使得用户可以使用Tab键切换到容器中的其他控件。这需要实现IDocHostUIHandler::TranslateAccelerator来自定义浏览器控件的快捷键处理。对于MFC这样用消息钩子来做消息预处理的可自定义容器来说，也可以用PreTranslateMessage来过滤F5键盘消息，而不是实现IDocHostUIHandler::TranslateAccelerator。 </p>
<p>在脚本中调用应用程序对浏览器控件的扩展，这需要实现IDocHostUIHandler::GetExternal。使用.Net的WebBrowser控件的话设置ObjectForScripting属性就可以了。</p>
<p>对于用浏览器控件来做HTML分析器的场合来说，有时需要屏蔽脚本产生的消息框。这需要实现IDocHostShowUI::ShowMessage，或者设置浏览器的Silent属性。</p>
<p>另外，浏览器也会查询IOleClientSite来获得其它的服务信息，例如</p>
<ul>
    <li>IOleCommandTarget，查询控件的容器是否提供替代的命令处理，见拙作Hook DHTML Commands一文（<a href="http://blog.joycode.com/jiangsheng/archive/2005/07/09/58754.aspx"><u><font color=#0000ff>http://blog.joycode.com/jiangsheng/archive/2005/07/09/58754.aspx</font></u></a>）
    <li>IServiceProvider。此接口被用于查询用户对如下接口的实现：
    <ul>
        <li>IInternetSecurityManager ，用户可实现此接口来自定义浏览器控件的安全相关选项（<a href="http://msdn.microsoft.com/workshop/security/szone/overview/impl_secmanager.asp"><u><font color=#0000ff>http://msdn.microsoft.com/workshop/security/szone/overview/impl_secmanager.asp</font></u></a>）
        <li>IDownloadMamanger ，用户可实现此接口来自定义浏览器控件的下载过程
        <li>IAuthenticate，用户可实现此接口来自定义一些登录界面（<a href="http://support.microsoft.com/kb/329802"><u><font color=#0000ff>http://support.microsoft.com/kb/329802</font></u></a>）
        <li>INewWindowManager，用户可实现此接口来重载Windows XP SP2和Windows 2003 SP1中新增的弹出窗口管理器的行为 </li>
    </ul>
    </li>
</ul>
<h2>其他控制 </h2>
<p>对于用浏览器控件来做HTML分析器的场合来说，有时需要禁用浏览器的脚本、ActiveX或者图片下载。这可以通过在容器中实现IDispatch，处理DISPID_AMBIENT_DLCONTROL来做到（<a href="http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/Overview.asp"><u><font color=#0000ff>http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/Overview.asp</font></u></a>）。</p>
<p>看来离线浏览的控制并不能用这种方法来控制（<a href="http://support.microsoft.com/kb/247336"><u><font color=#0000ff>http://support.microsoft.com/kb/247336</font></u></a>）。不过你可以自己编写一个HTTP层传递 BINDF_OFFLINEOPERATION标志 （<a href="http://groups-beta.google.com/group/microsoft.public.inetsdk.programming.mshtml_hosting/msg/76bf4910a289d4b3"><u><font color=#0000ff>http://groups-beta.google.com/group/microsoft.public.inetsdk.programming.mshtml_hosting/msg/76bf4910a289d4b3</font></u></a>）</p>
<p>在浏览器控件中java小程序可能不能正常运行，如果使用Sun JVM1.4之后的版本，可以用SetEnvironmentVariable 来设置JAVA_PLUGIN_WEBCONTROL_ENABLE为1来启用Sun JVM。</p>
<p>默认情况下在页面载入时会有点击声。屏蔽点击声的一个方法是在程序运行时修改注册表键（<a href="http://support.microsoft.com/kb/201901"><u><font color=#0000ff>http://support.microsoft.com/kb/201901</font></u></a>），另一个方法是将浏览器控件隐藏，在调用Navigate2之后再显示，但是这也需要锁定控件的更新区域（LockWindowUpdate）以避免闪烁。在IE7中，也可以调用 <a href="http://msdn.microsoft.com/workshop/security/szone/reference/functions/cointernetsetfeatureenabled.asp"><u><font color=#0000ff>CoInternetSetFeatureEnabled</font></u></a>函数，传递FEATURE_DISABLE_NAVIGATION_SOUNDS来禁用浏览时的声音。</p>
<p>在需要使用代理服务器时，有可能需要在应用程序中使用非默认的代理服务器设置。这可以通过调用UrlMkSetSessionOption来实现。<br><br><strong>Overriding IInternetSecurityManager in a CComControl class</strong><br>CAxWindow implements IObjectWithSite interface (get it with QueryHost<br>method). Call SetSite passing your implementation of IServiceProvider.<br>At this point, AxWin will forward all QueryService calls from hosted<br>WebBrowser to your implementation.<br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/47547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-04-18 22:29 <a href="http://www.cppblog.com/bigsml/archive/2008/04/18/47547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ie 攻击监测</title><link>http://www.cppblog.com/bigsml/archive/2008/04/18/47528.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Fri, 18 Apr 2008 11:49:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/04/18/47528.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/47528.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/04/18/47528.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/47528.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/47528.html</trackback:ping><description><![CDATA[<p>对ie 的攻击分好几类, 有修改主页, 弹出窗口, 恶意插件, 网页木马等. 其中一些是利用了ie 的脚本的自带功能, 而另外一些要对ie 实施攻击后才能做到, 主要手段有利用第三方软件漏洞, ie 堆喷射等, 文章 [ [JavaScript中的堆风水]|[ http://www.team509.com/download/Heap%20Feng%20Shui%20in%20JavaScript_en_cn.htm ] ] 对堆喷射进行了介绍, 主要是利用覆盖函数返回地址或者对象的虚函数表来执行shellcode, 主要涉及到ie &amp; 系统的内存管理. <br>一般shellcode 基本只完成攻击动作, 具体的对系统的后续攻击肯定离不了下载执行 exe 文件等动作, 并且在攻击ie 也会有各种症状, 可以根据这些基本实现恶意代码. </p>
<p>1. 根据ie 症状<br>当ie 访问恶意页面的遭受攻击时, 其重要表现是<br>a. 内存使用<br>b. cpu 使用率<br>所以实时监测这些参数可以基本判断是否有攻击</p>
<p><br>2. 根据行为<br>shellcode 如果被执行, 那么肯定会进行木马下载执行等步骤. 一般纯shellcode 里面的内容不会很多, 所以不可能完成很多复杂的攻击. <br>win32 创建进程的API调用串是: <br>WinExec/ShellExecuteA/CreateProcessA-&gt;CreateProcessInternalA-&gt;CreateProcessInternalW-&gt;ZwCreateProcessEx<br>或<br>CreateProcessW-&gt;CreateProcessInternalW-&gt;ZwCreateProcessEx</p>
<p>win32 要执行下载的API 主要是wsock32.dll 的 <br>recv , recvfrom </p>
<p>所以对上述API 进行拦截, 一般可以检测到是否有ie 是否被攻击, 但是这个只能在攻击成功后, shellcode 执行后才能被检测到 </p>
<p>3. <br>拦截一些操作注册表, 创建窗口等API , 可以做到防止被修改主页, 弹出窗口等 </p>
<p>&nbsp;</p>
<p>利用ms 的Detours 可以很容易的实现对系统 API 的hook <br><a href="http://blog.csdn.net/hu0406/archive/2008/03/05/2150358.aspx">http://blog.csdn.net/hu0406/archive/2008/03/05/2150358.aspx</a><br><a href="http://blog.csdn.net/hu0406/archive/2008/03/05/2150351.aspx">http://blog.csdn.net/hu0406/archive/2008/03/05/2150351.aspx</a><br><a href="http://www.moon-soft.com/doc/2288.htm">http://www.moon-soft.com/doc/2288.htm</a><br><a href="http://blog.csdn.net/dedodong/archive/2006/10/07/1323925.aspx">http://blog.csdn.net/dedodong/archive/2006/10/07/1323925.aspx</a></p>
<p>[ [JavaScript中的堆风水]|[ <a href="http://www.team509.com/download/Heap%20Feng%20Shui%20in%20JavaScript_en_cn.htm">http://www.team509.com/download/Heap%20Feng%20Shui%20in%20JavaScript_en_cn.htm</a> ] ] ie 堆喷射 </p>
<p>[ [也聊inline-hook]|[ <a href="http://blog.tom.com/tigerkings941220/article/9211.html">http://blog.tom.com/tigerkings941220/article/9211.html</a> ] ] 介绍了 进程自身保护(通过拦截LoadLibraryW)和IE漏洞防护(通过拦截CreateProcessInternalW)</p>
<p>[ [maxthon2(遨游2) mxsafe.dll对网页木马的防护以及绕过]|[ <a href="http://hi.baidu.com/54nop/blog/item/b52cff6e713964d980cb4a9e.html">http://hi.baidu.com/54nop/blog/item/b52cff6e713964d980cb4a9e.html</a>&nbsp;]&nbsp;] 讨论了maxthon2 防止网页木马的策略( 拦截 ZwCreateProcessEx/ZwCreateProcess, ZwWriteVirtualMemory, LoadLibraryExW, CreateProcessInternalW )以及对抗策略, 其实这个只是hook &amp; unhook 的游戏了.. </p>
<p>[ [小议PE病毒技术]|[ http://blog.vckbase.com/windowssky/archive/2007/04/17.html ] ] 介绍了 pe 病毒 &amp; win32 进程加载内部</p>
<p>[ [360安全卫士程序员志愿者]|[ <a href="http://blog.csdn.net/dedodong/archive/2006/10/07/1323925.aspx">http://blog.csdn.net/dedodong/archive/2006/10/07/1323925.aspx</a> ] ] 通过拦截 NtCreateProcessEx/NtCreateProcess 实现了"""编写一个程序，在此程序中运行a.exe，并使得a.exe认为是由explorer.exe运行它的"""<br><br>[ [阻击恶意软件--清除和保护你的网站的小技巧]|[ <a href="http://www.googlechinawebmaster.com/labels/badware.html">http://www.googlechinawebmaster.com/labels/badware.html</a>&nbsp;] ] google 上的对恶意软件(badware) 的介绍 <br><br>[ [StopBadware Blog]|[ <a href="http://blogs.stopbadware.org/articles/2007/11">http://blogs.stopbadware.org/articles/2007/11</a>&nbsp;] ]<br></p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/bigsml/aggbug/47528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-04-18 19:49 <a href="http://www.cppblog.com/bigsml/archive/2008/04/18/47528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows Winnet 实现HTTP 文件断点续传下载</title><link>http://www.cppblog.com/bigsml/archive/2008/04/17/47449.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Thu, 17 Apr 2008 15:01:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/04/17/47449.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/47449.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/04/17/47449.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/47449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/47449.html</trackback:ping><description><![CDATA[<p>1. MFC 下载文件</p>
<p>有2种方法: <br>a)<br>创建CInternetSession 对象 -&gt; 调用 CInternetSession::OpenURL 该函数解析URL，然后打开与URL指定的服务器连接，同时返回一个只读的CInternetFile对象 -&gt; CInternetFile::Read 读取文件 -&gt; 析构CInternetSession </p>
<p>b) <br>创建CInternetSession 对象 -&gt; 调用 CInternetSession::GetHttpConnection<br>返回CHttpConnection 对象 -&gt; 调用CHttpConnection::OpenRequest 创建一个CHttpFile对象 -&gt; CHttpFile::SendRequest 发送连接请求 -&gt; CHttpFile::QueryInfo 获取HTTP 信息(比如文件大小, ETAG等) | CInternetFile::Read 读取文件 -&gt;&nbsp; 析构CInternetSession </p>
<p>在上述过程中, 如果出现错误会抛出 CInternetException 异常 <br>另外在打开链接前, 可以进行如下设置<br>CInternetSession::SetOption&nbsp;&nbsp;&nbsp;&nbsp;读取或设置 InternetQuery 选项 (如超时或重试次数）<br>CInternetSession::EnableStatusCallback&nbsp;设置回调函数监视session状态<br>CHttpFile::AddRequestHeaders&nbsp;&nbsp;&nbsp;设置HTTP 请求头(需要在CHttpFile::SendRequest 前调用)</p>
<p><br>2. 实现断点续传<br>断点续传其实是通过在HTTP 请求头中设置要下载的文件区间来实现, 一个典型的HTTP 请求头是 </p>
<p>&nbsp; GEThttp://class/download.microtool.de:80/somedata.exe&nbsp; <br>&nbsp; Host:download.microtool.de<br>&nbsp; Accept:*/*<br>&nbsp; Pragma:no-cache<br>&nbsp; Cache-Control:no-cache<br>&nbsp; Referer:http://class/download.microtool.de/<br>&nbsp; User-Agent:Mozilla/4.04[en](Win95;I;Nav)<br>&nbsp; Range:bytes=554554-<br>&nbsp;<br>注意最后一行：Range:bytes=554554-，格式为:Range: bytes=起始位置 - 终止位置，也就是说，我们可以通过设置Http请求头的设置起始结束位置，来获取HTTP文件的某一部分。 </p>
<p><br>3. Win32 WinInet API 实现 <br>和MFC 的函数对应, 执行下载操作大致需要的函数有：</p>
<p>InternetOpen是最先调用的函数，它返回HINTERNET句柄，习惯定义为hSession，即会话句柄, 相当于CInternetSession<br>InternetConnect使用hSession句柄，返回的是http连接句柄，定义为hConnect, 相当于 CInternetSession::GetHttpConnection<br>HttpOpenRequest使用hConnect句柄，返回的句柄是http请求句柄，定义为hRequest, 相当于 CHttpConnection::OpenRequest<br>HttpSendRequest(相当于 CHttpFile::SendRequest)、HttpQueryInfo、InternetSetFilePointer和InternetReadFile都使用HttpOpenRequest返回的句柄，即hRequest。</p>
<p>CInternetSession::OpenURL 相当于实现了 InternetConnect &amp; HttpOpenRequest &amp; HttpSendRequest 3个函数 </p>
<p>当这几个句柄不再使用时，应该用函数InternetCloseHandle把它关闭，以释放其占用的资源。 </p>
<p><br><a href="http://www.vckbase.com/document/viewdoc/?id=545" target=_blank>用WinInet开发Internet客户端应用指南（一）</a>&nbsp;&nbsp;<a href="http://www.vckbase.com/document/viewdoc/?id=545">http://www.vckbase.com/document/viewdoc/?id=545</a><br><a href="http://www.vckbase.com/document/viewdoc/?id=546" target=_blank>用WinInet开发Internet客户端应用指南（二）</a>&nbsp;<a href="http://www.vckbase.com/document/viewdoc/?id=546">http://www.vckbase.com/document/viewdoc/?id=546</a><br><a href="http://www.vckbase.com/document/viewdoc/?id=1693" target=_blank>使用 CInternetSession 封装多线程 http 文件下载</a>&nbsp;<a href="http://www.vckbase.com/document/viewdoc/?id=1693">http://www.vckbase.com/document/viewdoc/?id=1693</a><br><a href="http://sunyan331.spaces.live.com/blog/cns!89B9F8BF2575E281!947.entry" target=_blank>Http下载的断点续传</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://sunyan331.spaces.live.com/blog/cns!89B9F8BF2575E281!947.entry">http://sunyan331.spaces.live.com/blog/cns!89B9F8BF2575E281!947.entry</a><br><a href="http://www.cnitblog.com/wangk/archive/2007/05/22/5942.html" target=_blank>HTTP服务器上断点下载文件(里面有很不错的源码)</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.cnitblog.com/wangk/archive/2007/05/22/5942.html">http://www.cnitblog.com/wangk/archive/2007/05/22/5942.html</a><br><a href="http://www.bbbh.org/20060427/2620/" target=_blank>编写断点续传和多线程下载(有源码)&nbsp;</a>&nbsp;&nbsp;<a href="http://www.bbbh.org/20060427/2620/">http://www.bbbh.org/20060427/2620/</a><br><a href="http://www.clevercomponents.com/articles/article015/resuming.asp" target=_blank>WinInet: implementing resuming feature</a>&nbsp;&nbsp;<a href="http://www.clevercomponents.com/articles/article015/resuming.asp">http://www.clevercomponents.com/articles/article015/resuming.asp</a><br>(很详细的一个代码解释)<a href="http://www.codeproject.com/KB/IP/getwebfile.aspx" target=_blank>Retrieving a file via. HTTP</a>&nbsp; <a href="http://www.codeproject.com/KB/IP/getwebfile.aspx">http://www.codeproject.com/KB/IP/getwebfile.aspx</a>&nbsp;<br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/47449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-04-17 23:01 <a href="http://www.cppblog.com/bigsml/archive/2008/04/17/47449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MSNP协议的通信过程[En]  </title><link>http://www.cppblog.com/bigsml/archive/2008/03/23/45178.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Sun, 23 Mar 2008 05:13:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/03/23/45178.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/45178.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/03/23/45178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/45178.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/45178.html</trackback:ping><description><![CDATA[<p><font face="Arial, Helvetica, sans-serif" color=#000000>You have been using MSN for quite some time wondering how it works. Well You need not look any further. This article will not just tell you how MSN works but will also tell you how to make your own version of MSN messenger. You can download a sample application from here <a href="http://www.venkydude.com/articles/msnclone.zip"><font color=#000080><u>MSN Clone</u></font></a> .Let's get ready to rumble!!!!</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>We can split up the working of MSN messenger into 2 phases</font></p>
<ul>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Authentication Phase</font></p>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Instant Messaging Phase</font></p>
    </li>
</ul>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The Authentication Phase involves logging into the MSN messenger server and also (friends) list retrieval in this case.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The Instant Messaging Phase involves sending/accepting requests for an Instant Messaging session and also sending/receiving messages.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The MSN messenger protocol is an ASCII based protocol. In other words the commands are in pure English !!!.The first phase involves connecting to an MSN messenger server .In this case we shall connect to the server 64.4.13.58 on port 1863(MSN messenger works through port 1863).</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Once the connection is done we need to start the log in process. The first stage in this phase is the versioning stage. In this stage the client (in this case your app) lists/sends the versions that it can support to the server and waits for the server to respond.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>VER 0 MSNP7 MSNP6 MSNP5 MSNP4 CVRO</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>In the MSN messenger protocol a "trial id" is sent along with every command. The trial id starts from 0 and is incremented every time the server responds successfully to the client's commands.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server responds like this</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>VER 0 MSNP7 MSNP6 MSNP5 MSNP4</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The Client and the server have agreed on a version in which they will communicate.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Next the client sends a request to the server asking it for the name of the security package it supports for authentication.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>INF 1</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Unlike Yahoo, Rediff and a few other Messengers MSN does not actually send the password as it is.It encrypts the password while sending it ensuring that your password will not be leaked out easily if somebody monitors your port.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server responds with this </font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>INF 1 MD5</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Here MD5 is the name of the security package which the server currently supports.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Next the client sends the userid to the server</font></p>
<p align=left><font color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 2&nbsp; MD5&nbsp; I&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#118;&#101;&#110;&#107;&#121;&#95;&#100;&#117;&#100;&#101;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;"><font color=#000080><u>venky_dude@hotmail.com</u></font></a></strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Here the server does a check whether it contains all the relevant details about the user for authentication .If it does not then it sends the following reply</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>&nbsp;XFR 2&nbsp; NS 64.4.13.55:1863&nbsp; 0</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>What the server says is that the client should connect to the Notification Server(NS) on 64.4.13.55 on port 1863. We close the current connection and repeat the&nbsp; steps while being connected to the new server i.e&nbsp; 64.4.13.55</font></p>
<ul>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>(client)&nbsp;&nbsp; VER 3 MSNP7 MSNP6 MSNP5 MSNP4 CVRO</strong></font> </p>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>(server) VER 3 MSNP7 MSNP6 MSNP5 MSNP4&nbsp;</strong></font> </p>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>(client)&nbsp;&nbsp; INF&nbsp; 4</strong></font> </p>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>(server) INF&nbsp; 4&nbsp; MD5</strong></font> </p>
    <li>
    <p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>(client)&nbsp; USR&nbsp; 5&nbsp; MD5 I venky_dude@hotmail.com</strong></font> </p>
    </li>
</ul>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Now the server to which we are connected to has the relevant information about the user trying to log in. The server replies this way</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 5&nbsp; MD5&nbsp; S 989048851.1851137130</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>&nbsp;The string which is sent by the server is the " MD5 Hash". It is a hash generated by the server and is used in the authentication process. The client then has to send the password which is encrypted using the <a href="http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html"><font color=#000080><u>MD5</u></font></a> algorithm.In effect the client has to send the unique <a href="http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html"><font color=#000080><u>MD5</u></font></a> equivalent of the <a href="http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html"><font color=#000080><u>MD5</u></font></a> hash i.e 989048851.1851137130 in this case and the password combined .i.e. <a href="http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html"><font color=#000080><u>MD5</u></font></a> equivalent of (hash+pass). In this case it turns out to be 3b7926d277068ec49576a0c40598ff21.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 6 MD5 S 3b7926d277068ec49576a0c40598ff21</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>If the password is right then the server replies with this</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 6 OK venky_dude@hotmail.com venkat</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Here the last word is the nickname/name by which the user is known.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>In the new version of the protocol (MSNP7) the server sends additional data like some general information about the user and a authentication code something similar to a cookie which can be used for various other functions.</font></p>
<p align=left>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MSG Hotmai Hotmail 362<br>MIME-Version: 1.0<br>Content-Type: text/x-msmsgspro file; charset=UT<br>LoginTime: 1011252477<br>EmailEnabled: 1<br>MemberIdHigh: 84736<br>MemberIdLow: - 1434729391<br>lang _preference: 103<br>preferredEmai l: venky_dude@hotmail.com<br>country: IN<br>PostalCode:<br>Gender: M<br>Kid:0<br>Age: 22<br>sid: 517<br>kv: 2<br>MSPAuth: 2AAAAAAAADU0p4uxxxJtDJozJSlUTS0i7YpwnC9PUHRv56YKxxxCTWmg$$</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Now we are logged into the server but our status is still offline. We need to change our status to online in order to send and receive messages. The client does this in the following way</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>CHG 7 NLN</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server replies with friends who are online and in various states.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>CHG 7 NLN<br><br>ILN 7 NLN btxxxe@hotmail.com nick<br>ILN 7 AWY wmpyxxx@msn.com mike<br>ILN 7 BSY tehpxxpxx@hotmail.com yeaxxx</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MSG Hotmail Hotmail 223<br>MIME-Version: 1.0<br>Content-Type: text/x-msmsgsinitialemailnotification; charset=UTF-8</strong></font></p>
<p><font color=#000000><strong>Inbox-Unread: 293<br>Folders-Unread: 0<br>Inbox-URL: /cgi-bin/HoTMaiL<br>Folders-URL: /cgi-bin/folders<br>Post-URL: http://www.hotmail.com</strong></font></p>
<p align=left>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The next command to be sent to the server pertains to the version of the client currently being used.The client send to the server it's version number and also information about the machine like the OS and the build.</font></p>
<p align=left><font color=#000000><strong><font face="Arial, Helvetica, sans-serif"><strong>CVR 8 0x0409 win 4.10 i386 MSMSGS 4.5.0127 MSMSGS</strong></font></strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>Here 0x409 win 4.10 i386 specifies that the client is running win98 on a intel microprocessor, and MSMSGS 4.5.0127 MSMSGS here specifies the version and build no of msmsgs.exe (basically the version no of MSN messenger).</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server responds with the url to download the latest version and some other info</font></p>
<p align=left><font color=#000000><strong><font face="Arial, Helvetica, sans-serif"><strong>CVR 8 4.5.0127 4.5.0127 1.0.0863 http://download.microsoft.com/download/msnmessenger/install/4.5/win98me/en-us/mmssetup.exe http://messenger.microsoft.com</strong></font></strong></font></p>
<p align=left>&nbsp;</p>
<p align=left><font color=#000000 size=3>It is not necesarry to send the CVR command, the messenger protocol will function properly regardless of this command being sent</font></p>
<p align=left>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>To get a list of people who are in our friends list we may send this command</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>LST 9 RL</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>On sending this command the server will reply by sending the reverse list .The reverse list is basically a list of users who can see you when you are online and send you a message.You could alternatively also request for the forward list by sending <strong>LST 9 FL</strong> .The forward list contains a list of all users whom the user has added to his/her list.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server responds this way</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>LST 9 RL 69 1 19 venky_dude@hotmail.com venkat<br>LST 9 RL 69 2 19 puxxxxx@hotmail.com PUJA<br>LST 9 RL 69 3 19 vancxxxxx@hotmail.com ramachandran<br>LST 9 RL 69 4 19 moxxxxx@hotmail.com chandramouli<br>LST 9 RL 69 5 19 v_n_xxxxx@hotmail.com Narayanaswamy<br>LST 9 RL 69 6 19 dexxxxx@hotmail.com Venkatesh<br>LST 9 RL 69 7 19 lousydxxxxx@hotmail.com deepika%20kalyani%20Vairam&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; LST 9 RL 69 8 19 hexxxxxr@hotmail.com Hetchar%20Ramachandran<br>LST 9 RL 69 9 19 ambxxxxx@hotmail.com Aiyer<br>LST 9 RL 69 10 19 suxxx@hotmail.com Ganesh<br>LST 9 RL 69 11 19 deexxxxx@hotmail.com Deepak<br>LST 9 RL 69 12 19 anilxxxxx@hotmail.com anil<br>LST 9 RL 69 13 19 dixxxxx@hotmail.com &lt;Diamond&gt;<br>LST 9 RL 69 14 19 nvxxxx@hotmail.com giri<br>LST 9 RL 69 15 19 shxxx@hotmail.com Hari<br>LST 9 RL 69 16 19 radhikashuxxxxx@hotmail.com radhika<br>LST 9 RL 69 17 19 eskaxxxxx@hotmail.com kannan<br>LST 9 RL 69 18 19 shaxxxxx@hotmail.com Shankar<br>LST 9 RL 69 19 19 puneetagarxxxxx@hotmail.com puneet</strong></font></p>
<p align=left><font color=#000000></font>&nbsp;</p>
<p align=left><font color=#000000></font>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>*Every time a friend comes online the server(NS) sends us the following command</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>NLN 10NLN deaxxxx@hotmail.com Venkatesh</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>and when the friend goes offline the server sends us this</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>FLN 10 FLN deaxxxx@hotmail.com </strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>With the MSNP7 protocol msn has introduced a new challenege authentication mechanism. The MSN server sends t a challenge key which the user has to authenticate succesfully in order for the session to continue.</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>CHL 0 20881396011366812350</strong></font></p>
<p align=left>&nbsp;</p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The client has to send the md5 equivalent of this string which is formed by appending this hash with the string "Q1P7W2E4J9R8U3S5".So the final string which will be sent to the server will be the md5 equivalent of <strong><u>20881396011366812350Q1P7W2E4J9R8U3S5 </u></strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>i.e MD5string(20881396011366812350Q1P7W2E4J9R8U3S5 )</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>So the client response would be something like this</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>QRY 18 msmsgs@msnmsgr.com 32<br>0212eaad0876afb8505859ca75d21a78</strong></font></p>
<p align=left><font color=#000000>Here 18 is the trial id .Replace it by the appropriate trial id in your program .</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>The server will respond in the following way if the authentication is right</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000><strong>QRY 18</strong></font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>We have successfully logged into the MSN Messenger server. The Instant Messaging phase is next.</font></p>
<br><br><br><br><br></font>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Instant Messaging in MSN Messenger is session based . The people in between whom the conversation is going to take place have to be in a session mode. We cannot send/receive messages unless we start a chat session with a user.&nbsp;</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>There are basically two methods in&nbsp; which a user can be in a chat session&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;&nbsp;&nbsp;&nbsp;</font></p>
<ul>
    <li><font face="Arial, Helvetica, sans-serif" color=#000000>User sends a chat session request to another user</font>
    <li><font face="Arial, Helvetica, sans-serif" color=#000000>User receives a chat session request from another user</font> </li>
</ul>
<p><font color=#000000></font>&nbsp;</p>
<p align=center><font face="Arial, Helvetica, sans-serif" color=#000000 size=4>User sends a chat session request</font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>The client(user) sends a command to the server asking it for the address of the SwitchBoard(SB) server. All instant messaging conversation take place via the switchboard server.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>XFR 9 SB</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>The server(SB) replies back with the ip address of the switchboard server(SB),the port on which to connect and a CKI hash. CKI is a security package and the client has to use the hash to connect to the switchboard server.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>&nbsp;XFR 9 SB 64.4.13.88:1863 CKI 989487642.2070896604&nbsp;</strong>&nbsp;&nbsp;&nbsp;&nbsp;</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Now we have to make <u>another&nbsp; new connection</u> this time to the switchboard server. Our previous connection to the MSN messenger server&nbsp; must be kept as it is. If we lose connection with that server we would log out.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>After we have connected to the switchboard server(SB) we send the following command to the switchboard server.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 1 venky_dude@hotmail.com&nbsp; 989487642.2070896604</strong>&nbsp;&nbsp;</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>If the CKI hash sent by us is right the server(SB) responds back with this</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>USR 1 OK venky_dude@hotmail.com venkat</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>After this has been done the user has to "Call" the other user to the chat session. This is done by sending the following command.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>CAL 2 deadxxx@hotmail.com&nbsp;</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>The server replies back with the a session id which it will pass on to the other user</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>CAL 2 RINGING 11717653</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>When the other user replies and is ready for a chat the server(SB) sends us this command</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>JOI deadlee@hotmail.com Venkatesh</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>This indicates that the other user has joined in the conversation and we are now ready to send and receive messages.</font></p>
<p><font color=#000000></font>&nbsp;</p>
<p align=center><font face="Arial, Helvetica, sans-serif" color=#000000 size=4>User receives a chat session request</font></p>
<p align=left><font face="Arial, Helvetica, sans-serif" color=#000000>When we are being invited to a chat session by a user the server(NS) send us the following message.</font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>RNG 11742066 64.4.13.74:1863 CKI 989495494.750408580 deaxxxx@hotmail.com Venkatesh</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Here the server(NS) sends us the session id ,the ip address of the SwitchBoard server to connect to,the port on which to connect to ,the CKI hash and the user trying to start a conversation with us.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Now we have to make <u>another&nbsp; new connection</u> this time to the switchboard server. Our previous connection to the MSN messenger server&nbsp; must be kept as it is. If we loose connection with that server we would log out.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>We&nbsp; connect to the switchboard server and send the following command</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>ANS 1 venky_dude@hotmail.com 989495494.750408580 11742066</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Here we send our login name ,the CKI hash that was sent to us and the session Id that was sent to us</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>The server responds back with&nbsp;</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>IRO 1 1 1 deaxxxx@hotmail.com Venkatesh</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>and</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>ANS 1 OK</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>We are now ready to send and receive messages.</font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Before sending/receiving messages let us see how the message is constructed.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>When we are sending a message we build the header information&nbsp; in the following way</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MIME-Version: 1.0<br>Content-Type: text/plain; charset=UTF-8<br>X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>While sending a message we send it this way</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MSG&nbsp; 2&nbsp; N 137&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;&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;&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; MIME-Version: 1.0<br>Content-Type: text/plain; charset=UTF-8<br>X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22<br><br>hello</strong></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Here 2 is the trial id which has to incremented each time we send a message. 137 is the total length of the message i.e length of the header and length of the actual message that we are sending in this case it is 'hello'.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>&nbsp;While receiving the message it is more or less similar</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>Here is an example of a message received</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MSG deaxxxx@hotmail.com Venkatesh 137<br>MIME-Version: 1.0<br>Content-Type: text/plain; charset=UTF-8<br>X-MMS-IM-Format: FN=Microsoft%20Sans%20Serif; EF=; CO=0; CS=0; PF=22<br><br>hello</strong></font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>When the other user is typing a message we receive the foll message</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000><strong>MSG deaxxxx@hotmail.com Venkatesh 100<br>MIME-Version: 1.0<br>Content-Type: text/x-msmsgscontrol<br>TypingUser: deaxxxx@hotmail.com</strong></font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>I guess now u guys are well on your way to make your own version of&nbsp; MSN messenger.Post your doubts/comments/message in the Forumn .Do visit my projects page for some cool vb &amp; c++ codes</font></p>
<p><font color=#000000 size=4>&nbsp;I'll keep adding to the protocol ,will try to put in addition functions like add/remove users ,rename user id,file transfer and voice chat, so keep checking back</font></p>
<p><font color=#000000></font>&nbsp;</p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>References:</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>You could take a look at these sites for more information</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>This is the original protocol published by microsoft.</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#0000ff><a href="http://www.tlsecurity.net/Textware/Misc/draft-movva-msn-messenger-protocol-00.txt"><u>http://www.tlsecurity.net/Textware/Misc/draft-movva-msn-messenger-protocol-00.txt</u></a></font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#000000>This is the MD5 homepage where u can find programs/codes for doing the MD5 encryption</font></p>
<p><font face="Arial, Helvetica, sans-serif" color=#0000ff><a href="http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html"><u>http://userpages.umbc.edu/~mabzug1/cs/md5/md5.html</u></a></font></p>
<br>MSNP10协议分析 01.登录 [by progsoft] <br><a href="http://blog.csdn.net/progsoft/archive/2004/08/24/82938.aspx">http://blog.csdn.net/progsoft/archive/2004/08/24/82938.aspx</a><br><br>MSN协议中文释义(Zz)<br><a href="http://blog.csdn.net/fanccYang/archive/2005/03/16/321198.aspx">http://blog.csdn.net/fanccYang/archive/2005/03/16/321198.aspx</a><br><br>MSN Protocol Version 8<br><a href="http://msnpiki.msnfanatic.com/index.php/Main_Page">http://msnpiki.msnfanatic.com/index.php/Main_Page</a><br>介绍了MSNP 的整个协议 &amp; 服务器 Notification Server (NS)&nbsp; &amp; Switchboard (SB)&nbsp; 的功能 <br><br>MSN Messenger Protocol Version 9<br><a href="http://zoronax.bot2k3.net/">http://zoronax.bot2k3.net/</a><br>很详细的介绍, 里面还有原始包例子 <br><br>MSN Messenger Protocol<br><a href="http://www.hypothetic.org/docs/msn/client/invitation_types.php">http://www.hypothetic.org/docs/msn/client/invitation_types.php</a><br>MSNP 的详细命令介绍<br><br>Reverse-engineering MSN Messenger's Video Conversation Formats[Ramiro Polla] <br><a href="http://www.libing.net.cn/read.php/1031.htm">http://www.libing.net.cn/read.php/1031.htm</a><br><br>
<img src ="http://www.cppblog.com/bigsml/aggbug/45178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-03-23 13:13 <a href="http://www.cppblog.com/bigsml/archive/2008/03/23/45178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IE 异步可插入协议扩展 </title><link>http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Sat, 22 Mar 2008 16:38:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/45145.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/45145.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/45145.html</trackback:ping><description><![CDATA[<p>可插入协议扩展（Asynchronous Pluggable Protocols）主要基于异步的URL Moniker技术。 IE的URL Moniker在urlmon.dll 动态库中实现的， 有两种处理机制：<br><strong>1. 根据URL 协议调用外部程序处理</strong><br>比如telnet: or news: or mailto:，当访问这些url的时候会打开相应的程序来处理。<br>比如要添加note:协议(Registering an Application to a URL Protocol), 则只要修改注册表<br>[HKEY_CLASSES_ROOT]<br>&nbsp;&nbsp;&nbsp; [note]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Default) = "<a href="http://www.cppblog.com/bigsml/admin/Note">URL:Note</a> Protocol"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL Protocol = ""<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [DefaultIcon]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Default) = "notepad.exe"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [shell]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [open]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [command]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Default) = "c:\windows\notepad.exe %1"<br>在IE 中输入 note://xxx.txt 的时候会自动用notepad 打开xxx.txt 文件</p>
<p><strong>2. 根据URL 协议调用类对象来处理<br></strong>可以根据URL 协议或者MIME type 注册不同的处理对象<br>有两种方式：<br>a) 通过在注册表将URL 协议与COM 对象关联<br>主要在注册表中的 <br>HKEY_CLASSES_ROOT\PROTOCOLS\Handler&nbsp;# URL 协议<br>HKEY_CLASSES_ROOT\PROTOCOLS\Filter&nbsp;# Mime Filter</p>
<p>b) 通过临时注册类对象将URL 协议与其关联<br>// 注册<br>CComPtr&lt;IInternetSession&gt; spSession;<br>CComPtr&lt;IClassFactory&gt;&nbsp;&nbsp; spCFHTTP;<br>HRESULT hr = CoInternetGetSession(0, &amp;spSession, 0);<br>hr = FilterFactory::CreateInstance(CLSID_HttpProtocol, &amp;spCFHTTP);<br>hr = spSession-&gt;RegisterNameSpace(spCFHTTP, CLSID_NULL, L"http", 0, 0, 0);</p>
<p>// 反注册<br>spSession-&gt;UnregisterNameSpace(spCFHTTP, L"http");</p>
<p>&nbsp;</p>
<p>3. FilterFactory 的实现可以参考<br><a href="http://www.codeguru.com/cpp/com-tech/atl/misc/article.php/c37/">Asynchronous Pluggable Protocol Implementation with ATL</a><br><a href="http://www.codeguru.com/cpp/com-tech/atl/misc/article.php/c37/">http://www.codeguru.com/cpp/com-tech/atl/misc/article.php/c37/</a><br><br><a href="http://blog.csdn.net/111222/archive/2002/02/09/7255.aspx">Internet Explorer下载文件的终极过滤</a><br><a href="http://blog.csdn.net/111222/archive/2002/02/09/7255.aspx">http://blog.csdn.net/111222/archive/2002/02/09/7255.aspx</a></p>
<p><a href="http://blog.csdn.net/lion_wing/archive/2006/06/27/839134.aspx">通过Mime filter技术对网页源码进行过滤（监视下载文件）</a><br><a href="http://blog.csdn.net/lion_wing/archive/2006/06/27/839134.aspx">http://blog.csdn.net/lion_wing/archive/2006/06/27/839134.aspx</a><br><br><a href="http://blog.csdn.net/lion_wing/articles/534716.aspx">HTML代码过滤技术</a><br><a href="http://blog.csdn.net/lion_wing/articles/534716.aspx">http://blog.csdn.net/lion_wing/articles/534716.aspx</a></p>
<p>About Asynchronous Pluggable Protocols （MSDN）<br><br><a href="http://blog.csdn.net/CathyEagle/archive/2005/12/12/550698.aspx">Internet Explorer 编程简述（九）在自己的浏览器中嵌入Google工具条</a><br><a href="http://blog.csdn.net/CathyEagle/archive/2005/12/12/550698.aspx">http://blog.csdn.net/CathyEagle/archive/2005/12/12/550698.aspx</a><br><br><a href="http://topic.csdn.net/t/20061214/12/5230161.html">放1000分，高手进来动手试试：如何提取AJAX里的HTML内容？<br></a><a href="http://topic.csdn.net/t/20061214/12/5230161.html">http://topic.csdn.net/t/20061214/12/5230161.html</a><br>这里主要通过监视IE 的下载从而保存Google Map 的地图数据文件.&nbsp; 通过监视http &amp; text/html &amp; application/javascript 的内容来获取图片文件URL 和 信息.. :)<br><br><br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/45145.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-03-23 00:38 <a href="http://www.cppblog.com/bigsml/archive/2008/03/23/45145.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>const和指针组合的变化</title><link>http://www.cppblog.com/bigsml/archive/2008/02/27/43326.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Wed, 27 Feb 2008 03:03:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/02/27/43326.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/43326.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/02/27/43326.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/43326.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/43326.html</trackback:ping><description><![CDATA[<p>a. char const* p&nbsp; 　　　*p不能变，p能变，不需要初始化<br>b. const char* p&nbsp; 　　　同a<br>c. char* const p&nbsp; 　　　*p能变，p不能变，需要初始化<br>d. const char* const p&nbsp; *p不能变，p不能变，需要初始化<br>d. const char const* p&nbsp; *p不能变，p能变，不需要初始化<br>e. const char const* const p&nbsp; 错误<br>f. char const* const p&nbsp; 同d<a href="http://www.cppblog.com/bigsml/admin/EditPosts.aspx?opt=1"></a></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/43326.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-02-27 11:03 <a href="http://www.cppblog.com/bigsml/archive/2008/02/27/43326.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何禁用Tree Control 的节点</title><link>http://www.cppblog.com/bigsml/archive/2008/01/14/41146.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Mon, 14 Jan 2008 11:16:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2008/01/14/41146.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/41146.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2008/01/14/41146.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/41146.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/41146.html</trackback:ping><description><![CDATA[<p>Tree Control : how to disable an item </p>
<p>Tree Control 不支持节点的禁用, 但是可以通过自绘实现, 主要如下:<br><br>1. 标记节点是否禁用. 可以用 SetItemData &amp; GetItemData 来设置&amp;获取节点数据<br><br>2. 在禁用的节点上, 要过滤一些对节点操作, 如expanding, selecting, drag &amp; drop 等.<br>TVN_SELCHANGING &nbsp;节点选中改变时<br>TVN_ITEMEXPANDING&nbsp;节点展开时<br>TVN_BEGINDRAG&nbsp;&nbsp;节点开始被拖拉<br>TVN_BEGINLABELEDIT&nbsp;节点被编辑</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Preventing&nbsp;selection:&nbsp;(handle&nbsp;TVN_SELCHANGING)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CYourDialog::OnSelchangingTree(NMHDR</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pNMHDR,&nbsp;LRESULT</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pResult)&nbsp;<br>{<br>&nbsp;&nbsp;NM_TREEVIEW</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pNMTreeView&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(NM_TREEVIEW</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;pNMHDR;<br>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(((CItemStruct&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;m_tree.GetItemData(pNMTreeView</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">iNewItem))</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">m_bDisabled)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pResult&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;设置&nbsp;*pResult=1&nbsp;表示TVN_SELCHANGING&nbsp;这个操作不能继续</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pResult&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br>}</span></div>
<p><br>3. 对禁用节点进行自画, 用图标,颜色将禁用节点和其他节点进行区分 <br>a) 直接在 WM_PAINT 中进行自画 (或对Tree Control的绘图结果进行修改)<br>&nbsp;可以参考: <a href="http://www.vckbase.com/document/viewdoc/?id=355" target=_blank>如何在树型控件中使用背景位图</a></p>
<p>b) 相应 WM_OWERDRAW 事件 <br>&nbsp;可以参考: <a href="http://www.vckbase.com/document/viewdoc/?id=504" target=_blank>Outlook风格的单列使用不同的颜色显示新邮件数</a></p>
<p><br>参考:<br><a href="http://www.codeguru.com/forum/showthread.php?t=231234" target=_blank>MFC Tree Control: How to disable an item?</a>&nbsp;<br><a href="http://www.codeguru.com/Cpp/controls/treeview/misc-advanced/article.php/c633" target=_blank>Setting color and font attribute for individual items</a><br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/41146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2008-01-14 19:16 <a href="http://www.cppblog.com/bigsml/archive/2008/01/14/41146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM 类工厂有必要存在吗</title><link>http://www.cppblog.com/bigsml/archive/2007/11/18/36907.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Sun, 18 Nov 2007 14:53:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2007/11/18/36907.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/36907.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2007/11/18/36907.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/36907.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/36907.html</trackback:ping><description><![CDATA[<p>1. IClassFactory 的用途</p>
<p>在 <a href="http://www.80diy.com/home/20041120/19/3572410.html">http://www.80diy.com/home/20041120/19/3572410.html</a> 看到几段关于COM 的类厂的话, </p>
<p>"""<br>类厂用来抽象组件的create过程，客户不需要知道组件的详细情况，也不需要知道类厂的详细情况，只要知道CoCreateInstance可以创建组件即可。而CoCreateInstance内部调用DllGetClassObject来生成该组件的类厂，由于类厂有组件的作者撰写，所以对组件类可谓知根知底，由类厂来生成组件完全行得通，这样客户和组件就进一步划分，客户只能查询该组件是否支持某借口，而对组件的其他情况一无所知，这样的划分可以使组件和客户间的耦合更小。<br>"""</p>
<p>"""<br>组件如果将某接口的全部方法都实现了，就称该组件支持某接口，com并没有规定组件和接口之间是虚函数继承的关系，只是在c++中以这种方法来实现最好而已。&nbsp;&nbsp; <br>IClassFactory说穿了就是专门构造组件的类，这样做是为了抽象，因为客户没有必要知道组件是什么，如果由客户直接构造组件，客户势必要知道组件的信息，com就失去了它的意义了，所以，规定了一个类厂（支持IClassFactory接口），每个组件的类厂都很清楚并且也只清楚该组件的信息，而客户只需要调用com库函数CoCreateInstance就可以了。&nbsp;&nbsp; <br>下面是流程图：&nbsp;&nbsp; <br>&nbsp; CoCreateInstance -&gt; CoGetClassObject -&gt; DllGetClassObject -&gt; new ClassFactory -&gt; IClassFactory::CreateInstance() -&gt; new Component<br>"""</p>
<p>并且在 <a href="http://www.codeproject.com/com/comintro2.asp">http://www.codeproject.com/com/comintro2.asp</a> 也看到几段话</p>
<p>"""<br>每次实现组件对象类的时候，都要写一个旁类负责创建第一个组件对象类的实例。这个旁类就叫这个组件对象类的类工厂（class factory），其唯一目的是创建COM对象。之所以要一个类工厂，是因为语言无关的缘故。COM本身并不创建对象，因为它不是独立于语言的也不是独立于实现的。 <br>当某个客户端想要创建一个COM对象时，COM库就从COM服务器请求类工厂。然后类工厂创建COM对象并将它返回客户端。它们的通讯机制由函数DllGetClassObject()来提供。<br>"""</p>
<p>在&lt;COM 技术内幕&gt; 中, 对类厂的引入也有描述. <br>主要是:<br>a. 在面向对象系统中, 对象创建是非常重要的, 因为要使用它必须先创建它. 所以尽可能灵活的创建对象(component)<br>b. 在CoCreateInstance 创建对象过程是: 传给一共CLSID, 然后创建成相应组件, 并返回所请求的指针. 其弊端在于无法提供给客户一种控制对象创建过程的方法. (问题关键不在初始化, 而是控制创建对象过程)<br>c. IClassFactory2 成批的调用接口. </p>
<p><br>2. <br>参考CoCreateInstance 的实现过程: <br>CoCreateInstance -&gt; CoGetClassObject -[系统|组件代码]-&gt; DllGetClassObject -&gt; new ClassFactory -&gt; IClassFactory::CreateInstance() -&gt; new Component</p>
<p>因为 DllGetClassObject -&gt; new ClassFactory -&gt; IClassFactory::CreateInstance() -&gt; new Component 都是组件所来实现的, 而系统调用 CoCreateInstance 所提供的参数, 和通过自己使用IClassFactory 来创建Component 的参数是没有变化的, 所以如果省略 ClassFactory 应该也可以. </p>
<p>CoCreateInstance -&gt; CoGetClassObject -[系统|组件代码]-&gt; DllGetClassObject -&gt; new Component </p>
<p>DllGetClassObject 完全可以完成&lt;COM 技术内幕说的&gt; a. 灵活创建对象, b. 控制创建过程, c. IClassFactory2 , 而且这样子的实现也与语言无关.&nbsp; <br>所以感觉没有必要一定要用到IClassFactory 这个接口</p>
<p><br>3. <br>因此在实现的时候, 完全可以这样子的实现组件<br>CCoClass : public IA, public IB, public IClassFactory <br>{<br>......<br>}</p>
<p>DllGetClassObject()<br>{<br>new CCoClass<br>}</p>
<p>而不需要额外的用一个类单独的去实现IClassFactory . 好像ATL 默认的就是这么干的, 提供了一个CComCoClass&lt;CCoClass, &amp;CLSID_CCoClass)&nbsp; 实现类. </p>
<p>这个是我的对COM 的IClassFactory 的理解, 感觉没必要多一个这个东西. <br><br>不知道大家是如何看待这个东西的:) </p>
<p><br>&nbsp;</p>
<img src ="http://www.cppblog.com/bigsml/aggbug/36907.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2007-11-18 22:53 <a href="http://www.cppblog.com/bigsml/archive/2007/11/18/36907.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>窗口的子类化与超类化</title><link>http://www.cppblog.com/bigsml/archive/2007/08/24/30780.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Fri, 24 Aug 2007 10:58:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2007/08/24/30780.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/30780.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2007/08/24/30780.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/30780.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/30780.html</trackback:ping><description><![CDATA[<p>1. 子类化 <br><strong>改变一个已经存在的窗口实例的性质：消息处理与其他实例属性。</strong><br>在SDK编程范畴内，子类化就是改变一个窗口实例的窗口函数（通过GetWindowLong()和SetWindowLong()），子类化所要做的就是为某窗口实例编写新的窗口函数。其操作是在实例级别上进行的。<br>在MFC中子类化的情况有所不同：所有MFC窗口有相同的窗口函数，由该窗口函数根据窗口句柄查找窗口实例，在把消息映射到该窗口类（class）得消息处理函数上。为了利用MFC的消息映射机制，不宜改变窗口函数（名），MFC也把子类化封装在函数SubclassWindow（）中。但子类化的本质没有变：在实例级别影响窗口的消息及其处理。例：<br>Class&nbsp; B ：public A <br>{ <br>&nbsp; &#8230;&#8230;<br>}<br>A&nbsp; a; <br>B&nbsp; b; <br>HWND ha=a.GetSafeHwnd();<br>b.SubclassWindow(ha);&nbsp;#当然A 和B 不一定是继承关系。<br>注意：在被子类化的窗口销毁之前，必须执行窗口的反子类化： <br>b.UnSubclassWindow(); <br></p>
<p><br>2 超类化<br><strong>窗口超类化是在窗口类——WNDCLASS或WNDCLASSEX（非MFC类概念）级别进行的改变窗口类特征的</strong>。<br>使用过程：首先获得一个已存在的窗口类，然后设置窗口类，最后注册该窗口类。<br>例：<br>WNDCLASSEX&nbsp; wc; <br>wc.cbSize=sizeof(wc);&nbsp;//Windows用来进行版本检查的，与窗口特征无关 <br>GetClassInfoEx(hinst,&#8221;XXXXXX&#8221;,&amp;wc);<br>&nbsp;// hinst—定义窗口类XXXXXX的模块的句柄，如为系统定义的窗口类（如：EDIT、BUTTON）则hinst=NULL.。 <br>wc.lpszClassName = &#8220;YYYYYYY&#8221;;//必须改变窗口类的名字 <br>wc.hbrBackGround = CreateSolidBrush(RGB(0,0.0));//改变背景刷 <br>wc.lpfnWndProc = NewWndProc;//改变窗口函数 <br>&#8230;&#8230;<br>RegisterClassEx(&amp;wc);// 注册新窗口类 <br>//使用窗口类 <br>&#8230;&#8230;<br>::CreateWindow(_T(&#8220;YYYYYYYY&#8221;,&#8230;&#8230;)； </p>
<p>故超类化只能改变自己创建的窗口的特征，而不能用于由Windows创建的窗口（如对话框上的按钮就不能进行超类化） 。而子类化是实例级别上的，只要能获得窗口的实例，就可对其子类化，这是唯一的子类化对于超类化的优势。另外，凡是子类化可实现的，超类化都可实现，不过超类化用起来较麻烦。 </p>
<p><br>3. 总结</p>
<p>（0） 子类化修改窗口过程函数, &nbsp;超类化修改窗口类(新的窗口类名)<br>（1） 子类化是在窗口实例级别上的，超类化是在窗口类（WNDCLASS）级别上的。 <br>（2） 超类化可以完成比子类化更复杂的功能，在SDK范畴上，可以认为子类化是超类化的子集。 <br>（3） 子类化只能改变窗口创建后的性质，对于窗口创建期间无能为力(无法截获ON_CREATE 事件)，而超类化可以实现；超类化不能用于Windows创建的窗口，子类化可以。&nbsp;<br><br><br>4. 其他<br>在 <a href="http://blog.csdn.net/fmddlmyy/archive/2007/04/08/1556777.aspx" target=_blank>眼见为实(2)：介绍Windows的窗口、消息、子类化和超类化</a>&nbsp;这里有一个例子.. <br>可以得出结论<br>a) 子类化的classname 是不会变化的, 而超类化使用新注册classname<br>b) 子类化 &amp; 超类化 描述的是一个动作 和实现方法没什么关系..... 主要是子类化是SubclassWindow, SubclassDlgItem, 而超类化是RegisterClassEx(&amp;newwindowclass)<br>c) 感觉具体没有必要区分这些, 实现功能就行了, 呵呵 <br><br><br></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/30780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2007-08-24 18:58 <a href="http://www.cppblog.com/bigsml/archive/2007/08/24/30780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Some DirectShow Samples Break in Visual Studio 2005</title><link>http://www.cppblog.com/bigsml/archive/2007/06/26/26978.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Tue, 26 Jun 2007 03:07:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2007/06/26/26978.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/26978.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2007/06/26/26978.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/26978.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/26978.html</trackback:ping><description><![CDATA[<p>zt: <a href="http://blogs.msdn.com/mikewasson/archive/2005/05/23/some-directshow-samples-break-in-visual-studio-2005.aspx">http://blogs.msdn.com/mikewasson/archive/2005/05/23/some-directshow-samples-break-in-visual-studio-2005.aspx</a><br><br>DirectX 9.0 与 VS 2005 之间存在冲突,&nbsp;主要因为VS 2005 的语法比VC6 &amp; VS2003 更加严格, 所以一些DirectX 自带的代码需要更改以后才能编译通过.&nbsp;本来想自己改的, 不过在网上发现了有人已经做了这个:)<br><br><br>[Note: This post applies to the Platform SDK for Windows Server 2003 SP1 and&nbsp;Server 2003 R2. These issues were fixed in the Windows SDK for Vista.]&nbsp;&nbsp;</p>
<p>Some of the DirectShow samples break if you install&nbsp;Visual Studio 2005 Beta 2. Most of the errors that I found fall into three categories:</p>
<ul>
    <li>C4430: Missing type specifier.&nbsp;To conform with C++,&nbsp;undeclared types do not default to int. All types must be declared.&nbsp;Fix: Declare the type, or&nbsp;suppress the warning with the "/wd4430" flag.
    <li>C4996: '&nbsp;xxxx' was declared deprecated.&nbsp;You may be including&nbsp;an older&nbsp;version of strsafe.h from the DirectX SDK or the Platform SDK.&nbsp;You should include the version installed with Visual Studio.&nbsp;(But it's probably harmless to ignore this&nbsp;warning.)&nbsp;
    <li>C2065: 'xxx': undeclared identifier.&nbsp;To conform with C++,&nbsp;the scope of a variable declared inside a "for" loop is restricted to the loop.&nbsp;Fixes: (a) Move the declaration outside the for loop. (b) Redeclare the variable in multiple scopes, if you don't need it to persist outside the loop. (c) Set the /Zc:forScope flag. (You can find this under Project, Properties, Configuration Properties, C/C++, Language, Force Conformance In For Loop Scope. Set&nbsp;to "No".)</li>
</ul>
<p>Here are the specific fixes that I made. Warning: I have not thoroughly tested these, and I only tried them under the "Windows XP 32-bit Debug" environment in Platform SDK. You should use your own judgment before making any of these fixes.</p>
<ul>
    <li>BaseClasses\ctlutil.h (278)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<font face="Courier New"> <font color=#0000ff>(LONG) operator=(LONG);</font></font>
    <li>BaseClasses\wxdebug.cpp (564)<br>&nbsp;&nbsp;&nbsp; <font face="Courier New" color=#0000ff>static DWORD g_dwLastRefresh = 0;</font>
    <li>BaseClasses\winutil.cpp (2092)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp;</font><font face="Courier New" color=#0000ff>UINT Count;<br>&nbsp;&nbsp; for (Count = 0;Count &lt; Result;Count++) {</font>
    <li>&nbsp;BaseClasses\outputq.cpp (635)<br><font face="Courier New">&nbsp;&nbsp;&nbsp;</font><font face="Courier New" color=#0000ff>long iDone = 0;<br>&nbsp;&nbsp;&nbsp;for (iDone = 0;</font>
    <li>Capture\AmCap\amcap.cpp (691)<br>&nbsp;<font face="Courier New">&nbsp;&nbsp; <font color=#0000ff>for(int i = 0; i &lt; NUMELMS(gcap.rgpmAudioMenu); i++)</font></font>
    <li>Capture\AmCap\amcap (2795)<br><font face="Courier New" color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;<font color=#0000ff>for(int i = 0; i &lt; NUMELMS(gcap.rgpmAudioMenu); i++)</font></font>
    <li>DMODemo\dsutil.cpp (686)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; DWORD i = 0;<br>&nbsp;&nbsp;&nbsp; for( i=0; i&lt;m_dwNumBuffers; i++ )</font>
    <li>dmoimpl.h (622)&nbsp;&nbsp; [In the Platform SDK headers]<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; for (DWORD dw = 0; dw &lt; NUMBEROFOUTPUTS; dw++) {</font>
    <li>DMO\GargleDMO\MedParamBase\param.cpp (91)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; for (DWORD dwIndex = 0; dwIndex &lt; cParams; dwIndex++)</font>
    <li>DMO\GargleDMO\MedParamBase\param.cpp (309)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; CCurveItem *pCurve = NULL;<br>&nbsp;&nbsp;&nbsp; for (pCurve = pCurveHead; </font>
    <li>DMO\GargleDMO\gargle.cpp (145)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; for (DWORD i = 0; i &lt; cOutputStreams &amp;&amp; SUCCEEDED(hr); ++i)</font>
    <li>Filters\Dump\dump.cpp (426)<br><font color=#0000ff><font face="Courier New">&nbsp;&nbsp;&nbsp; for (int Loop = 0;Loop &lt; (DataLength % BYTES_PER_LINE);Loop++)</font> </font>
    <li>Filters\Gargle\gargle.cpp (212)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; static int m_nInstanceCount; // total instances</font>
    <li>Filters\RGBFilters\RateSource\ratesource.cpp (382)<br>&nbsp;<font face="Courier New" color=#0000ff>&nbsp;&nbsp; for( int y = 0 ; y &lt; DEFAULT_HEIGHT ; y++ )</font>
    <li>Filters\RGBFilters\RateSource\ratesource.cpp (387)<br>&nbsp;<font face="Courier New" color=#0000ff>&nbsp;&nbsp; for( int y = 0 ; y &lt; DEFAULT_WIDTH ; y++ )</font>
    <li>VMR\VMRXclBasic and VMR\Ticker: LNK1181: cannot open input file 'dxguid.lib'.&nbsp;This was an error in the makefile. Change to read:<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; DXLIB="$(DXSDK_DIR)\Lib\x86"</font>&nbsp; (currently says "x32")
    <li>VMR\VMRXcl and VMR\VMRMulti: C1083: Cannot open include file: 'd3dxmath.h': No such file or directory.&nbsp;This is an old DX header that is no longer included in DX or in Visual Studio. Unfortunately the only fix is to download an older version of the DirectX SDK.
    <li>VMR9\MultiVMR9\GamePlayer\character.cpp (383)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; DWORD i = 0;<br>&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; pMeshContainer-&gt;NumInfl; ++i)</font>
    <li>VMR9\MultiVMR9\DLL\MixerControl.h (28)<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; static const DWORD MultiVMR9Mixer_DefaultFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;</font>
    <li>VMR9\VMRAllocator: error LNK2019: unresolved external symbol "wchar_t * __stdcall _com_util::ConvertStringToBSTR(char const *)" (etc).&nbsp;&nbsp;Add this to the makefile:<br><font face="Courier New" color=#0000ff>&nbsp;&nbsp;&nbsp; LINK32_LIBS = \<br>&nbsp;&nbsp;&nbsp; <strong>comsuppw.lib \</strong><br>&nbsp;&nbsp;&nbsp; shell32.lib \</font></li>
</ul>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/bigsml/aggbug/26978.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2007-06-26 11:07 <a href="http://www.cppblog.com/bigsml/archive/2007/06/26/26978.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用IE 实现Web 页面截图</title><link>http://www.cppblog.com/bigsml/archive/2007/06/10/25983.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Sun, 10 Jun 2007 10:55:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2007/06/10/25983.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/25983.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2007/06/10/25983.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/25983.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/25983.html</trackback:ping><description><![CDATA[<p>1. 目的<br><br>&nbsp;&nbsp;&nbsp;在Codeproject 中看到有人做这个,&nbsp; 稍微做了下修改, 做成了命令行的, 使用方法是&nbsp;<br>&nbsp;&nbsp;&nbsp;iesnap.exe url filename<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用以抓取 URL 对于的Web, 并且将Web 的截图保存在Filename 中.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url : 要截图的网址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename: 截图保存文件名<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>2. 思路<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;主要使用WebBrowser Control 和 MSHTML 来完成. <br>&nbsp;a. 创建WebBrowser control <br>&nbsp;b. 从WebBrowser Control 获取 IWebBrowser2 接口, 用 IWebBrowser2::Navigate2 来访问URL<br>&nbsp;c. 获得IHTMLElementRender (WebBrowser -&gt; IHTMLDocument2 -&gt; IHTMLElement -&gt; IHTMLElementRender), 使用该接口的DrawToDC 来获取URL 对应的页面截图内容.<br>&nbsp;d. 用GDI 的 Image 来保存截图到Filename<br><br>3.&nbsp;<br>&nbsp;&nbsp;&nbsp;可以看看原文以得到更好的解答&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;我看的那个文章: <a href="http://www.codeproject.com/internet/htmlimagecapture.asp">Capture an HTML document as an image<br></a>&nbsp;&nbsp;&nbsp;另外一篇C# 的文章: <a href="http://www.codeproject.com/cs/media/IECapture.asp">Image Capture Whole Web Page using C#</a></p>
<p><br>4.&nbsp;问题<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;a. DocumentComplete 事件会在URL 对应页面的每个元素下载完毕的时候都会发生, 所以:( 还不知道哪个事件是整个页面下载完毕的事件:/ <br>&nbsp;b. 现在是通过MFC 来创建WebBrowser Control 的, 不知道怎么在Win32 Application 中创建这个控件.<br>&nbsp;c. 不知道如何得到整个页面的大小, 现在只能保存页面截图的一部分:(<br>&nbsp;&nbsp;&nbsp;这个已经知道怎么做了.&nbsp;<br>&nbsp;&nbsp;&nbsp;IHTMLElement2&nbsp;的 scrollWidth &amp; scrollHeight 加上 scrollLeft &amp; scrollTop&nbsp;来实现, 但是不知道为什么, put_scrollTop &amp; put_scrollLeft&nbsp;这些函数好像不对, 只能截获到一部分页面截图.:( 不知道为什么<br>&nbsp;&nbsp;&nbsp;<br></p>
<p><br>&nbsp;代码可以在这里下载: <a href="http://www.cppblog.com/Files/bigsml/iesnapshot.zip">http://www.cppblog.com/Files/bigsml/iesnapshot.zip</a></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/25983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2007-06-10 18:55 <a href="http://www.cppblog.com/bigsml/archive/2007/06/10/25983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>YC 浏览器</title><link>http://www.cppblog.com/bigsml/archive/2007/04/25/22808.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Wed, 25 Apr 2007 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2007/04/25/22808.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/22808.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2007/04/25/22808.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/22808.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/22808.html</trackback:ping><description><![CDATA[<p>这款浏览器,称之为Yang C/C++ Compiler &amp; Internet Browser或者YC编译型浏览器..<br><br>最开始是在程序员看到相关的文章的, 开始以为是在吹..但是今天用他的程序的时候, 感觉真的很nb..<br><br>"""<br>记者在杨晓兵处观摩了该产品的演示,发现它是由如下五个部分组成：HTML解析器；XML解析器（目前完成一部分）；javascript脚本解释器,C/C++脚本解释器；C/C++编译器；文本及二进制编辑器.其中最令人瞩目的功能,自然是他所内嵌的C/C++实时编译功能了,这样使得C/C++的运行效果看上去类似动态语言,它不仅使得HTML支持脚本化的标准C/C++语言,而且使得C/C++ 能够与象JacaScript这样的动态语言可以互相调用.杨晓兵说&#8220;这将是软件开发方式的革新.通过这个实时编译功能,每个软件可以同时分割成若干模块,相互之间可以独立运行.&#8221;该编译器,与主流的C/C++编译器相比,YC++在功能进行了一些删减和改良,比如去掉了标准C/C++的函数重载、运算符重载、模板等,而改良的方向,主要侧重增加与网页开发环境（HTML4.0、CSS2.JavaScript）的互相支持和调用.令人颇感意外的是,该产品包括编译器、HTML解析器等在内的五个模块的所有代码,都与由杨晓兵独自一个人用C语言开发完成,从未借鉴参考任何其他源代码.杨晓兵解释说主要是为了便于调试和控制.这是相当大的工作量,整整花了他六年时间.从演示的运行效果来看,这款由一人手工完成的作品,编译速度竟然比VC++还要快一些.据透露是源自其许多算法的优化,如专门为变量参数作了可供快速查找的字典表等.<br>"""<br><br><br>在用的时候, 发现整个浏览器没有使用一个Windows 控件, 所有的控件都是由用GDI 级来绘制成的... 包括菜单, 输入框, 按钮, 树形控件等等等<br><br>Orz... 一把<br><br>可以在这里下载试用, 解压缩3个压缩包就行了.<br><a href="http://www.cppblog.com/Files/bigsml/setyc.part01.rar">/Files/bigsml/setyc.part01.rar</a><br><a href="http://www.cppblog.com/Files/bigsml/setyc.part02.rar">/Files/bigsml/setyc.part02.rar</a><br><a href="http://www.cppblog.com/Files/bigsml/setyc.part03.rar">/Files/bigsml/setyc.part03.rar</a></p>
<img src ="http://www.cppblog.com/bigsml/aggbug/22808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2007-04-25 17:07 <a href="http://www.cppblog.com/bigsml/archive/2007/04/25/22808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用BoundsChecker检测内存泄漏 (zz) </title><link>http://www.cppblog.com/bigsml/archive/2006/10/19/13860.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Thu, 19 Oct 2006 05:45:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2006/10/19/13860.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/13860.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2006/10/19/13860.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/13860.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/13860.html</trackback:ping><description><![CDATA[　　BoundsChecker采用一种被称为 Code Injection的技术，来截获对分配内存和释放内存的函数的调用。简单地说，当你的程序开始运行时，BoundsChecker的DLL被自动载入进程的地址空间（这可以通过system-level的Hook实现），然后它会修改进程中对内存分配和释放的函数调用，让这些调用首先转入它的代码，然后再执行原来的代码。BoundsChecker在做这些动作的时，无须修改被调试程序的源代码或工程配置文件，这使得使用它非常的简便、直接。<br /><br />　　这里我们以malloc函数为例，截获其他的函数方法与此类似。<br /><br />　　需要被截获的函数可能在DLL中，也可能在程序的代码里。比如，如果静态连结C-Runtime Library，那么malloc函数的代码会被连结到程序里。为了截获住对这类函数的调用，BoundsChecker会动态修改这些函数的指令。<br /><br />　　以下两段汇编代码，一段没有BoundsChecker介入，另一段则有BoundsChecker的介入：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">126</span><span style="color: rgb(0, 0, 0);">: _CRTIMP </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> __cdecl malloc (<br /></span><span style="color: rgb(0, 0, 0);">127</span><span style="color: rgb(0, 0, 0);">: size_t nSize<br /></span><span style="color: rgb(0, 0, 0);">128</span><span style="color: rgb(0, 0, 0);">: )<br /></span><span style="color: rgb(0, 0, 0);">129</span><span style="color: rgb(0, 0, 0);">: {<br /><br />00403C10 push ebp<br />00403C11 mov ebp,esp<br /></span><span style="color: rgb(0, 0, 0);">130</span><span style="color: rgb(0, 0, 0);">: </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> _nh_malloc_dbg(nSize, _newmode, _NORMAL_BLOCK, NULL, </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);<br />00403C13 push </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);"><br />00403C15 push </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);"><br />00403C17 push </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />00403C19 mov eax,[__newmode (0042376c)]<br />00403C1E push eax<br />00403C1F mov ecx,dword ptr [nSize]<br />00403C22 push ecx<br />00403C23 call _nh_malloc_dbg (00403c80)<br />00403C28 add esp,14h<br /></span><span style="color: rgb(0, 0, 0);">131</span><span style="color: rgb(0, 0, 0);">: }</span></div>以下这一段代码有BoundsChecker介入：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">126</span><span style="color: rgb(0, 0, 0);">: _CRTIMP </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> __cdecl malloc (<br /></span><span style="color: rgb(0, 0, 0);">127</span><span style="color: rgb(0, 0, 0);">: size_t nSize<br /></span><span style="color: rgb(0, 0, 0);">128</span><span style="color: rgb(0, 0, 0);">: )<br /></span><span style="color: rgb(0, 0, 0);">129</span><span style="color: rgb(0, 0, 0);">: {<br /><br />00403C10 jmp 01F41EC8<br />00403C15 push </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);"><br />00403C17 push </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />00403C19 mov eax,[__newmode (0042376c)]<br />00403C1E push eax<br />00403C1F mov ecx,dword ptr [nSize]<br />00403C22 push ecx<br />00403C23 call _nh_malloc_dbg (00403c80)<br />00403C28 add esp,14h<br /></span><span style="color: rgb(0, 0, 0);">131</span><span style="color: rgb(0, 0, 0);">: }</span></div><br />　　当BoundsChecker介入后，函数malloc的前三条汇编指令被替换成一条jmp指令，原来的三条指令被搬到地址01F41EC8处了。当程序进入malloc后先jmp到01F41EC8，执行原来的三条指令，然后就是BoundsChecker的天下了。大致上它会先记录函数的返回地址（函数的返回地址在stack上，所以很容易修改），然后把返回地址指向属于BoundsChecker的代码，接着跳到malloc函数原来的指令，也就是在00403c15的地方。当malloc函数结束的时候，由于返回地址被修改，它会返回到BoundsChecker的代码中，此时BoundsChecker会记录由malloc分配的内存的指针，然后再跳转到到原来的返回地址去。<br /><br />　　如果内存分配/释放函数在DLL中，BoundsChecker则采用另一种方法来截获对这些函数的调用。BoundsChecker通过修改程序的DLL Import Table让table中的函数地址指向自己的地址，以达到截获的目的。<br /><br />　　截获住这些分配和释放函数，BoundsChecker就能记录被分配的内存或资源的生命周期。接下来的问题是如何与源代码相关，也就是说当BoundsChecker检测到内存泄漏，它如何报告这块内存块是哪段代码分配的。答案是调试信息（Debug Information）。当我们编译一个Debug版的程序时，编译器会把源代码和二进制代码之间的对应关系记录下来，放到一个单独的文件里(.pdb)或者直接连结进目标程序，通过直接读取调试信息就能得到分配某块内存的源代码在哪个文件，哪一行上。使用Code Injection和Debug Information，使BoundsChecker不但能记录呼叫分配函数的源代码的位置，而且还能记录分配时的Call Stack，以及Call Stack上的函数的源代码位置。这在使用像MFC这样的类库时非常有用，以下我用一个例子来说明：<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> ShowXItemMenu()<br />{<br />　…<br />　CMenu menu;<br /><br />　menu.CreatePopupMenu();<br />　</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">add menu items.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">　menu.TrackPropupMenu();<br />　…<br />}<br /><br /></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> ShowYItemMenu( )<br />{<br />　…<br />　CMenu menu;<br />　menu.CreatePopupMenu();<br />　</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">add menu items.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">　menu.TrackPropupMenu();<br />　menu.Detach();</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">this will cause HMENU leak</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">　…<br />}<br /><br />BOOL CMenu::CreatePopupMenu()<br />{<br />　…<br />　hMenu </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> CreatePopupMenu();<br />　…<br />}</span></div>当调用ShowYItemMenu()时，我们故意造成HMENU的泄漏。但是，对于BoundsChecker来说被泄漏的HMENU是在class CMenu::CreatePopupMenu()中分配的。假设的你的程序有许多地方使用了CMenu的CreatePopupMenu()函数，如CMenu::CreatePopupMenu()造成的，你依然无法确认问题的根结到底在哪里，在ShowXItemMenu()中还是在ShowYItemMenu()中，或者还有其它的地方也使用了CreatePopupMenu()？有了Call Stack的信息，问题就容易了。BoundsChecker会如下报告泄漏的HMENU的信息：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Function<br />File<br />Line<br /><br />CMenu::CreatePopupMenu<br />E:\</span><span style="color: rgb(0, 0, 0);">8168</span><span style="color: rgb(0, 0, 0);">\vc98\mfc\mfc\include\afxwin1.inl<br /></span><span style="color: rgb(0, 0, 0);">1009</span><span style="color: rgb(0, 0, 0);"><br /><br />ShowYItemMenu<br />E:\testmemleak\mytest.cpp<br /></span><span style="color: rgb(0, 0, 0);">100</span></div>　　<br />这里省略了其他的函数调用<br /><br />如此，我们很容易找到发生问题的函数是ShowYItemMenu()。当使用MFC之类的类库编程时，大部分的API调用都被封装在类库的class里，有了Call Stack信息，我们就可以非常容易的追踪到真正发生泄漏的代码。<br /><br />　　记录Call Stack信息会使程序的运行变得非常慢，因此默认情况下BoundsChecker不会记录Call Stack信息。可以按照以下的步骤打开记录Call Stack信息的选项开关：<br /><br />　　1. 打开菜单：BoundsChecker|Setting… <br /><br />　　2. 在Error Detection页中，在Error Detection Scheme的List中选择Custom<br /><br />　　3. 在Category的Combox中选择 Pointer and leak error check<br /><br />　　4. 钩上Report Call Stack复选框<br /><br />　　5. 点击Ok<br /><br />　　基于Code Injection，BoundsChecker还提供了API Parameter的校验功能，memory over run等功能。这些功能对于程序的开发都非常有益。由于这些内容不属于本文的主题，所以不在此详述了。<br /><br />　　尽管BoundsChecker的功能如此强大，但是面对隐式内存泄漏仍然显得苍白无力。所以接下来我们看看如何用Performance Monitor检测内存泄漏。<br /><br />　　使用Performance Monitor检测内存泄漏<br /><br />　　NT的内核在设计过程中已经加入了系统监视功能，比如CPU的使用率，内存的使用情况，I/O操作的频繁度等都作为一个个Counter，应用程序可以通过读取这些Counter了解整个系统的或者某个进程的运行状况。Performance Monitor就是这样一个应用程序。<br /><br />　　为了检测内存泄漏，我们一般可以监视Process对象的Handle Count，Virutal Bytes 和Working Set三个Counter。Handle Count记录了进程当前打开的HANDLE的个数，监视这个Counter有助于我们发现程序是否有Handle泄漏；Virtual Bytes记录了该进程当前在虚地址空间上使用的虚拟内存的大小，NT的内存分配采用了两步走的方法，首先，在虚地址空间上保留一段空间，这时操作系统并没有分配物理内存，只是保留了一段地址。然后，再提交这段空间，这时操作系统才会分配物理内存。所以，Virtual Bytes一般总大于程序的Working Set。监视Virutal Bytes可以帮助我们发现一些系统底层的问题; Working Set记录了操作系统为进程已提交的内存的总量，这个值和程序申请的内存总量存在密切的关系，如果程序存在内存的泄漏这个值会持续增加，但是Virtual Bytes却是跳跃式增加的。<br /><br />　　监视这些Counter可以让我们了解进程使用内存的情况，如果发生了泄漏，即使是隐式内存泄漏，这些Counter的值也会持续增加。但是，我们知道有问题却不知道哪里有问题，所以一般使用Performance Monitor来验证是否有内存泄漏，而使用BoundsChecker来找到和解决。<br /><br />　　当Performance Monitor显示有内存泄漏，而BoundsChecker却无法检测到，这时有两种可能：第一种，发生了偶发性内存泄漏。这时你要确保使用Performance Monitor和使用BoundsChecker时，程序的运行环境和操作方法是一致的。第二种，发生了隐式的内存泄漏。这时你要重新审查程序的设计，然后仔细研究Performance Monitor记录的Counter的值的变化图，分析其中的变化和程序运行逻辑的关系，找到一些可能的原因。这是一个痛苦的过程，充满了假设、猜想、验证、失败，但这也是一个积累经验的绝好机会。<br /><br />　　总结<br /><br />　　内存泄漏是个大而复杂的问题，即使是Java和.Net这样有Gabarge Collection机制的环境，也存在着泄漏的可能，比如隐式内存泄漏。由于篇幅和能力的限制，本文只能对这个主题做一个粗浅的研究。其他的问题，比如多模块下的泄漏检测，如何在程序运行时对内存使用情况进行分析等等，都是可以深入研究的题目。如果您有什么想法，建议或发现了某些错误，欢迎和我交流。 <br /><br /><br /><img src ="http://www.cppblog.com/bigsml/aggbug/13860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2006-10-19 13:45 <a href="http://www.cppblog.com/bigsml/archive/2006/10/19/13860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言中可变参数的用法 </title><link>http://www.cppblog.com/bigsml/archive/2006/10/19/13859.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Thu, 19 Oct 2006 04:55:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2006/10/19/13859.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/13859.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2006/10/19/13859.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/13859.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/13859.html</trackback:ping><description><![CDATA[我们在C语言编程中会遇到一些参数个数可变的函数,例如printf()这个函数,这里将介绍可变函数的写法以及原理.<br /><br />* 1. 可变参数的宏<br /><br />一般在调试打印Debug 信息的时候, 需要可变参数的宏. 从C99开始可以使编译器标准支持可变参数宏(variadic macros), 另外GCC 也支持可变参数宏, 但是两种在细节上可能存在区别.<br /><br />1. __VA_ARGS__<br /><br />__VA_ARGS__ 将"..." 传递给宏.如<br />#define debug(format, ...) fprintf(stderr, fmt, __VA_ARGS__)<br /><br />在GCC中也支持这类表示, 但是在G++ 中不支持这个表示.<br /><br />2. GCC 的复杂宏<br /><br />GCC使用一种不同的语法从而可以使你可以给可变参数一个名字，如同其它参数一样。<br />#define debug(format, args...) fprintf (stderr, format, args)<br /><br />这和上面举的那个定义的宏例子是完全一样的，但是这么写可读性更强并且更容易进行描述。<br /><br />3. ##__VA_ARGS__<br /><br />上面两个定义的宏, 如果出现debug("A Message") 的时候, 由于宏展开后有个多余的逗号, 所以将导致编译错误. 为了解决这个问题，CPP使用一个特殊的‘##’操作。<br /><br />#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)<br />这里，如果可变参数被忽略或为空，‘##’操作将使预处理器（preprocessor）去除掉它前面的那个逗号。如果你在宏调用时，确实提供了一些可变参数，GNU CPP也会工作正常，它会把这些可变参数放到逗号的后面。<br /><br />4. 其他方法<br /><br />一种流行的技巧是用一个单独的用括弧括起来的的 "参数" 定义和调用宏, 参数在宏扩展的时候成为类似 printf() 那样的函数的整个参数列表。 <br />#define DEBUG(args) (printf("DEBUG: "), printf(args))<br /><br /><br />* 2. 可变参数的函数 <br /><br />写可变参数的C函数要在程序中用到以下这些宏:<br />void va_start( va_list arg_ptr, prev_param )<br />type va_arg( va_list arg_ptr, type )<br />void va_end( va_list arg_ptr )<br /><br />va在这里是variable-argument(可变参数)的意思,这些宏定义在stdarg.h中.下面我们写一个简单的可变参数的函数,该函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值.<br />void simple_va_fun(int i, ...)<br />{<br />    va_list arg_ptr;<br />    int j=0; <br />    <br />    va_start(arg_ptr, i);<br />    j=va_arg(arg_ptr, int);<br />    va_end(arg_ptr);<br />    printf("%d %d\n", i, j);<br />    return;<br />}<br /><br />在程序中可以这样调用:<br />simple_va_fun(100);<br />simple_va_fun(100,200);<br /><br />从这个函数的实现可以看到,使用可变参数应该有以下步骤:<br />1)首先在函数里定义一个va_list型的变量,这里是arg_ptr,这个变量是指向参数的指针.<br />2)然后用va_start宏初始化变量arg_ptr,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数.<br />3)然后用va_arg返回可变的参数,并赋值给整数j. va_arg的第二个参数是你要返回的参数的类型,这里是int型.<br />4)最后用va_end宏结束可变参数的获取.然后你就可以在函数里使用第二个参数了.如果函数有多个可变参数的,依次调用va_arg获取各个参数.<br /><br />如果我们用下面三种方法调用的话,都是合法的,但结果却不一样:<br />1)simple_va_fun(100);<br />结果是:100 -123456789(会变的值)<br />2)simple_va_fun(100,200);<br />结果是:100 200<br />3)simple_va_fun(100,200,300);<br />结果是:100 200<br /><br />我们看到第一种调用有错误,第二种调用正确,第三种调用尽管结果正确,但和我们函数最初的设计有冲突.下面一节我们探讨出现这些结果的原因和可变参数在编译器中是如何处理的. <br />* 3. 可变参数函数原理<br /><br />va_start,va_arg,va_end是在stdarg.h中被定义成宏的,由于硬件平台的不同,编译器的不同,所以定义的宏也有所不同,下面以VC++中stdarg.h里x86平台的宏定义摘录如下:<br /><br />typedef char * va_list;<br />#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&amp;~(sizeof(int) - 1) ) <br />#define va_start(ap,v) ( ap = (va_list)&amp;v + _INTSIZEOF(v) ) <br />#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) <br />#define va_end(ap) ( ap = (va_list)0 ) <br /><br />定义_INTSIZEOF(n)主要是为了内存对齐,C语言的函数是从右向左压入堆栈的(设数据进栈方向为从高地址向低地址发展,即首先压入的数据在高地址). 下图是函数的参数在堆栈中的分布位置:<br /><br />低地址    |-----------------------------|&lt;-- &amp;v<br />        |第n-1个参数(最后一个固定参数)|<br />        |-----------------------------|&lt;--va_start后ap指向<br />        |第n个参数(第一个可变参数) |<br />        |-----------------------------|<br />        |....... |<br />        |-----------------------------|<br />        |函数返回地址 |<br />高地址  |-----------------------------|<br /><br />1. va_list 被定义为char *<br />2. va_start 将地址ap定义为 &amp;v+_INTSIZEOF(v),而&amp;v是固定参数在堆栈的地址,所以va_start(ap, v)以后,ap指向第一个可变参数在堆栈的地址<br />3. va_arg 取得类型t的可变参数值,以int型为例,va_arg取int型的返回值:<br />   j= ( *(int*)((ap += _INTSIZEOF(int))-_INTSIZEOF(int)) );<br />4. va_end 使ap不再指向堆栈,而是跟NULL一样.这样编译器不会为va_end产生代码. <br /><br />在不同的操作系统和硬件平台的定义有些不同,但原理却是相似的. <br /><br /><br />* 4. 小结<br /><br />对于可变参数的函数,因为va_start, va_arg, va_end等定义成宏,所以它显得很愚蠢,可变参数的类型和个数需要在该函数中由程序代码控制;另外,编译器对可变参数的函数的原型检查不够严格,对编程查错不利.<br />所以我们写一个可变函数的C函数时,有利也有弊,所以在不必要的场合,无需用到可变参数.如果在C++里,我们应该利用C++的多态性来实现可变参数的功能,尽量避免用C语言的方式来实现.<br /><br /><br />* 5. 附一些代码<br /><br />#define debug(format, ...) fprintf(stderr, fmt, __VA_ARGS__)<br />#define debug(format, args...) fprintf (stderr, format, args)<br />#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)<br /><br />// 使用va... 实现<br />void debug(const char *fmt, ...)<br />{<br />    int nBuf;<br />    char szBuffer[1024];<br />    va_list args;<br /><br />    va_start(args, fmt);<br />    nBuf = vsprintf(szBuffer, fmt, args) ;<br />    assert(nBuf &gt;= 0);<br /><br />    printf("QDOGC ERROR:%s\n",szBuffer);<br />    va_end(args);<br />}<br /><br /><img src ="http://www.cppblog.com/bigsml/aggbug/13859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2006-10-19 12:55 <a href="http://www.cppblog.com/bigsml/archive/2006/10/19/13859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过例子学习 CPPUnit </title><link>http://www.cppblog.com/bigsml/archive/2006/10/18/13836.html</link><dc:creator>泡泡牛</dc:creator><author>泡泡牛</author><pubDate>Wed, 18 Oct 2006 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/bigsml/archive/2006/10/18/13836.html</guid><wfw:comment>http://www.cppblog.com/bigsml/comments/13836.html</wfw:comment><comments>http://www.cppblog.com/bigsml/archive/2006/10/18/13836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bigsml/comments/commentRss/13836.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bigsml/services/trackbacks/13836.html</trackback:ping><description><![CDATA[下面是CPPUnit的一个简单例子. <br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SimpleCalcTest : </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> CPPUNIT_NS::TestFixture<br />{<br />    CPPUNIT_TEST_SUITE( SimpleCalcTest );<br />    CPPUNIT_TEST( testAdd );<br />    CPPUNIT_TEST( testSub );<br />    CPPUNIT_TEST( testMul);<br />    CPPUNIT_TEST( testDiv );<br />    CPPUNIT_TEST_SUITE_END();<br /><br /></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> :<br />    SimpleCalculator </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> sc;<br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br />    </span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setUp()<br />    {<br />        sc </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> SimpleCalculator();<br />    }<br />    </span><span style="color: rgb(0, 0, 255);">virtual</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> tearDown()<br />    {<br />        delete sc;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testAdd(){<br />        CPPUNIT_ASSERT_EQUAL( sc</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">add(</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">11</span><span style="color: rgb(0, 0, 0);">);<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testSub(){<br />        CPPUNIT_ASSERT_EQUAL( sc</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">sub(</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"> );<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testMul(){<br />        CPPUNIT_ASSERT_EQUAL( sc</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">mul(</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">30</span><span style="color: rgb(0, 0, 0);"> );<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testDiv(){<br />        CPPUNIT_ASSERT_EQUAL( sc</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">div(</span><span style="color: rgb(0, 0, 0);">12</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 0);">6</span><span style="color: rgb(0, 0, 0);">), </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"> );<br />    }<br />};<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 把这个TestSuite注册到名字为"alltest"的TestSuite中, 如果没有定义会自动定义<br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 也可以CPPUNIT_TEST_SUITE_REGISTRATION( MathTest );注册到全局的一个未命名的TestSuite中.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">CPPUNIT_TEST_SUITE_REGISTRATION( SimpleCalcTest, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">alltest</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> );<br /><br /></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> main()<br />{<br />    CPPUNIT_NS::TestResult r;<br />    CPPUNIT_NS::TestResultCollector result;<br />    r.addListener( </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">result );<br />    <br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 从注册的TestSuite中获取特定的TestSuite, 没有参数获取全局的未命名的TestSuite.</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">    CPPUNIT_NS::TestFactoryRegistry::getRegistry(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">alltest</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">).makeTest()</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">run( </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">r );<br />    CPPUNIT_NS::TextOutputter </span><span style="color: rgb(0, 0, 255);">out</span><span style="color: rgb(0, 0, 0);">( </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">result, std::cout );<br />    </span><span style="color: rgb(0, 0, 255);">out</span><span style="color: rgb(0, 0, 0);">.write();<br />    </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />}</span></div><br />从上面的代码可以看到, 使用CPPUnit 主要是两个步骤:<br />1. 创建TestSuite<br />首先从CPPUNIT_NS::TestFixture 生成一个子类, 然后用宏 CPPUNIT_TEST_SUITE, CPPUNIT_TEST, CPPUNIT_TEST_SUITE_END 来定义要测试的各个小单元, 并且实现CPPUNIT_TEST 中定义的类函数; 在每个类函数中使用 CPPUNIT_ASSERT, CPPUNIT_ASSERT_MESSAGE, CPPUNIT_FAIL, CPPUNIT_ASSERT_EQUAL, CPPUNIT_ASSERT_EQUAL_MESSAGE, CPPUNIT_ASSERT_DOUBLES_EQUAL 等来对结果进行断言.<br /><br />然后通过宏 CPPUNIT_TEST_SUITE_REGISTRATION 将测试类注册到TestSuite中.<br /><br />2. Main<br />在main程序中对TestSuite 进行测试. <br /><br /><br />CPPUnit的更详细的资料可以查看:<br />IBM 的 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-cppunit/index.html">便利的开发工具 CppUnit 快速使用指南</a>  比较详细的介绍了CppUnit<br />VCKBase的 <a href="http://www.vckbase.com/document/viewdoc/?id=1258">CppUnit测试框架入门</a> 详细的介绍了VC6下MFC Dialog下的CPPUnit的使用<br />CSDN 的 <a href="http://sd.csdn.net/n/20061012/96091.html">如何使用CppUnit做单元测试</a> 介绍了VC6的MFC 下的CPPUnit的使用, 和VCKBase的实现稍微有点差别<br />Meng Yan ( 孟岩 ) 的文章 <a href="http://www.mengyan.org/blog/tag/cppunit">CPPUnit Lite</a> 对CPPUnit的使用和宏进行了简单的分析<br /><br /><br /><br /><img src ="http://www.cppblog.com/bigsml/aggbug/13836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bigsml/" target="_blank">泡泡牛</a> 2006-10-18 20:59 <a href="http://www.cppblog.com/bigsml/archive/2006/10/18/13836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>