Extra Characters (/r/n) when Converting MFC ISAPI under VS 2005

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:

void CTestIISDLLExtension::Default(CHttpServerContext* pCtxt, void* pVoid, DWORD dwBytes)

{

// StartContent(pCtxt);

// WriteTitle(pCtxt);

      *pCtxt << _T("Test");

// EndContent(pCtxt);

}

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:

void CTestIISDLLExtension::Default(CHttpServerContext* pCtxt, void* pVoid, DWORD dwBytes)

{

// StartContent(pCtxt);

// WriteTitle(pCtxt);

      this->AddHeader(pCtxt,"Dummy: My Header");

      *pCtxt << _T("Test");

// EndContent(pCtxt);

}

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. 

            // The bug can be fixed by adding the following line:

            // isapi.cpp Ln676

            if(ctxtCall.m_dwEndOfHeaders == 0 )

            { // Fix is to only add 1 delim, and not 2

                  nDelimsToAdd = 1;

            } else // End of Fix

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

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

static

CHttpServer* pServer = NULL;
static const TCHAR szGet[] = _T("GET");
static const TCHAR szPost[] = _T("POST");

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

inline

int AfxInvariantStrICmp(const char *pszLeft, const char *pszRight)
{
    return ::CompareStringA(MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),
NORM_IGNORECASE,pszLeft,-1,pszRight,-1)-CSTR_EQUAL;
}

inline

int AfxInvariantStrICmp(const wchar_t *pwszLeft, const wchar_t *pwszRight)
{
    return ::CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),NORM_IGNORECASE,pwszLeft,-1,pwszRight,-1)-CSTR_EQUAL;
}
// End Additions

Finally you need to initialize pServer in the constuctor:

CTestIISDLLExtension::CTestIISDLLExtension()
{

pServer = this;
}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.