Jeff Sanders Technical Blog

I am a Microsoft employee that has worked on all aspects of the Web Stack for a long time. I hope these blogs are useful to you! Use this information at your own risk.


<< Go Back

Extra Characters Rn When Converting Mfc Isapi Under Vs 2005

- 11 May 2007

When you convert an MFC ISAPI project you created in an early version of Visual Studio to MFC 8 (VS 2005) you may notice that there is an extra set of carriage return linefeed characters.  This will be true if your code does not add a header to the return stream.  You can see this if you take the default project and comment out the lines as shown below:<p class=MsoNormal style="MARGIN: 0in 0in 0pt">

void CTestIISDLLExtension::Default(CHttpServerContext* pCtxt, void* pVoid, DWORD dwBytes)<?xml:namespace prefix = o ns = “urn:schemas-microsoft-com:office:office” /></p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">

{</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    StartContent(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    WriteTitle(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">      *pCtxt « _T(“Test”);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt"> </p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    EndContent(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">}</p>

This is because of a bug in MFC 8.0 ISAPI classes.  It is unlikely that this bug will be fixed because these classes are being phased out (note there is no ISAPI wizard in VS 2005) and the workaround is relatively simple.  The easiest fix for this problem is to ensure you add a header as the following example shows:<p class=MsoNormal style="MARGIN: 0in 0in 0pt">

void CTestIISDLLExtension::Default(CHttpServerContext* pCtxt, void* pVoid, DWORD dwBytes)</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">{</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    StartContent(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    WriteTitle(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">      this->AddHeader(pCtxt,“Dummy: My Header”);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">      *pCtxt « _T(“Test”);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt"> </p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">//    EndContent(pCtxt);</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">}</p>

Of course you can make this look more official in your case. “Company XYX: CustomISAPI”.

A little more complicated fix is for you to leverage the fact that this is a C++ class.  The bug is in this function in the base class.  You can implement this virtual function however and fix the issue.  Here is the funtion signiture to override in your ISAPI Extension .h file:

 virtual DWORD HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB);

Then implement the fix by copying the source for this function from the base class (all of the source for these MFC Classes gets installed by default) and change the behavior on by adding a couple of lines.  It is a little more complicated however because the base class has a static member you need to add to your file and you must declare some helper functions as well.  The change is (in the original source) on line 676 of isapi.cpp.  <p class=MsoNormal style="MARGIN: 0in 0in 0pt">

            // The bug can be fixed by adding the following line:</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">            // isapi.cpp Ln676</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">            if(ctxtCall.m_dwEndOfHeaders == 0 )</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">            {     // Fix is to only add 1 delim, and not 2</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">                  nDelimsToAdd = 1;</p> <p class=MsoNormal style="MARGIN: 0in 0in 0pt">            } else // End of Fix</p>

Here are the globals and helper functions needed by the copied code:

<font color=#008000 size=2>

//Needed as part of the fix
// pointers to single global server and filter objects

</font><font color=#0000ff size=2>

static</font> CHttpServer* pServer = NULL; <font color=#0000ff size=2>static</font> <font color=#0000ff size=2>const</font> TCHAR szGet[] = _T(<font color=#a31515 size=2>“GET”</font>); <font color=#0000ff size=2>static</font> <font color=#0000ff size=2>const</font> TCHAR szPost[] = _T(<font color=#a31515 size=2>“POST”</font>);<p mce_keep="true"> </p>

</font><font color=#008000 size=2>

/////////////////////////////////////////////////////////////////////////////
// helpers copied from afxwin.h since isapi.cpp is a separate static lib

</font><font color=#0000ff size=2>

inline</font> <font color=#0000ff size=2>int</font> AfxInvariantStrICmp(<font color=#0000ff size=2>const</font> <font color=#0000ff size=2>char</font> *pszLeft, <font color=#0000ff size=2>const</font> <font color=#0000ff size=2>char</font> *pszRight) { <font color=#0000ff size=2>    return</font> ::CompareStringA(MAKELCID(MAKELANGID(LANG\_ENGLISH,SUBLANG\_ENGLISH\_US),SORT\_DEFAULT), NORM\_IGNORECASE,pszLeft,-1,pszRight,-1)-CSTR\_EQUAL; }

</font><font color=#0000ff size=2>

inline</font> <font color=#0000ff size=2>int</font> AfxInvariantStrICmp(<font color=#0000ff size=2>const</font> <font color=#0000ff size=2>wchar_t</font> *pwszLeft, <font color=#0000ff size=2>const</font> <font color=#0000ff size=2>wchar_t</font> *pwszRight) { <font color=#0000ff size=2>    return</font> ::CompareStringW(MAKELCID(MAKELANGID(LANG\_ENGLISH,SUBLANG\_ENGLISH\_US),SORT\_DEFAULT),NORM\_IGNORECASE,pwszLeft,-1,pwszRight,-1)-CSTR\_EQUAL; } <font color=#008000 size=2>//  End Additions</font>

Finally you need to initialize pServer in the constuctor:

CTestIISDLLExtension::CTestIISDLLExtension() {    

<font color=#008000 size=2>pServer = this;
</font>}

</font>I leave it to you to iron out all the nitty gritty details and as with any sample code is you up to you to understand and test your changes.

<< Go Back