home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- // This module is unique -- no need for PCH
-
- #include <limits.h>
-
- #ifdef _AFXDLL
- #include <afx.h>
- #include <afxwin.h>
- #include <afxdb.h>
- #include <afxpriv.h>
- #endif
-
- #include <afxisapi.h>
- #include <afxres.h>
- #include <stdio.h>
- #include <malloc.h>
- #include "dispimpl.h"
-
- ///////////////////////////////////////////////////////////////////////
- // Globals
-
- // pointers to single global server and filter objects
-
- static CHttpServer* pServer = NULL;
- static CHttpFilter* pFilter = NULL;
-
- // stock server extension strings
-
- static const TCHAR szGet[] = _T("GET");
- static const TCHAR szPost[] = _T("POST");
- static const TCHAR szDecimalFormat[] = _T("%d");
- static const TCHAR szFloatFormat[] = _T("%f");
-
- // stock HTML tags
-
- static const TCHAR szContentType[] = _T("Content-Type: text/html\r\n");
- static const TCHAR szEndBody[] = _T("</body></html>");
- static const TCHAR szStartTitle[] = _T("<html><head><title>");
- static const TCHAR szEndTitle[] = _T("</title></head><body>");
- static const TCHAR szDefaultTitle[] = _T("Default MFC Web Server Extension");
-
- // error texts
- // these aren't localized as they are part of the HTTP spec
-
- typedef struct _httpstatinfo {
- DWORD dwCode;
- LPCTSTR pstrString;
- } HTTPStatusInfo;
-
- static HTTPStatusInfo statusStrings[] = {
- { HTTP_STATUS_OK, _T("OK") },
- { HTTP_STATUS_CREATED, _T("Created") },
- { HTTP_STATUS_ACCEPTED, _T("Accepted") },
- { HTTP_STATUS_NO_CONTENT, _T("No Content") },
- { HTTP_STATUS_TEMP_REDIRECT, _T("Moved Temporarily") },
- { HTTP_STATUS_REDIRECT, _T("Moved Permanently") },
- { HTTP_STATUS_NOT_MODIFIED, _T("Not Modified") },
- { HTTP_STATUS_BAD_REQUEST, _T("Bad Request") },
- { HTTP_STATUS_AUTH_REQUIRED, _T("Unauthorized") },
- { HTTP_STATUS_FORBIDDEN, _T("Forbidden") },
- { HTTP_STATUS_NOT_FOUND, _T("Not Found") },
- { HTTP_STATUS_SERVER_ERROR, _T("Internal Server Error") },
- { HTTP_STATUS_NOT_IMPLEMENTED, _T("Not Implemented") },
- { HTTP_STATUS_BAD_GATEWAY, _T("Bad Gateway") },
- { HTTP_STATUS_SERVICE_NA, _T("Service Unavailable") },
- { 0, NULL }
- };
-
- /////////////////////////////////////////////////////////////////////////////
- // Root of all parse maps
-
- const AFXIS_DATADEF AFX_PARSEMAP CHttpServer::parseMap =
- {
- &CHttpServer::GetNumMapEntries,
- #ifdef _AFXDLL
- &CHttpServer::_GetBaseParseMap,
- #else
- NULL,
- #endif
- &CHttpServer::_parseEntries[0],
- };
-
- AFX_PARSEMAP_ENTRY CHttpServer::_parseEntries[] =
- {
- { NULL, NULL, NULL } // nothing here
- };
-
- #ifdef _AFXDLL
- const AFX_PARSEMAP* CHttpServer::_GetBaseParseMap()
- {
- return NULL;
- }
- #endif
-
- UINT PASCAL CHttpServer::GetNumMapEntries()
- {
- return 0;
- }
-
- const AFX_PARSEMAP* CHttpServer::GetParseMap() const
- {
- return NULL;
- }
-
- AFX_PARSEMAP::~AFX_PARSEMAP()
- {
- // walk through parse map to find any dying parsed parameter entries
-
- UINT iEntry;
- UINT cEntries = (*pfnGetNumMapEntries)();
- AFX_PARSEMAP_ENTRY* pCurrent = (AFX_PARSEMAP_ENTRY*) lpEntries;
-
- for (iEntry = 0; iEntry < cEntries; iEntry++, pCurrent++)
- {
- if (pCurrent->pfn == NULL)
- {
- delete (AFX_PARSEMAP_ENTRY_PARAMS*) pCurrent->pszFnName;
- pCurrent->pszFnName = NULL;
-
- free(pCurrent->pszParamInfo);
- pCurrent->pszParamInfo = NULL;
- }
- }
- }
-
- AFX_PARSEMAP_ENTRY_PARAMS::~AFX_PARSEMAP_ENTRY_PARAMS()
- {
- delete [] ppszInfo;
- delete [] ppszDefaults;
- delete [] ppszValues;
- }
-
- ///////////////////////////////////////////////////////////////////////
- // Entry points for HTTP Server Extensions
-
- extern "C" DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- #endif
- DWORD dwRet;
-
- ISAPIASSERT(pServer != NULL);
- if (pServer == NULL)
- {
- dwRet = HSE_STATUS_ERROR;
- pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
- }
- else
- dwRet = pServer->HttpExtensionProc(pECB);
-
- return dwRet;
- }
-
- extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- #endif
- BOOL bRet;
-
- ISAPIASSERT(pServer != NULL);
- if (pServer == NULL)
- bRet = FALSE;
- else
- bRet = pServer->GetExtensionVersion(pVer);
-
- return bRet;
- }
-
- extern "C" BOOL WINAPI TerminateExtension(DWORD dwFlags)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- #endif
-
- if (pServer == NULL)
- return TRUE;
- return pServer->TerminateExtension(dwFlags);
- }
-
- ///////////////////////////////////////////////////////////////////////
- // CHttpAsyncContext implementation
-
- class CHttpAsyncContext
- {
- public:
- CHttpAsyncContext(HANDLE hFile, LPVOID pvHeader, DWORD dwHeaderLen,
- LPVOID pvTail, DWORD dwTailLen);
- virtual ~CHttpAsyncContext();
-
- protected:
- LPVOID m_pvHeader;
- DWORD m_dwHeaderLen;
- LPVOID m_pvTail;
- DWORD m_dwTailLen;
- HANDLE m_hFile;
- };
-
- CHttpAsyncContext::CHttpAsyncContext(HANDLE hFile, LPVOID pvHeader,
- DWORD dwHeaderLen, LPVOID pvTail, DWORD dwTailLen)
- : m_hFile(hFile)
- {
- if (pvHeader == NULL || dwHeaderLen == 0)
- {
- m_pvHeader = NULL;
- dwHeaderLen = 0;
- }
- else
- {
- m_pvHeader = new BYTE[dwHeaderLen+1];
- memcpy(m_pvHeader, pvHeader, dwHeaderLen);
- m_dwHeaderLen = dwHeaderLen;
- }
-
- if (pvTail == NULL || dwTailLen == 0)
- {
- m_pvTail = NULL;
- dwTailLen = 0;
- }
- else
- {
- m_pvTail = new BYTE[dwTailLen+1];
- memcpy(m_pvTail, pvTail, dwTailLen);
- m_dwTailLen = dwTailLen;
- }
- }
-
- CHttpAsyncContext::~CHttpAsyncContext()
- {
- if (m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
- CloseHandle(m_hFile);
-
- delete [] m_pvTail;
- delete [] m_pvHeader;
- }
-
- ///////////////////////////////////////////////////////////////////////
- // CHttpServerContext implementation
-
- void CHttpServerContext::Reset()
- {
- #ifdef _DEBUG
- m_dwOldEndOfHeaders = 0;
- #endif
- m_pStream->Reset();
- }
-
- DWORD CHttpServerContext::SetChunkSize(DWORD dwNewSize)
- {
- DWORD dwReturn = m_dwChunkSize;
- m_dwChunkSize = dwNewSize;
- return dwReturn;
- }
-
- DWORD CHttpServerContext::GetChunkSize() const
- {
- return m_dwChunkSize;
- }
-
- VOID WINAPI AfxIOCallback(EXTENSION_CONTROL_BLOCK* pECB,
- PVOID pvContext, DWORD /* cbIO */, DWORD /* dwError */)
- {
- if (!pECB->ServerSupportFunction(pECB->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL))
- ISAPITRACE("HttpExtensionProc io callback error\n");
-
- CHttpAsyncContext* pInfo = (CHttpAsyncContext*) pvContext;
- delete pInfo;
- }
-
- BOOL CHttpServerContext::TransmitFile(HANDLE hFile,
- DWORD dwFlags /* = HSE_IO_DISCONNECT_AFTER_SEND */,
- LPVOID pvHeader /* = NULL */, DWORD dwHeaderLen /* = 0 */,
- LPVOID pvTail /* = NULL */, DWORD dwTailLen /* = 0 */)
- {
- if (hFile == INVALID_HANDLE_VALUE)
- return FALSE;
-
- ISAPIASSERT(dwHeaderLen == 0 || pvHeader != NULL);
- ISAPIASSERT(dwTailLen == 0 || pvTail != NULL);
-
- if (dwTailLen == 0 && pvTail != NULL)
- dwTailLen = lstrlen((LPCTSTR) pvTail);
-
- if (dwHeaderLen == 0 && pvHeader != NULL)
- dwHeaderLen = lstrlen((LPCTSTR) pvHeader);
-
- CHttpAsyncContext* pInfo =
- new CHttpAsyncContext(hFile, pvHeader, dwTailLen, pvTail, dwHeaderLen);
-
- HSE_TF_INFO info;
-
- info.pszStatusCode = NULL;
- info.hFile = hFile;
- info.dwFlags = dwFlags;
- info.BytesToWrite = 0;
- info.Offset = 0;
- info.pfnHseIO = AfxIOCallback;
- info.pContext = pInfo;
- info.pHead = pvHeader;
- info.HeadLength = dwHeaderLen;
- info.pTail = pvTail;
- info.TailLength = dwTailLen;
-
- BOOL bResult = ServerSupportFunction(HSE_REQ_TRANSMIT_FILE, &info, 0, 0);
-
- if (bResult)
- {
- m_dwStatusCode = HSE_STATUS_PENDING;
- m_bSendHeaders = FALSE;
- }
- else
- delete pInfo;
-
- return bResult;
- }
-
- ///////////////////////////////////////////////////////////////////////
- // CHttpServer implementation
-
- BOOL CHttpServer::TerminateExtension(DWORD /* dwFlags */)
- {
- // okay to unload at any time, by default
- return TRUE;
- }
-
- LPTSTR CHttpServer::GetQuery(CHttpServerContext* pCtxt, LPTSTR lpszQuery)
- {
- // If the request is a POST, get all of the data. First get what's
- // already available, then read any additional data via the
- // ReadClient() call.
-
- memcpy(lpszQuery, (LPCTSTR) pCtxt->m_pECB->lpbData, pCtxt->m_pECB->cbAvailable);
- lpszQuery[pCtxt->m_pECB->cbAvailable] = '\0';
-
- if (pCtxt->m_pECB->cbAvailable < pCtxt->m_pECB->cbTotalBytes)
- {
- LPCTSTR pstrTarget = lpszQuery + pCtxt->m_pECB->cbAvailable;
- DWORD cbRemaining = pCtxt->m_pECB->cbTotalBytes - pCtxt->m_pECB->cbAvailable;
- DWORD cbRead;
-
- while (cbRemaining > 0)
- {
- cbRead = cbRemaining;
- if (!pCtxt->ReadClient((LPVOID) pstrTarget, &cbRead))
- {
- ISAPITRACE("Error: only %d of %d bytes read!\n",
- pCtxt->m_pECB->cbTotalBytes - cbRemaining,
- pCtxt->m_pECB->cbTotalBytes);
- return NULL;
- }
-
- if (cbRead == 0)
- break;
-
- pstrTarget += cbRead;
- cbRemaining -= cbRead;
- }
- }
-
- pCtxt->m_dwBytesReceived = pCtxt->m_pECB->cbTotalBytes;
- return lpszQuery;
- }
-
- BOOL CHttpServer::OnWriteBody(CHttpServerContext* pCtxt, LPBYTE pbContent,
- DWORD dwSize, DWORD dwReserved /* = 0 */)
- {
- BOOL bRetVal;
-
- if (pCtxt->m_dwChunkSize == 0)
- bRetVal = pCtxt->WriteClient(pbContent, &dwSize, dwReserved);
- else
- {
- LPBYTE pbStart = pbContent;
- DWORD dwBytesLeft = dwSize;
- bRetVal = TRUE;
-
- while (bRetVal && (dwBytesLeft > 0))
- {
- DWORD dwThisChunk = min(dwBytesLeft, pCtxt->m_dwChunkSize);
- bRetVal = pCtxt->WriteClient(pbStart, &dwThisChunk, dwReserved);
- pbStart += dwThisChunk;
- dwBytesLeft -= dwThisChunk;
- }
- }
-
- return bRetVal;
- }
-
- DWORD CHttpServer::HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
- {
- DWORD dwRet = HSE_STATUS_SUCCESS;
- LPTSTR pszPostBuffer = NULL;
- LPTSTR pszQuery;
- LPTSTR pszCommand = NULL;
- int nMethodRet;
- LPTSTR pstrLastChar;
- DWORD cbStream = 0;
- BYTE* pbStream = NULL;
- CHttpServerContext ctxtCall(pECB);
-
- pECB->dwHttpStatusCode = 0;
-
- ISAPIASSERT(NULL != pServer);
- if (pServer == NULL)
- {
- dwRet = HSE_STATUS_ERROR;
- goto CleanUp;
- }
-
- // get the query
-
- if (lstrcmpi(pECB->lpszMethod, szGet) == 0)
- {
- pszQuery = pECB->lpszQueryString;
- ctxtCall.m_dwBytesReceived = lstrlen(pszQuery);
- }
- else if (lstrcmpi(pECB->lpszMethod, szPost) == 0)
- {
- pszCommand = pECB->lpszQueryString;
- pszPostBuffer = new TCHAR[pECB->cbTotalBytes + 1];
- pszQuery = GetQuery(&ctxtCall, pszPostBuffer);
- if (pszQuery == NULL)
- {
- dwRet = HSE_STATUS_ERROR;
- goto CleanUp;
- }
- }
- else
- {
- ISAPITRACE1("Error: Unrecognized method: %s\n", pECB->lpszMethod);
- dwRet = HSE_STATUS_ERROR;
- goto CleanUp;
- }
-
- // trim junk that some browsers put at the very end
-
- pstrLastChar = pszQuery + ctxtCall.m_dwBytesReceived -1;
- while ((*pstrLastChar == ' ' || *pstrLastChar == '\n' ||
- *pstrLastChar == '\r') && pstrLastChar > pszQuery)
- {
- *pstrLastChar-- = '\0';
- }
-
- // do something about it
-
- if (!pServer->InitInstance(&ctxtCall))
- dwRet = HSE_STATUS_ERROR;
- else
- {
- pECB->dwHttpStatusCode = HTTP_STATUS_OK;
- try {
- nMethodRet = pServer->CallFunction(&ctxtCall, pszQuery, pszCommand);
- }
- catch (...)
- {
- ISAPITRACE1("Error: command %s caused an unhandled exception!\n",
- pszQuery);
- nMethodRet = callNoStackSpace;
- }
-
- // was an error caused by trying to dispatch?
-
- if (nMethodRet != callOK && pECB->dwHttpStatusCode == HTTP_STATUS_OK)
- {
- dwRet = HSE_STATUS_ERROR;
- switch (nMethodRet)
- {
- case callNoStream:
- pECB->dwHttpStatusCode = HTTP_STATUS_NO_CONTENT;
- break;
-
- case callParamRequired:
- case callBadParamCount:
- case callBadParam:
- pECB->dwHttpStatusCode = HTTP_STATUS_BAD_REQUEST;
- break;
-
- case callBadCommand:
- pECB->dwHttpStatusCode = HTTP_STATUS_NOT_IMPLEMENTED;
- break;
-
- case callNoStackSpace:
- default:
- pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
- break;
- }
- }
-
- // if there was no error or the user said they handled
- // the error, prepare to spit out the generated HTML
-
- if (nMethodRet == callOK ||
- OnParseError(&ctxtCall, nMethodRet))
- {
- cbStream = ctxtCall.m_pStream->GetStreamSize();
- pbStream = ctxtCall.m_pStream->Detach();
- }
- }
-
- CleanUp:
- // if there was an error, return an appropriate status
- TCHAR szResponse[64];
- BuildStatusCode(szResponse, pECB->dwHttpStatusCode);
-
- DWORD dwSize = cbStream - ctxtCall.m_dwEndOfHeaders;
- LPBYTE pbContent = NULL;
- BYTE cSaved = 0;
-
- if (pbStream != NULL && ctxtCall.m_bSendHeaders)
- {
- cSaved = pbStream[ctxtCall.m_dwEndOfHeaders];
- pbStream[ctxtCall.m_dwEndOfHeaders] = '\0';
- pbContent = &pbStream[ctxtCall.m_dwEndOfHeaders];
- }
-
- if (ctxtCall.m_bSendHeaders &&
- !ctxtCall.ServerSupportFunction(HSE_REQ_SEND_RESPONSE_HEADER,
- szResponse, 0, (LPDWORD) pbStream) &&
- ::GetLastError() != 10054) // WSAECONNRESET
- {
- pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
- dwRet = HSE_STATUS_ERROR;
- #ifdef _DEBUG
- DWORD dwCause = ::GetLastError();
- ISAPITRACE1("Error: Unable to write headers: 0x%8.8X!\n", dwCause);
- #endif
- }
- else
- {
- if (pbContent != NULL)
- {
- BOOL bWorked = TRUE;
-
- // write a newline to separate content from headers
-
- if (ctxtCall.m_bSendHeaders)
- {
- *pbContent = cSaved;
- DWORD dwNewLineSize = 2;
- bWorked = ctxtCall.WriteClient(_T("\r\n"), &dwNewLineSize, 0);
- }
-
- if (!bWorked || !OnWriteBody(&ctxtCall, pbContent, dwSize))
- {
- dwRet = HSE_STATUS_ERROR;
- pECB->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
- #ifdef _DEBUG
- DWORD dwCause = ::GetLastError();
- ISAPITRACE1("Error: Unable to write content body: 0x%8.8X!\n",
- dwCause);
- #endif
- }
- }
- else
- ISAPITRACE("Error: No body content!\n");
- }
-
- if (pbStream != NULL)
- ctxtCall.m_pStream->Free(pbStream);
-
- if (ctxtCall.m_dwStatusCode != DWORD(-1))
- dwRet = ctxtCall.m_dwStatusCode;
- if (dwRet == HSE_STATUS_SUCCESS)
- pECB->dwHttpStatusCode = HTTP_STATUS_OK;
-
- if (pszPostBuffer != NULL)
- delete [] pszPostBuffer;
-
- return dwRet;
- }
-
- void CHttpServer::BuildStatusCode(LPTSTR pszResponse, DWORD dwCode)
- {
- ISAPIASSERT(pszResponse != NULL);
- HTTPStatusInfo* pInfo = statusStrings;
-
- while (pInfo->pstrString != NULL)
- {
- if (dwCode == pInfo->dwCode)
- break;
- pInfo++;
- }
-
- if (pInfo->pstrString != NULL)
- wsprintf(pszResponse, _T("%d %s"), dwCode, pInfo->pstrString);
- else
- {
- ISAPIASSERT(dwCode != HTTP_STATUS_OK);
- ISAPITRACE1("Warning: Nonstandard status code %d\n", dwCode);
- BuildStatusCode(pszResponse, HTTP_STATUS_OK);
- }
- }
-
- BOOL CHttpServer::GetExtensionVersion(HSE_VERSION_INFO *pVer)
- {
- pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
- pVer->lpszExtensionDesc[0] = '\0';
- return TRUE;
- }
-
-
- CHttpServer::CHttpServer(TCHAR cDelimiter /* = '&' */)
- : m_cTokenDelimiter(cDelimiter)
- {
- ISAPIASSERT(pServer == NULL); // only one server instance
- pServer = this;
-
- // allocate our critical section directly to avoid bogus traces
- m_pCritSec = (LPCRITICAL_SECTION)
- LocalAlloc(LPTR, sizeof(CRITICAL_SECTION));
- ::InitializeCriticalSection(m_pCritSec);
- }
-
- CHttpServer::~CHttpServer()
- {
- if (m_pCritSec != NULL)
- {
- ::DeleteCriticalSection(m_pCritSec);
- LocalFree(m_pCritSec);
- }
- pServer = NULL;
- }
-
- BOOL CHttpServer::OnParseError(CHttpServerContext* pCtxt, int nMethodRet)
- {
- UNUSED(nMethodRet);
- UINT nResource = 0;
-
- if (pCtxt->m_pStream != NULL)
- {
- TCHAR szBuffer[132];
- TCHAR szTitle[256];
- TCHAR szFormat[256];
- LPCTSTR pszObject = NULL;
-
- switch (pCtxt->m_pECB->dwHttpStatusCode)
- {
- case HTTP_STATUS_BAD_REQUEST:
- nResource = AFX_IDS_HTTP_BAD_REQUEST;
- if (pCtxt->m_pECB->lpszQueryString)
- pszObject = pCtxt->m_pECB->lpszQueryString;
- else
- pszObject = pCtxt->m_pECB->lpszPathInfo;
- break;
-
- case HTTP_STATUS_AUTH_REQUIRED:
- nResource = AFX_IDS_HTTP_AUTH_REQUIRED;
- break;
-
- case HTTP_STATUS_FORBIDDEN:
- nResource = AFX_IDS_HTTP_FORBIDDEN;
- break;
-
- case HTTP_STATUS_NOT_FOUND:
- nResource = AFX_IDS_HTTP_NOT_FOUND;
- break;
-
- case HTTP_STATUS_SERVER_ERROR:
- nResource = AFX_IDS_HTTP_SERVER_ERROR;
- break;
-
- case HTTP_STATUS_NOT_IMPLEMENTED:
- nResource = AFX_IDS_HTTP_NOT_IMPLEMENTED;
- pszObject = pCtxt->m_pECB->lpszQueryString;
- break;
-
- default:
- nResource = AFX_IDS_HTTP_NO_TEXT;
- pszObject = (LPCTSTR) pCtxt->m_pECB->dwHttpStatusCode;
- break;
- }
-
- HINSTANCE hRes;
- hRes = AfxGetResourceHandle();
-
- #ifdef _AFXDLL
- if (AfxLoadString(nResource, szBuffer, sizeof(szBuffer)/sizeof(szBuffer[0])) > 0)
- #else
-
- if (::LoadString(hRes, nResource, szBuffer,
- sizeof(szBuffer)/sizeof(szBuffer[0])) > 0)
- #endif
- {
- pCtxt->Reset();
- CHttpServer::StartContent(pCtxt);
-
- if (::LoadString(hRes, AFX_IDS_HTTP_TITLE,
- szTitle, sizeof(szTitle)/sizeof(szTitle[0])) > 0)
- {
- TCHAR szTitleCopy[64];
- wsprintf(szTitleCopy, szTitle, pCtxt->m_pECB->dwHttpStatusCode);
- *pCtxt << szTitleCopy;
- }
-
- if (pszObject != NULL)
- {
- wsprintf(szFormat, szBuffer, pszObject);
- *pCtxt << szFormat;
- }
- else
- *pCtxt << szBuffer;
- CHttpServer::EndContent(pCtxt);
- }
- else
- {
- ISAPITRACE1("Error: Couldn't load string %d\n", nResource);
- nResource = 0;
- }
- }
-
- if (nResource == 0)
- ISAPITRACE1("Error: Unhandled parsing error code %d\n", nMethodRet);
-
- return nResource != 0;
- }
-
- void CHttpServer::AddHeader(CHttpServerContext* pCtxt,
- LPCTSTR pszString) const
- {
- #ifdef _DEBUG
- // Can't call AddHeader() after writing directly to the stream.
- ISAPIASSERT(pCtxt->m_dwOldEndOfHeaders == pCtxt->m_pStream->GetStreamSize());
- #endif
-
- *pCtxt << pszString;
- pCtxt->m_dwEndOfHeaders = pCtxt->m_pStream->GetStreamSize();
-
- #ifdef _DEBUG
- pCtxt->m_dwOldEndOfHeaders = pCtxt->m_dwEndOfHeaders;
- #endif
- }
-
- void CHttpServer::StartContent(CHttpServerContext* pCtxt) const
- {
- AddHeader(pCtxt, szContentType);
- }
-
- void CHttpServer::WriteTitle(CHttpServerContext* pCtxt) const
- {
- *pCtxt << szStartTitle;
- *pCtxt << GetTitle();
- *pCtxt << szEndTitle;
- }
-
- LPCTSTR CHttpServer::GetTitle() const
- {
- return szDefaultTitle;
- }
-
- void CHttpServer::EndContent(CHttpServerContext* pCtxt) const
- {
- *pCtxt << szEndBody;
- }
-
- BOOL CHttpServer::InitInstance(CHttpServerContext*)
- {
- return TRUE;
- }
-
- int CHttpServer::CallFunction(CHttpServerContext* pCtxt,
- LPTSTR pszQuery, LPTSTR pszCommand)
- {
- int nRet;
-
- AFX_PARSEMAP_ENTRY* pParams;
- const AFX_PARSEMAP* pMap;
- const AFX_PARSEMAP_ENTRY* pFn;
-
- ISAPIASSERT(pCtxt->m_pStream == NULL);
- pCtxt->m_pStream = ConstructStream();
- if (pCtxt->m_pStream == NULL)
- nRet = callNoStream;
- else
- {
- ISAPIASSERT(pszQuery != NULL);
- if (pszQuery == NULL)
- nRet = callBadCommand;
- else
- {
- LPTSTR pszMethod;
- LPTSTR pszParams;
-
- // did the user specify a command via "MfcISAPICommand"?
-
- LPTSTR pszHiddenCommand = _tcschr(pszQuery, '=');
- if (pszHiddenCommand != NULL)
- {
- *pszHiddenCommand = '\0';
-
- // is it there?
-
- if (lstrcmpi(pszQuery, _T("MfcISAPICommand")) == 0)
- {
- // did they have a method, too?
-
- pszMethod = pszHiddenCommand+1;
- if (*pszMethod == '\0')
- pszParams = pszMethod;
- else
- {
- pszParams = _tcschr(pszMethod, m_cTokenDelimiter);
- if (pszParams != NULL && *pszParams != '\0')
- *pszParams++ = '\0';
- }
-
- // if we find it, we can call it
-
- pFn = LookUp(pszMethod, pMap, pParams);
- if (pFn != NULL)
- goto MakeTheCall;
- }
-
- // we didn't find the command, or we didn't have
- // "MfcISAPICommand", so we'll try and process things
- // normally...
-
- *pszHiddenCommand = '=';
- }
-
- if (pszCommand == NULL)
- {
- // got something via a GET method
- // is the first thing a parameter or a command?
-
- LPTSTR pszEquals;
- LPTSTR pszQMark;
-
- pszParams = _tcschr(pszQuery, m_cTokenDelimiter);
- pszQMark = _tcschr(pszQuery, '?');
-
- // Parameters start at the first delimiter
-
- if (pszParams == NULL || (pszQMark != NULL && (pszQMark < pszParams)))
- {
- pszParams = pszQMark;
-
- // if the command ends in question mark
- // and nothing else, ignore it
- if (pszQMark != NULL && pszQMark[1] == '\0')
- {
- *pszQMark = '\0';
- pszParams = NULL;
- }
- }
-
- // Does an equals sign show up before the first delimiter?
-
- pszEquals = _tcschr(pszQuery, '=');
- if (pszEquals == NULL || pszEquals > pszParams)
- {
- // It might be a command. If it isn't blank,
- // try and find it in the parameter map--if
- // we can't, then assume it is a parameter.
-
- pszMethod = pszQuery;
- if (*pszMethod != '\0')
- {
- TCHAR cTemp = 0;
- if (pszParams != NULL)
- {
- cTemp = *pszParams;
- *pszParams++ = '\0';
- }
-
- pFn = LookUp(pszMethod, pMap, pParams);
- if (pFn != NULL)
- goto MakeTheCall;
-
- if (pszParams != NULL)
- *--pszParams = cTemp;
- }
- }
-
- // we can be sure it's a parameter
- if (pszQMark == NULL || pszQMark >= pszParams)
- {
- // default command, params as supplied
- pszMethod = NULL;
- pszParams = pszQuery;
- }
- else
- {
- pszMethod = pszQuery;
- *pszQMark++ = '\0';
- pszParams = pszQMark;
- }
- }
- else
- {
- // with a POST, the verb arrives seperately
- pszMethod = pszCommand;
- pszParams = pszQuery;
- }
-
- // is it a default verb?
- if (pszMethod != NULL && lstrlen(pszMethod) == 0)
- pszMethod = NULL;
-
- // is it a useless parameter?
- if (pszParams != NULL && lstrlen(pszParams) == 0)
- pszParams = NULL;
-
- pFn = LookUp(pszMethod, pMap, pParams);
-
- MakeTheCall:
- if (pFn == NULL)
- nRet = callBadCommand;
- else
- {
- pCtxt->m_pStream->InitStream();
- nRet = CallMemberFunc(pCtxt, pFn, pParams, pszParams);
- }
- }
- }
-
- return nRet;
- }
-
- CHtmlStream* CHttpServer::ConstructStream()
- {
- return new CHtmlStream();
- }
-
- const AFX_PARSEMAP_ENTRY* CHttpServer::LookUp(LPCTSTR pszMethod,
- const AFX_PARSEMAP*& pMap, AFX_PARSEMAP_ENTRY*& pParams,
- AFX_PISAPICMD pCmdDefault /* = NULL */)
- {
- UINT iEntry;
- LPCTSTR pszFnName;
- const AFX_PARSEMAP* pParseMap = GetParseMap();
- const AFX_PARSEMAP* pBaseMap;
- const AFX_PARSEMAP_ENTRY* pRet = NULL;
-
- while (pParseMap != NULL && pRet == NULL)
- {
- UINT cEntries = (*pParseMap->pfnGetNumMapEntries)();
- const AFX_PARSEMAP_ENTRY* pCurrent = pParseMap->lpEntries;
-
- for (iEntry = 0; iEntry < cEntries && pRet == NULL; iEntry++, pCurrent++)
- {
- #ifdef _DEBUG
- // make sure not 2 parameter maps in a row
-
- if (pCurrent->pfn == NULL && (iEntry+1 < cEntries))
- ISAPIASSERT(pCurrent[1].pfn != NULL);
- #endif
-
- // skip parameter maps
-
- if (pCurrent->pfn == NULL)
- continue;
-
- pszFnName = pCurrent->pszFnName;
-
- // if the caller wants the default command, find that--
- // if the caller wants something specific, perform a compare
- // otherwise, see if we recursed to look up the default command
-
- if (pCmdDefault == NULL)
- {
- if (pszMethod == NULL && pCurrent->pszArgs == NULL)
- pRet = pCurrent;
- else if (pszMethod != NULL && pCurrent->pszArgs != NULL
- && lstrcmpi(pszFnName, pszMethod) == 0)
- pRet = pCurrent;
- }
- else if (pCurrent->pfn == pCmdDefault && pCurrent->pszArgs != NULL)
- pRet = pCurrent;
-
- if (pRet != NULL)
- {
- // if we need the default, recurse to find it by name
- if (pszMethod == NULL && pCmdDefault == NULL)
- return LookUp(NULL, pMap, pParams, pCurrent->pfn);
-
- // found it! see if there are parameters
-
- if (iEntry+1 >= cEntries || pCurrent[1].pfn != NULL)
- {
- pParams = NULL;
- pMap = NULL;
- }
- else
- {
- pParams = (AFX_PARSEMAP_ENTRY*) &(pCurrent[1]);
- pMap = pParseMap;
- }
- }
- }
-
- #ifdef _AFXDLL
- pBaseMap = (*pParseMap->pfnGetBaseMap)();
- #else
- pBaseMap = pParseMap->pBaseMap;
- #endif
-
- // catch simple mistake of BEGIN_PARSE_MAP(CMyClass, CMyClass)
- ISAPIASSERT(pBaseMap != pParseMap);
- pParseMap = pBaseMap;
- }
-
- // no matching entry ?
- if (pRet == NULL)
- ISAPITRACE1("Warning: no handler for command '%s'\n", pszMethod);
- return pRet;
- }
-
- UINT PASCAL CHttpServer::GetStackSize(const BYTE* pbParams)
- {
- // size of arguments on stack when pushed by value
- static const UINT rgnByValue[] =
- {
- sizeof(_STACK_INT), // ITS_I2
- sizeof(_STACK_LONG), // ITS_I4
- sizeof(_STACK_FLOAT), // ITS_R4
- sizeof(_STACK_DOUBLE), // ITS_R8
- sizeof(LPCTSTR), // ITS_PSTR
- 0, // ITS_EMPTY
- sizeof(LPCTSTR)+sizeof(_STACK_INT), // ITS_RAW
- };
- // sizeof 'this' pointer
- UINT nCount = sizeof(CHttpServer*);
- #ifdef _ALIGN_STACK
- nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
- #endif
-
- // count arguments
- ISAPIASSERT(pbParams != NULL);
- while (*pbParams != 0 && *pbParams != IT_EMPTY)
- {
- // align if necessary
- // get and add appropriate byte count
-
- #ifdef _ALIGN_DOUBLES
- // align doubles on 8 byte for some platforms
- if (*pbParams == IT_R8)
- nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
- #endif
-
- // *pbParams must fit in the rgnByValue array
- ISAPIASSERT(*pbParams >= 1 && *pbParams <= sizeof(rgnByValue)/sizeof(UINT));
- nCount += rgnByValue[*pbParams-1];
-
- #ifdef _ALIGN_STACK
- nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
- #endif
- ++pbParams;
- }
- #if defined(_ALIGN_DOUBLES) && defined(_SHADOW_DOUBLES)
- // align doubles on 8 byte for some platforms
- nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
- #endif
- return nCount;
- }
-
-
- // indirect call helper (see OLECALL.CPP for implementation)
-
- extern "C" DWORD AFXISAPI
- _AfxParseCall(AFX_PISAPICMD pfn, void* pArgs, UINT nSizeArgs);
-
- // invoke standard method given IDispatch parameters/return value, etc.
-
- int CHttpServer::CallMemberFunc(CHttpServerContext* pCtxt,
- const AFX_PARSEMAP_ENTRY* pEntry,
- AFX_PARSEMAP_ENTRY* pParams, LPTSTR pszParams)
- {
- ISAPIASSERT(NULL != pEntry);
- AFX_PISAPICMD pFunc = pEntry->pfn;
- ISAPIASSERT(NULL != pFunc);
- int nRet = callOK;
-
- // get default function and parameters
- BYTE bNoParams = 0;
-
- ::EnterCriticalSection(m_pCritSec);
- const BYTE* pbParams = (const BYTE*)pEntry->pszArgs;
- if (NULL == pbParams)
- pbParams = &bNoParams;
- UINT nParams = lstrlenA((LPCSTR)pbParams);
-
- AFX_PARSEMAP_ENTRY_PARAMS *pDefaultParams = NULL;
- if (pParams != NULL)
- {
- if (pParams->pszFnName == NULL)
- nRet = ParseDefaultParams(pParams, nParams, pDefaultParams, pbParams);
- else
- pDefaultParams = (AFX_PARSEMAP_ENTRY_PARAMS*) pParams->pszFnName;
- }
- ::LeaveCriticalSection(m_pCritSec);
-
- if (nRet == callOK)
- {
- // get default function and return value information
- AFX_PISAPICMD pfn = pEntry->pfn;
-
- // determine size of arguments and allocate stack space
- // include space for our context pointer
- UINT nSizeArgs = GetStackSize(pbParams) + sizeof(_STACK_PTR);
- ISAPIASSERT(nSizeArgs != 0);
-
- if (nSizeArgs < _STACK_MIN)
- nSizeArgs = _STACK_MIN;
- BYTE* pStack = (BYTE*)_alloca(nSizeArgs + _SCRATCH_SIZE);
- if (pStack == NULL)
- {
- ISAPITRACE0("Error: stack overflow in CHttpServer::CallMemberFunc()!\n");
- return callNoStackSpace;
- }
-
- if (pDefaultParams != NULL)
- #ifndef _SHADOW_DOUBLES
- nRet = PushDefaultStackArgs(pStack, pCtxt, pbParams, pszParams,
- pDefaultParams);
- #else
- nRet = PushDefaultStackArgs(pStack, pCtxt, pbParams, pszParams,
- pDefaultParams, nSizeArgs);
- #endif
- else
- #ifndef _SHADOW_DOUBLES
- nRet = PushStackArgs(pStack, pCtxt, pbParams, pszParams);
- #else
- nRet = PushStackArgs(pStack, pCtxt, pbParams, pszParams, nSizeArgs);
- #endif
- pStack += _STACK_OFFSET;
-
- if (nRet == 0)
- {
- DWORD (AFXISAPI *pfnInet)(AFX_PISAPICMD, void*, UINT) =
- &_AfxParseCall;
- pfnInet(pfn, pStack, nSizeArgs);
- }
- }
-
- return nRet;
- }
-
- int CHttpServer::CountParams(LPCTSTR pszCommandLine, int& nCount)
- {
- BOOL bInQuote = FALSE;
- BOOL bInSpace = TRUE;
- LPCTSTR pszWalker = pszCommandLine;
- int nRetCode = callOK;
-
- nCount = 0;
- if (pszCommandLine != NULL)
- {
- while (*pszWalker != '\0')
- {
- if (bInSpace)
- {
- // this is invalid syntax
- ISAPIASSERT(*pszWalker != '\'');
- if (*pszWalker == '\'')
- {
- nRetCode = callMissingQuote;
- break;
- }
-
- if (!_istspace(*pszWalker))
- {
- nCount++;
- bInSpace = FALSE;
- }
- }
- else
- {
- if (*pszWalker == '\'')
- bInQuote = !bInQuote;
- else if (!bInQuote &&
- (_istspace(*pszWalker) || *pszWalker == m_cTokenDelimiter))
- bInSpace = TRUE;
- }
-
- pszWalker++;
- }
-
- // can't have only whitespace
- if (nCount == 0 && bInSpace)
- {
- nRetCode = callMissingParams;
- ISAPIASSERT(nCount > 0 || !bInSpace);
- }
- // unclosed quoted string?
- else if (bInQuote)
- {
- nRetCode = callMissingQuote;
- ISAPIASSERT(!bInQuote);
- }
- }
-
- return nRetCode;
- }
-
- int CHttpServer::ParseDefaultParams(AFX_PARSEMAP_ENTRY* pParams,
- int nParams, AFX_PARSEMAP_ENTRY_PARAMS*& pBlock, const BYTE* pbParams)
- {
- int nRet = callOK;
-
- LPSTR pszWalker;
- BOOL bInQuote;
- BOOL bInSpace;
- BOOL bInEquals;
- BOOL bMandatory = TRUE;
-
- // only if we haven't done it already
-
- if (pParams->pszFnName == NULL)
- {
- AFX_PARSEMAP_ENTRY_PARAMS* pParBlock = NULL;
- ISAPIASSERT(pParams->pszParamInfo == NULL);
-
- // can't have empty param string
- ISAPIASSERT(*pParams->pszArgs != '\0');
-
- if (*pParams->pszArgs != '\0')
- {
- pParBlock = new AFX_PARSEMAP_ENTRY_PARAMS;
- pBlock = pParBlock;
- memset(pParBlock, 0, sizeof(AFX_PARSEMAP_ENTRY_PARAMS));
- pParams->pszFnName = (LPTSTR) pParBlock;
-
- // start by finding how many parameters we have
- nRet = CountParams(pParams->pszArgs, pParBlock->nParams);
- if (nRet == callOK)
- pParams->pszParamInfo = _tcsdup(pParams->pszArgs);
- }
-
- if (pParBlock == NULL || nRet != callOK)
- {
- if (nRet == callOK)
- nRet = callMissingParams;
- goto CleanUp;
- }
-
- // wrong number of parameters?
- if (nParams != pParBlock->nParams)
- {
- nRet = callBadParamCount;
- ISAPIASSERT(nParams == pParBlock->nParams);
- }
- // it's a winner!
- else
- {
- pParBlock->ppszInfo =
- new LPTSTR[pParBlock->nParams *2];
- pParBlock->ppszDefaults =
- new BYTE[pParBlock->nParams * sizeof(double)];
- pParBlock->ppszValues =
- new BYTE[pParBlock->nParams * sizeof(double)];
-
- bInQuote = FALSE;
- bInSpace = TRUE;
- bInEquals = FALSE;
- int nStorage = 0;
-
- for (pszWalker = pParams->pszParamInfo;
- *pszWalker != '\0'; pszWalker++)
- {
- if (bInSpace)
- {
- // this is invalid syntax
- ISAPIASSERT(*pszWalker != '\'' && *pszWalker != '=');
- if (*pszWalker == '\'' || *pszWalker == '=')
- {
- nRet = callMissingQuote;
- break;
- }
-
- if (!_istspace(*pszWalker))
- {
- pParBlock->ppszInfo[nStorage++] = pszWalker;
- bInSpace = FALSE;
- }
- }
- else
- {
- if (bInEquals)
- {
- if (_istspace(*pszWalker) && bInQuote)
- continue;
-
- if (*pszWalker == '\'' || _istspace(*pszWalker))
- {
- if (bInQuote || _istspace(*pszWalker))
- {
- *pszWalker = '\0';
- bInEquals = FALSE;
- bInSpace = TRUE;
- bInQuote = FALSE;
- }
- else
- {
- pParBlock->ppszInfo[nStorage-1]++;
- bInQuote = TRUE;
- }
- }
- }
- else
- {
- // parameter with no default
- if (_istspace(*pszWalker))
- {
- // can't have required param after optional params
- ISAPIASSERT(bMandatory);
- if (!bMandatory)
- {
- nRet = callBadParam;
- goto CleanUp;
- }
-
- *pszWalker = '\0';
- bInSpace = TRUE;
- pParBlock->ppszInfo[nStorage++] = NULL;
- }
- // end of parameter name with default
- else if (*pszWalker == '=')
- {
- bMandatory = FALSE;
- bInEquals = TRUE;
- *pszWalker = '\0';
- pParBlock->ppszInfo[nStorage++] = pszWalker+1;
- }
- // bad syntax--quote in param name
- else if (*pszWalker == '\'')
- {
- ISAPIASSERT(*pszWalker != '\'');
- nRet = callMissingQuote;
- break;
- }
- }
- }
- }
-
- // handle case of no default for final param
- if (nStorage & 1)
- pParBlock->ppszInfo[nStorage] = NULL;
-
- int nIndex;
- for (nIndex = 0; nIndex < pParBlock->nParams; nIndex++)
- {
- if (pParBlock->ppszInfo[2*nIndex+1] != NULL)
- #ifndef _SHADOW_DOUBLES
- StoreStackParameter(
- &pParBlock->ppszDefaults[sizeof(double) * nIndex],
- pbParams[nIndex], pParBlock->ppszInfo[2*nIndex+1]);
- #else
- StoreStackParameter(
- &pParBlock->ppszDefaults[sizeof(double) * nIndex],
- pbParams[nIndex], pParBlock->ppszInfo[2*nIndex+1],
- 0, FALSE);
- #endif
- else
- pParBlock->nRequired++;
- }
- }
- }
-
- CleanUp:
- return nRet;
- }
-
-
- // push arguments on stack appropriate for C++ call (compiler dependent)
- #ifndef _SHADOW_DOUBLES
- int CHttpServer::PushDefaultStackArgs(BYTE* pStack,
- CHttpServerContext* pCtxt,
- const BYTE* pbParams, LPTSTR pszParams,
- AFX_PARSEMAP_ENTRY_PARAMS* pDefParams)
- #else
- int CHttpServer::PushDefaultStackArgs(BYTE* pStack,
- CHttpServerContext* pCtxt,
- const BYTE* pbParams, LPTSTR pszParams,
- AFX_PARSEMAP_ENTRY_PARAMS* pDefParams, int nSizeArgs)
- #endif
- {
- ISAPIASSERT(pStack != NULL);
-
- LPTSTR pszCurParam = NULL;
- int nExplicit = 0;
- LPBYTE pFlags;
- int nPushedExplicit = 0;
- int nRetVal = callOK;
- LPTSTR pszLineEnd;
-
- // keep a list of flags to know what's pushed and what's not
-
- pFlags = new BYTE[pDefParams->nParams];
- memset(pFlags, 0, pDefParams->nParams);
-
- // C++ member functions use the __thiscall convention, where parameters
- // are pushed last to first. Assuming the stack grows down, this means
- // that the first parameter is at the lowest memory address in the
- // stack frame and the last parameter is at the highest address.
-
- // push the 'this' pointer
-
- *(_STACK_PTR*)pStack = (_STACK_PTR)this;
- pStack += sizeof(_STACK_PTR);
-
- // push our context pointer
-
- *(_STACK_PTR*)pStack = (_STACK_PTR)pCtxt;
- pStack += sizeof(_STACK_PTR);
-
- // copy the default argument list to the usable argument list
- memcpy(pDefParams->ppszValues, pDefParams->ppszDefaults,
- sizeof(double) * pDefParams->nParams);
-
- // push the arguments, if explicitly supplied
-
- if (pszParams != NULL)
- {
- pszLineEnd = pszParams + lstrlen(pszParams);
-
- TCHAR szTokens[2];
- szTokens[0] = m_cTokenDelimiter;
- szTokens[1] = '\0';
-
- ISAPIASSERT(pbParams != NULL);
- for (const BYTE* pb = pbParams; *pb != '\0'; ++pb)
- {
- if (*pb == IT_EMPTY)
- {
- // can't have ITS_EMPTY with other types!
- ISAPIASSERT(pb == pbParams);
- break;
- }
-
- if (pszParams == NULL)
- break;
- pszCurParam = _tcstok(pszParams, szTokens);
- if (pszCurParam == NULL)
- break;
-
- // does this param have a name?
- LPTSTR pszValue = _tcschr(pszCurParam, '=');
- if (pszValue != NULL)
- {
- *pszValue++ = '\0';
-
- // find the parameter in our param block
-
- int nIndex;
- BOOL bFound = FALSE;
- for (nIndex = 0; nIndex < pDefParams->nParams; nIndex++)
- {
- if (lstrcmpi(pDefParams->ppszInfo[nIndex*2], pszCurParam) == 0)
- {
- bFound = TRUE;
- break;
- }
- }
-
- // something we don't recognize?
- if (!bFound)
- {
- nRetVal = callBadParam;
- goto CleanUp;
- }
-
- pszParams = pszValue + lstrlen(pszValue);
- if (pszParams != pszLineEnd)
- pszParams++;
-
- // if this parameter has a default and there's
- // no value for the parameter after the equal sign,
- // let the default value prevail
-
- if (*pszValue != '\0' ||
- pDefParams->ppszInfo[2*nIndex+1] == NULL)
- {
- #ifndef _SHADOW_DOUBLES
- StoreStackParameter(
- &(pDefParams->ppszValues[nIndex*sizeof(double)]),
- pbParams[nIndex], pszValue);
- #else
- StoreStackParameter(
- &(pDefParams->ppszValues[nIndex*sizeof(double)]),
- pbParams[nIndex], pszValue, 0, FALSE);
- #endif
-
- // if this has no default, it counts as explicit, too
- if (pDefParams->ppszInfo[2*nIndex+1] == NULL)
- nExplicit++;
- }
-
- // if we've already pushed this parameter, or if we've
- // already pushed this many explicit params, make an error
- if (pFlags[nIndex] != 0 || nIndex < nPushedExplicit)
- {
- nRetVal = callBadParam;
- goto CleanUp;
- }
- pFlags[nIndex] = 1;
- }
- else
- {
- // not allowed to have optional params before required params
- if (nExplicit != 0)
- {
- nRetVal = callBadParam;
- goto CleanUp;
- }
-
- pszParams += lstrlen(pszCurParam);
- if (pszParams != pszLineEnd)
- pszParams++;
-
- #ifndef _SHADOW_DOUBLES
- pStack = StoreStackParameter(pStack, *pb, pszCurParam);
- #else
- pStack = StoreStackParameter(pStack, *pb, pszCurParam,
- nSizeArgs, TRUE);
- #endif
-
- if (pFlags[nPushedExplicit] != 0)
- {
- nRetVal = callBadParam;
- goto CleanUp;
- }
- pFlags[nPushedExplicit] = 1;
- nPushedExplicit++;
- }
- }
-
- // any unused parameters?
-
- LPTSTR pszMoreParams;
- pszMoreParams = _tcschr(pszParams, m_cTokenDelimiter);
-
- if (*pb == '\0' && (pszMoreParams != NULL || *pszParams != '\0'))
- {
- nRetVal = callBadParamCount;
- goto CleanUp;
- }
- }
-
- // were any arguments without defaults missed?
- if (nPushedExplicit + nExplicit < pDefParams->nRequired)
- {
- nRetVal = callBadParamCount;
- }
- else if (nPushedExplicit < pDefParams->nParams)
- {
- int nIndex;
- for (nIndex = nPushedExplicit; nIndex < pDefParams->nParams; nIndex++)
- {
- #ifndef _SHADOW_DOUBLES
- pStack = StoreRawStackParameter(pStack,
- pbParams[nIndex],
- &(pDefParams->ppszValues[nIndex*sizeof(double)]));
- #else
- pStack = StoreRawStackParameter(pStack,
- pbParams[nIndex],
- &(pDefParams->ppszValues[nIndex*sizeof(double)]), 0);
- #endif
- }
- }
-
- CleanUp:
- if (pFlags != NULL)
- delete [] pFlags;
- return nRetVal;
- }
-
-
- // push arguments on stack appropriate for C++ call (compiler dependent)
- #ifndef _SHADOW_DOUBLES
- int CHttpServer::PushStackArgs(BYTE* pStack, CHttpServerContext* pCtxt,
- const BYTE* pbParams, LPTSTR pszParams)
- #else
- int CHttpServer::PushStackArgs(BYTE* pStack, CHttpServerContext* pCtxt,
- const BYTE* pbParams, LPTSTR pszParams, UINT nSizeArgs)
- #endif
- {
- LPTSTR pszCurParam = NULL;
- ISAPIASSERT(pStack != NULL);
-
- // C++ member functions use the __thiscall convention, where parameters
- // are pushed last to first. Assuming the stack grows down, this means
- // that the first parameter is at the lowest memory address in the
- // stack frame and the last parameter is at the highest address.
-
- // push the 'this' pointer
-
- *(_STACK_PTR*)pStack = (_STACK_PTR)this;
- pStack += sizeof(_STACK_PTR);
-
- // push our context pointer
-
- *(_STACK_PTR*)pStack = (_STACK_PTR)pCtxt;
- pStack += sizeof(_STACK_PTR);
-
- // push the arguments (first to last, low address to high address)
-
- TCHAR szTokens[2];
- szTokens[0] = m_cTokenDelimiter;
- szTokens[1] = '\0';
- const BYTE* pb;
- int nRetCode = callOK;
-
- if (pszParams != NULL && *pbParams == IT_EMPTY)
- nRetCode = callBadParamCount;
- else if (pszParams != NULL)
- {
- LPTSTR pszLineEnd;
- pszLineEnd = pszParams + lstrlen(pszParams);
-
- ISAPIASSERT(pbParams != NULL);
- for (pb = pbParams; *pb != '\0'; ++pb)
- {
- if (*pb == IT_EMPTY)
- {
- // can't have ITS_EMPTY with other types!
- ISAPIASSERT(pb == pbParams);
- if (pb != pbParams)
- nRetCode = callBadParam;
- break;
- }
-
- if (*pb == IT_RAW)
- {
- // can't have ITS_RAW with other types!
- ISAPIASSERT(pb == pbParams);
- if (pb != pbParams)
- nRetCode = callBadParam;
- else
- {
- BYTE* pbParam = (BYTE*) &pszParams;
- #ifndef _SHADOW_DOUBLES
- pStack = StoreRawStackParameter(pStack, IT_PSTR, pbParam);
- pStack = StoreRawStackParameter(pStack, IT_I4,
- (BYTE*) &(pCtxt->m_dwBytesReceived));
- #else
- pStack = StoreRawStackParameter(pStack, IT_PSTR, pbParam);
- pStack = StoreRawStackParameter(pStack, IT_I4,
- (BYTE*) &(pCtxt->m_dwBytesReceived));
- #endif
- }
- return nRetCode;
- }
-
- if (pszParams == NULL)
- break;
- pszCurParam = _tcstok(pszParams, szTokens);
- if (pszCurParam == NULL)
- break;
-
- pszParams = pszCurParam + lstrlen(pszCurParam);
- if (pszParams != pszLineEnd)
- pszParams++;
-
- #ifndef _SHADOW_DOUBLES
- pStack = StoreStackParameter(pStack, *pb, pszCurParam);
- #else
- pStack = StoreStackParameter(pStack, *pb, pszCurParam, nSizeArgs, TRUE);
- #endif
- }
-
- // check that all source arguments were consumed
-
- if (nRetCode == callOK)
- {
- LPTSTR pszMoreParams;
- pszMoreParams = _tcschr(pszParams, m_cTokenDelimiter);
-
- if (*pb != '\0' && pszMoreParams == NULL)
- nRetCode = callBadParamCount;
- else if (*pb == '\0' && (pszMoreParams != NULL || *pszParams != '\0'))
- nRetCode = callBadParamCount;
- }
- }
- else
- {
- if (*pbParams != IT_EMPTY)
- nRetCode = callBadParamCount;
- }
-
- return nRetCode;
- }
-
- #ifndef _SHADOW_DOUBLES
- BYTE* CHttpServer::StoreRawStackParameter(BYTE* pStack, BYTE nType,
- BYTE* pRawParam)
- #else
- BYTE* CHttpServer::StoreRawStackParameter(BYTE* pStack, BYTE nType,
- BYTE* pRawParam, int nSizeArgs)
- #endif
- {
- ISAPIASSERT(pStack != NULL);
- ISAPIASSERT(pRawParam != NULL);
-
- #ifdef _SHADOW_DOUBLES
- double* pDoubleShadow = (double*)(pStack + nSizeArgs);
- double* pDoubleShadowMax = pDoubleShadow + _SHADOW_DOUBLES;
- #endif
-
- // push parameter value on the stack
- switch (nType)
- {
- // by value parameters
- case IT_I2:
- *(_STACK_INT*)pStack = *((WORD*) pRawParam);
- pStack += sizeof(_STACK_INT); // 'short' is passed as 'int'
- break;
- case IT_I4:
- *(_STACK_LONG*)pStack = *((DWORD*) pRawParam);
- pStack += sizeof(_STACK_LONG);
- break;
- case IT_R4:
- *(_STACK_FLOAT*)pStack = *((_STACK_FLOAT*) pRawParam);
- pStack += sizeof(_STACK_FLOAT);
- #ifdef _SHADOW_DOUBLES
- if (pDoubleShadow < pDoubleShadowMax)
- *pDoubleShadow++ = *((_STACK_DOUBLE*) pRawParam);
- #endif
- break;
- case IT_R8:
- #ifdef _ALIGN_DOUBLES
- // align doubles on 8 byte for some platforms
- pStack = (BYTE*)(((DWORD)pStack + _ALIGN_DOUBLES-1) &
- ~(_ALIGN_DOUBLES-1));
- #endif
- *(_STACK_DOUBLE*)pStack = *((_STACK_DOUBLE*) pRawParam);
- pStack += sizeof(_STACK_DOUBLE);
- #ifdef _SHADOW_DOUBLES
- if (pDoubleShadow < pDoubleShadowMax)
- *pDoubleShadow++ = *((_STACK_DOUBLE*) pRawParam);
- #endif
- break;
- case IT_PSTR:
- *(_STACK_PTR*)pStack = *((_STACK_PTR*) pRawParam);
- pStack += sizeof(_STACK_PTR);
- break;
- default:
- ISAPIASSERT(FALSE);
- }
-
- #ifdef _ALIGN_STACK
- // align stack as appropriate for next parameter
- pStack = (BYTE*)(((DWORD)pStack + (_ALIGN_STACK-1)) &
- ~(_ALIGN_STACK-1));
- ISAPIASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
- #endif
-
- return pStack;
- }
-
- #ifndef _SHADOW_DOUBLES
- BYTE* CHttpServer::StoreStackParameter(BYTE* pStack, BYTE nType,
- LPTSTR pszCurParam)
- #else
- BYTE* CHttpServer::StoreStackParameter(BYTE* pStack, BYTE nType,
- LPTSTR pszCurParam, UINT nSizeArgs, BOOL bDoShadow)
- #endif
- {
- ISAPIASSERT(pStack != NULL);
- ISAPIASSERT(pszCurParam != NULL);
-
- #ifdef _SHADOW_DOUBLES
- double* pDoubleShadow = (double*)(pStack + nSizeArgs);
- double* pDoubleShadowMax = pDoubleShadow + _SHADOW_DOUBLES;
- #endif
-
- // push parameter value on the stack
- switch (nType)
- {
- // by value parameters
- case IT_I2:
- *(_STACK_INT*)pStack = (WORD) _ttoi(pszCurParam);
- pStack += sizeof(_STACK_INT); // 'short' is passed as 'int'
- break;
- case IT_I4:
- *(_STACK_LONG*)pStack = (DWORD) _ttol(pszCurParam);
- pStack += sizeof(_STACK_LONG);
- break;
- case IT_R4:
- *(_STACK_FLOAT*)pStack = (_STACK_FLOAT) atof(pszCurParam);
- pStack += sizeof(_STACK_FLOAT);
- #ifdef _SHADOW_DOUBLES
- if (bDoShadow && pDoubleShadow < pDoubleShadowMax)
- *pDoubleShadow++ = (double) atof(pszCurParam);
- #endif
- break;
- case IT_R8:
- #ifdef _ALIGN_DOUBLES
- // align doubles on 8 byte for some platforms
- pStack = (BYTE*)(((DWORD)pStack + _ALIGN_DOUBLES-1) &
- ~(_ALIGN_DOUBLES-1));
- #endif
- *(_STACK_DOUBLE*)pStack = (_STACK_DOUBLE) atof(pszCurParam);
- pStack += sizeof(_STACK_DOUBLE);
- #ifdef _SHADOW_DOUBLES
- if (bDoShadow && pDoubleShadow < pDoubleShadowMax)
- *pDoubleShadow++ = atof(pszCurParam);
- #endif
- break;
- case IT_PSTR:
- *(_STACK_PTR*)pStack = (_STACK_PTR) PreprocessString(pszCurParam);
- pStack += sizeof(_STACK_PTR);
- break;
- default:
- ISAPIASSERT(FALSE);
- }
-
- #ifdef _ALIGN_STACK
- // align stack as appropriate for next parameter
- pStack = (BYTE*)(((DWORD)pStack + (_ALIGN_STACK-1)) &
- ~(_ALIGN_STACK-1));
- ISAPIASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
- #endif
-
- return pStack;
- }
-
- LPVOID CHttpServer::PreprocessString(LPTSTR psz)
- {
- LPTSTR pszSource = psz;
- LPTSTR pszDest = psz;
-
- static const TCHAR szHex[] = _T("0123456789ABCDEF");
-
- // unescape special characters
-
- while (*pszSource != '\0')
- {
- if (*pszSource == '+')
- *pszDest++ = ' ';
- else if (*pszSource == '%')
- {
- TCHAR nValue = '?';
- LPCTSTR pszLow;
- LPCTSTR pszHigh;
- pszSource++;
-
- *pszSource = (TCHAR) _totupper(*pszSource);
- pszHigh = _tcschr(szHex, *pszSource);
-
- if (pszHigh != NULL)
- {
- pszSource++;
- *pszSource = (TCHAR) _totupper(*pszSource);
- pszLow = _tcschr(szHex, *pszSource);
- if (pszLow != NULL)
- {
- nValue = (TCHAR) (((pszHigh - szHex) << 4) +
- (pszLow - szHex));
- }
-
- }
-
- *pszDest++ = nValue;
- }
- else
- *pszDest++ = *pszSource;
- pszSource++;
- }
- *pszDest = '\0';
- return (LPVOID) psz;
- }
-
- ///////////////////////////////////////////////////////////////////////
- // in-memory HTML Stream
-
- CHtmlStream::CHtmlStream(UINT nGrowBytes /* = 4096 */)
- {
- ISAPIASSERT(nGrowBytes <= UINT_MAX && nGrowBytes >= 0);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = 0;
- m_lpBuffer = NULL;
- m_bAutoDelete = TRUE;
- m_nStreamSize = 0;
- }
-
- CHtmlStream::CHtmlStream(BYTE* lpBuffer, UINT nBufferSize,
- UINT nGrowBytes /* = 0 */)
- {
- ISAPIASSERT(nGrowBytes <= UINT_MAX && nGrowBytes >= 0);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = nBufferSize;
-
- // if the caller provides a grow-by size, use it;
- // otherwise, incrememt by the initial buffer size
- m_nStreamSize = nGrowBytes == 0 ? nBufferSize : 0;
-
- m_lpBuffer = lpBuffer;
- m_bAutoDelete = FALSE;
- }
-
- void CHtmlStream::Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
- {
- ISAPIASSERT(m_lpBuffer == NULL);
-
- m_nGrowBytes = nGrowBytes;
- m_nPosition = 0;
- m_nBufferSize = nBufferSize;
-
- // if the caller provides a grow-by size, use it;
- // otherwise, incrememt by the initial buffer size
- m_nStreamSize = nGrowBytes == 0 ? nBufferSize : 0;
-
- m_lpBuffer = lpBuffer;
- m_bAutoDelete = FALSE;
- }
-
- BYTE* CHtmlStream::Detach()
- {
- BYTE* lpBuffer = NULL;
- if (m_lpBuffer != NULL)
- {
- TCHAR chZero = 0;
- Write(&chZero, sizeof(TCHAR));
- lpBuffer = m_lpBuffer;
- m_lpBuffer = NULL;
- }
- m_nBufferSize = 0;
- m_nStreamSize = 0;
- m_nPosition = 0;
-
- return lpBuffer;
- }
-
- CHtmlStream::~CHtmlStream()
- {
- // Close should have already been called, but we check anyway
- if (m_lpBuffer)
- Close();
- ISAPIASSERT(NULL == m_lpBuffer);
-
- m_nGrowBytes = 0;
- m_nPosition = 0;
- m_nStreamSize = 0;
- m_nBufferSize = 0;
- }
-
- BYTE* CHtmlStream::Alloc(DWORD nBytes)
- {
- return (BYTE*)malloc((UINT)nBytes);
- }
-
- BYTE* CHtmlStream::Realloc(BYTE* lpMem, DWORD nBytes)
- {
- return (BYTE*)realloc(lpMem, (UINT)nBytes);
- }
-
- #pragma intrinsic(memcpy)
- BYTE* CHtmlStream::Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
- UINT nBytes)
- {
- ISAPIASSERT(lpMemTarget != NULL);
- ISAPIASSERT(lpMemSource != NULL);
-
- return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
- }
- #pragma function(memcpy)
-
- void CHtmlStream::Free(BYTE* lpMem)
- {
- ISAPIASSERT(lpMem != NULL);
- free(lpMem);
- }
-
- void CHtmlStream::GrowStream(DWORD dwNewLen)
- {
- if (dwNewLen > m_nBufferSize)
- {
- // grow the buffer
- DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
-
- // watch out for buffers which cannot be grown!
- ISAPIASSERT(m_nGrowBytes > 0);
- if (m_nGrowBytes == 0)
- throw;
-
- // determine new buffer size
- while (dwNewBufferSize < dwNewLen)
- dwNewBufferSize += m_nGrowBytes;
-
- // allocate new buffer
- BYTE* lpNew;
- if (m_lpBuffer == NULL)
- lpNew = Alloc(dwNewBufferSize);
- else
- lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
-
- if (lpNew == NULL)
- throw;
-
- m_lpBuffer = lpNew;
- m_nBufferSize = dwNewBufferSize;
- }
- }
-
- CHtmlStream& CHtmlStream::operator<<(LPCTSTR psz)
- {
- Write(psz, lstrlen(psz));
- return *this;
- }
-
- CHtmlStream& CHtmlStream::operator<<(short int w)
- {
- TCHAR sz[16];
- int nLen = wsprintf(sz, szDecimalFormat, w);
- Write(sz, nLen);
- return *this;
- }
-
- CHtmlStream& CHtmlStream::operator<<(long int dw)
- {
- TCHAR sz[16];
- int nLen = wsprintf(sz, szDecimalFormat, dw);
- Write(sz, nLen);
- return *this;
- }
-
- CHtmlStream& CHtmlStream::operator<<(float f)
- {
- TCHAR sz[64];
- int nLen = _stprintf(sz, szFloatFormat, f);
- Write(sz, nLen);
- return *this;
- }
-
- CHtmlStream& CHtmlStream::operator<<(double d)
- {
- TCHAR sz[64];
- int nLen = _stprintf(sz, szFloatFormat, d);
- Write(sz, nLen);
- return *this;
- }
-
- CHtmlStream& CHtmlStream::operator<<(const CHtmlStream& stream)
- {
- DWORD dwSourceLen = stream.GetStreamSize();
- Write(stream.m_lpBuffer, dwSourceLen);
- return *this;
- }
-
- void CHtmlStream::Close()
- {
- m_nGrowBytes = 0;
- m_nPosition = 0;
- m_nBufferSize = 0;
- m_nStreamSize = 0;
- if (m_lpBuffer && m_bAutoDelete)
- Free(m_lpBuffer);
- m_lpBuffer = NULL;
- }
-
- void CHtmlStream::Abort()
- {
- Close();
- }
-
- void CHtmlStream::Write(const void* lpBuf, UINT nCount)
- {
- if (nCount == 0)
- return;
- ISAPIASSERT(lpBuf != NULL);
-
- if (m_nPosition + nCount > m_nBufferSize)
- GrowStream(m_nPosition + nCount);
-
- ISAPIASSERT(m_nPosition + nCount <= m_nBufferSize);
-
- Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
-
- m_nPosition += nCount;
-
- if (m_nPosition > m_nStreamSize)
- m_nStreamSize = m_nPosition;
- }
-
- void CHtmlStream::Reset()
- {
- m_nPosition = 0;
- m_nStreamSize = 0;
- }
-
- void CHtmlStream::InitStream()
- {
- // subclass can override for interesting applications
- }
-
- ///////////////////////////////////////////////////////////////////////
- // HTTP Filter entry points
-
- extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc,
- DWORD dwNotificationType, LPVOID pvNotification)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- #endif
-
- DWORD dwRet;
-
- ISAPIASSERT(pFilter != NULL);
- if (pFilter == NULL)
- dwRet = SF_STATUS_REQ_NEXT_NOTIFICATION;
- else
- dwRet = pFilter->HttpFilterProc(pfc,
- dwNotificationType, pvNotification);
-
- return dwRet;
- }
-
- extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
- {
- #ifdef _AFXDLL
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
- #endif
-
- BOOL bRet;
-
- ISAPIASSERT(pFilter != NULL);
- if (pFilter == NULL)
- bRet = FALSE;
- else
- bRet = pFilter->GetFilterVersion(pVer);
-
- return bRet;
- }
-
-
- ///////////////////////////////////////////////////////////////////////
- // CHttpFilter implementation
-
- CHttpFilter::CHttpFilter()
- {
- ISAPIASSERT(pFilter == NULL);
- pFilter = this;
- }
-
- CHttpFilter::~CHttpFilter()
- {
- pFilter = NULL;
- }
-
- BOOL CHttpFilter::GetFilterVersion(PHTTP_FILTER_VERSION pVer)
- {
- pVer->dwFlags = SF_NOTIFY_ORDER_DEFAULT;
- pVer->dwFilterVersion = HTTP_FILTER_REVISION;
- pVer->lpszFilterDesc[0] = '\0';
- return TRUE;
- }
-
- DWORD CHttpFilter::HttpFilterProc(PHTTP_FILTER_CONTEXT pfc,
- DWORD dwNotificationType, LPVOID pvNotification)
- {
- DWORD dwRet = SF_STATUS_REQ_NEXT_NOTIFICATION;
- CHttpFilterContext callCtxt(pfc);
-
- switch (dwNotificationType)
- {
- case SF_NOTIFY_READ_RAW_DATA:
- dwRet = OnReadRawData(&callCtxt, (PHTTP_FILTER_RAW_DATA) pvNotification);
- break;
-
- case SF_NOTIFY_PREPROC_HEADERS:
- dwRet = OnPreprocHeaders(&callCtxt,
- (PHTTP_FILTER_PREPROC_HEADERS) pvNotification);
- break;
-
- case SF_NOTIFY_AUTHENTICATION:
- dwRet = OnAuthentication(&callCtxt,
- (PHTTP_FILTER_AUTHENT) pvNotification);
- break;
-
- case SF_NOTIFY_URL_MAP:
- dwRet = OnUrlMap(&callCtxt, (PHTTP_FILTER_URL_MAP) pvNotification);
- break;
-
- case SF_NOTIFY_SEND_RAW_DATA:
- dwRet = OnSendRawData(&callCtxt, (PHTTP_FILTER_RAW_DATA) pvNotification);
- break;
-
- case SF_NOTIFY_LOG:
- dwRet = OnLog(&callCtxt, (PHTTP_FILTER_LOG) pvNotification);
- break;
-
- case SF_NOTIFY_END_OF_NET_SESSION:
- dwRet = OnEndOfNetSession(&callCtxt);
- break;
-
- case SF_NOTIFY_END_OF_REQUEST:
- dwRet = OnEndOfRequest(&callCtxt);
- break;
-
- default:
- ISAPITRACE1("Warning: unrecognized HTTP filter notification code %d\n", dwNotificationType);
- break;
- }
-
- return dwRet;
- }
-
- // The user will override these. Here, the functions have no
- // formal parameters to avoid warnings.
-
- DWORD CHttpFilter::OnReadRawData(CHttpFilterContext*, PHTTP_FILTER_RAW_DATA)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnPreprocHeaders(CHttpFilterContext*, PHTTP_FILTER_PREPROC_HEADERS)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnAuthentication(CHttpFilterContext*, PHTTP_FILTER_AUTHENT)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnUrlMap(CHttpFilterContext*, PHTTP_FILTER_URL_MAP)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnSendRawData(CHttpFilterContext*, PHTTP_FILTER_RAW_DATA)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnLog(CHttpFilterContext*, PHTTP_FILTER_LOG)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnEndOfNetSession(CHttpFilterContext*)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
- DWORD CHttpFilter::OnEndOfRequest(CHttpFilterContext*)
- {
- return SF_STATUS_REQ_NEXT_NOTIFICATION;
- }
-
-
- ///////////////////////////////////////////////////////////////////////
- // tracing helper function for linking without MFC
-
- #ifndef _AFX
- #ifdef _DEBUG
-
- void AFXISAPI_CDECL AfxISAPITrace(LPCTSTR lpszFormat, ...)
- {
- va_list args;
- va_start(args, lpszFormat);
-
- // if the trace has been set to go to a window and the user
- // presses RETRY, we will break to the debugger here
-
- if (_CrtDbgReport(_CRT_WARN, NULL, 0, NULL, lpszFormat, args) == 1)
- _CrtDbgBreak();
-
- va_end(args);
- }
-
- #endif
- #endif
-
- ///////////////////////////////////////////////////////////////////////
- // handle inline functions
-
- #ifndef _AFX_ENABLE_INLINES
-
- static const char _szAfxWinInl[] = "isapi.inl";
- #undef THIS_FILE
- #define THIS_FILE _szAfxWinInl
- #define _AFXISAPI_INLINE
- #include "afxisapi.inl"
-
- #endif //!_AFX_ENABLE_INLINES
-