<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx</link><description>Question: 
 Hi everyone, 
 I wrote a ISAPI filter DLL to process text/html content. Whenever there's a request for a .php file, the OnUrlMap gets called 3 times whereas .html or .asp files causes the right behaviour in Filter (i.e. - OnUrlMap gets called</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#8476375</link><pubDate>Fri, 09 May 2008 04:47:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8476375</guid><dc:creator>David.Wang</dc:creator><description>&lt;p&gt;Mario - modifying the raw response data to perform logical HTTP operations is very difficult to do correctly and impossible to do performantly. SendRawData filter turns off just about all the IIS output caches and optimizations and turns async IO paths synchronous. For example, TransmitFile used to do optimal user-kernel transitions but NOT when SendRawData Filter is involved, even if the filter does nothing.&lt;/p&gt;
&lt;p&gt;1. You must buffer the response header at the very beginning SF_NOTIFY_SEND_RAW_DATA and prevent it from being sent -- since you likely have to modify it.&lt;/p&gt;
&lt;p&gt;2. Using pfc-&amp;gt;pFilterContext to store the buffered response header AND entity body is required for efficiency. If you do not use it, you would have to use global read/write variables, and that introduces read/write locks and thus contention into the critical data output pathway across the entire server... which would be horrendous.&lt;/p&gt;
&lt;p&gt;3. SF_NOTIFY_END_OF_REQUEST tells you that the request would not generate any more SF_NOTIFY_SEND_RAW_DATA. However, you would have to WriteClient() your buffered response in that event to flush the response back to the client, which itself would generate SF_NOTIFY_SEND_RAW_DATA... so if you are not careful, you would buffer everything and emit nothing.&lt;/p&gt;
&lt;p&gt;//David&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8476375" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#8465712</link><pubDate>Wed, 07 May 2008 14:04:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8465712</guid><dc:creator>Mario</dc:creator><description>&lt;p&gt;Thank you David, &lt;/p&gt;
&lt;p&gt; &amp;nbsp;That was concise and to the piont, and as mentioned in other posts, this is a duanting task. Would it say to assume the following as I move in this task.&lt;/p&gt;
&lt;p&gt;1. Regardless of how many event triggers, I will always have access to the Response header to calculate and modify the appropiate header ( &amp;quot;Transfer-type&amp;quot;, &amp;quot;Content-length&amp;quot; )?&lt;/p&gt;
&lt;p&gt;2. As per this entry, what is the wisest way to use to ensure safe and efficient ways of storing the entire body , across multiple child exec requests ( SSI Includes ). I would take a guess that as per you above mentioned cautionary notes, PER-CONNECTION would be the preffered method&lt;/p&gt;
&lt;p&gt;3. Is there a Event handler that I could use to find out when the EndOfRequest has been reached?&lt;/p&gt;
&lt;p&gt;Thank you again&lt;/p&gt;
&lt;p&gt;Mario&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8465712" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#8464683</link><pubDate>Wed, 07 May 2008 07:03:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8464683</guid><dc:creator>David.Wang</dc:creator><description>&lt;p&gt;Mario - yes, if you want to modify the outbound response, you have to buffer sufficient amount of entity body to make your modification, and depending on the response transfer method (either Content-Length, or Transfer-Encoding: chunked), you will have to make the appropriate modifications.&lt;/p&gt;
&lt;p&gt;For example, your code will fail right now if the double \r\n is sent over two HTTP packets.&lt;/p&gt;
&lt;p&gt;What you want to do is:&lt;/p&gt;
&lt;p&gt;1. Buffer enough raw data over possibly multiple triggers of SF_NOTIFY_SEND_RAW_DATA to determine if the response header has &amp;quot;Content-Length:&amp;quot;, &amp;quot;Transfer-Encoding: chunked&amp;quot;, or neither header&lt;/p&gt;
&lt;p&gt;2a. If Content-Length, then you must continue to buffer everything, perform your modifications, recalculate the new entity body length, and modify &amp;quot;Content-Length&amp;quot; to reflect the new length&lt;/p&gt;
&lt;p&gt;2b. If Transfer-Encoding: chunked, then you can easily insert chunks if you're just inserting data. If modifying existing data, then you have to buffer and modify as in 2a, this time having to update the chunk's length header.&lt;/p&gt;
&lt;p&gt;In all cases, your buffering has to be a sliding one that crosses two SF_NOTIFY_SEND_RAW_DATA because the thing you are looking to replace *may* come across two different event notifications -- for example, &amp;lt;/ht &amp;nbsp; comes on the first event and &amp;nbsp;ml&amp;gt; comes on the second event, so if you want to replace &amp;lt;/html&amp;gt;, you have to do this across the two events.&lt;/p&gt;
&lt;p&gt;//David&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8464683" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#8463453</link><pubDate>Tue, 06 May 2008 20:02:23 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8463453</guid><dc:creator>Mario</dc:creator><description>&lt;p&gt;Hi David,&lt;/p&gt;
&lt;p&gt; I am a little confused with the l differences in PER-CONNECTION and PER_REQUEST. As mentioned, it is a matter of scope, so I am thinking that is I am writing a ISAPI Filter to change elements ( special tags ) in the reponse back to the client, and they are all sliced up into a series of includes ( SSI includes ) , then it would be wise to take the PER-REQUEST Route????&lt;/p&gt;
&lt;p&gt;Here is some code, very simple, but it helps to try to show what I am doing. Thoughts on how to make the whole body of the response available, in an effiecent manner ?&lt;/p&gt;
&lt;p&gt;Also in a prior blog entry you mentioned content-size is important to note. Does this mean that I am replacing these tags with lets say a paragraph or a few lines of text, I now have to change the response header ( content-length: ) as well? I would assume so.&lt;/p&gt;
&lt;p&gt;#include &amp;lt;string&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;windows.h&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/p&gt;
&lt;p&gt;#include &amp;lt;httpfilt.h&amp;gt;&lt;/p&gt;
&lt;p&gt;BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;/* Specify the types and order of notification */&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pVer-&amp;gt;dwFlags = (SF_NOTIFY_SEND_RAW_DATA);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pVer-&amp;gt;dwFilterVersion = HTTP_FILTER_REVISION;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;strcpy_s(pVer-&amp;gt;lpszFilterDesc, &amp;quot;PreProcessor filter, Version 1.0&amp;quot;);&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return TRUE;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;CHAR *in;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;CHAR out[10000];&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;DWORD cbBuffer, cbtemp;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;signed int newCharCount, contentStartPos;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;switch (NotificationType) &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case SF_NOTIFY_SEND_RAW_DATA :&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;PHTTP_FILTER_RAW_DATA pResponse;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pResponse = (PHTTP_FILTER_RAW_DATA)pvData;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;in = (CHAR*)pResponse-&amp;gt;pvInData;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cbBuffer = 0;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Skips the header.&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for( ;cbBuffer&amp;lt;pResponse-&amp;gt;cbInData-2;cbBuffer++){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (in[cbBuffer] == '\n' &amp;amp;&amp;amp; in[cbBuffer + 2] == '\n'){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cbBuffer +=3;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Verifies that the requested file is an html file.&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (cbtemp = 0; cbtemp &amp;lt; (cbBuffer - 3); cbtemp++) &lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (in[cbtemp] == '/' &amp;amp;&amp;amp; in[cbtemp + 1] == 'h' &amp;amp;&amp;amp; in[cbtemp + 2] == 't' &amp;amp;&amp;amp; in[cbtemp + 3] == 'm')&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pfc-&amp;gt;pFilterContext &amp;nbsp; &amp;nbsp; = &amp;nbsp; &amp;nbsp; &amp;nbsp; (VOID &amp;nbsp; *)2;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (cbtemp == &amp;nbsp; cbBuffer)&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pfc-&amp;gt;pFilterContext &amp;nbsp; &amp;nbsp; = &amp;nbsp; &amp;nbsp; &amp;nbsp; 0; /* not an &amp;nbsp; &amp;nbsp;html file */&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;//Process the file&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if(pfc-&amp;gt;pFilterContext){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;newCharCount = 0;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;contentStartPos = cbBuffer;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for ( ;cbBuffer &amp;lt; pResponse-&amp;gt;cbInData-2;cbBuffer++){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (in[cbBuffer] == '&amp;lt;' &amp;amp;&amp;amp; in[cbBuffer + 1] == '&amp;amp;'){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (cbtemp = cbBuffer+2; cbtemp &amp;lt; pResponse-&amp;gt;cbInData-2; cbtemp++){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (in[cbtemp] == '&amp;amp;' &amp;amp;&amp;amp; in[cbtemp + 1] == '&amp;gt;'){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cbBuffer = cbtemp + 2;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;continue;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}else{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;out[newCharCount] = in[cbBuffer];&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;newCharCount++;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pResponse-&amp;gt;cbInData = contentStartPos + newCharCount+1;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;for (cbtemp=0 ;cbtemp &amp;lt; newCharCount; cbtemp++){&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;in[cbtemp + contentStartPos] = out[cbtemp];&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;default:&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return SF_STATUS_REQ_HANDLED_NOTIFICATION;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;Thank you again David. &lt;/p&gt;
&lt;p&gt;And if it helps, I think you blog and your reccomendations are both clear, helpful, and insightful.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8463453" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#640628</link><pubDate>Wed, 21 Jun 2006 02:57:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:640628</guid><dc:creator>David.Wang</dc:creator><description>JC - Which IIS version are you running, and are you running more than 1 ISAPI Filter at either global or site level.&lt;br&gt;&lt;br&gt;In general, you want to designate your data as either per-request or per-connection and then manage its lifetime appropriately.&lt;br&gt;- Per-connection memory can be handled with pfc-&amp;gt;AllocMem()&lt;br&gt;- Per-request memory can be handled with PreprocHeaders and Log/EndOfRequest&lt;br&gt;&lt;br&gt;Also, you need to be aware that pfc-&amp;gt;pFilterContext is PER-CONNECTION and NOT PER-REQUEST, which has special implications when servicing keep-alive or pipelined requests. For example:&lt;br&gt;- keep-alive requests mean that one connection and pFilterContext could be in use for 2 or more requests&lt;br&gt;- pipelined requests mean that one connection and pFilterContext could be used for 2 or more consecutive requests&lt;br&gt;&lt;br&gt;Finally, you probably want to minimize the amount of memory creation/deletion done by an ISAPI Filter because it can fragment memory. Pre-allocating memory and then re-using is the preferred approach.&lt;br&gt;&lt;br&gt;//David&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=640628" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#639333</link><pubDate>Tue, 20 Jun 2006 15:47:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:639333</guid><dc:creator>JC</dc:creator><description>Thank you for your answer. The reason I asked about which events might not be fired is because I have some problems with a filter I've written.&lt;br&gt;&lt;br&gt;In my filter, I use the filter context for storing data so I can have access to this data throughout the execution of the filter. The data is written to the context when the OnReadRawData event is fired. Then, when OnPreprocHeaders, OnUrlMap, OnSendRawData and OnLog is fired I read the data stored in the filter context. I delete the data from the filter context during the OnLog event.&lt;br&gt;&lt;br&gt;The problem is that sometimes when OnPreprocHeaders and OnLog is fired, the data cannot be found in the filter context. This happens most often when the web server is under high stress and it seems to be more frequent when simple/static resourses like images and javascripts are requested. I have guessed that the reason for this is one of the following two:&lt;br&gt;&lt;br&gt;1. OnPreprocHeaders and OnLog is sometimes fired before OnReadRawData&lt;br&gt;2. OnLog is fired more that once&lt;br&gt;&lt;br&gt;Do you have any idea why the data is not found in the filter context?&lt;br&gt;&lt;br&gt;/JC&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=639333" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#631436</link><pubDate>Thu, 15 Jun 2006 00:43:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:631436</guid><dc:creator>David.Wang</dc:creator><description>JC - I am not aware of a scenario where OnLog executes more than once per request because logically, it should execute exactly once per request, just like OnPreprocHeaders. However, some error cases and OnReadRawData event can certainly affect this expectation...&lt;br&gt;&lt;br&gt;Remember, ISAPI Filters directly manipulate IIS Server-Side behavior, which can change and break expected behaviors.&lt;br&gt;&lt;br&gt;Listing the possible interactions that result in filter events not firing is beyond the scope of a blog comment. Do you have a specific question in mind.&lt;br&gt;&lt;br&gt;//David&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=631436" width="1" height="1"&gt;</description></item><item><title>re: Why some ISAPI Filter events trigger multiple times per request</title><link>http://blogs.msdn.com/b/david.wang/archive/2006/03/11/why-some-isapi-filter-events-trigger-multiple-times-per-request.aspx#630787</link><pubDate>Wed, 14 Jun 2006 15:15:45 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:630787</guid><dc:creator>JC</dc:creator><description>Hi,&lt;br&gt;&lt;br&gt;you mention that some requests can be executed more than one time. Do you know if the notification OnLog also can be executed more than once per request?&lt;br&gt;&lt;br&gt;You state that 'There is no guarantee that every event fires at least once per request'. Does that mean that there are events that sometimes not will be executed/fired? Which events might not be executed?&lt;br&gt;&lt;br&gt;Thanks in advance! &lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=630787" width="1" height="1"&gt;</description></item></channel></rss>