⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isapi.cpp

📁 vc6.0完整版
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				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];
		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, _countof(szBuffer)) > 0)
#else
		if (::LoadString(hRes, nResource, szBuffer, _countof(szBuffer)) > 0)
#endif
		{
			pCtxt->Reset();
			CHttpServer::StartContent(pCtxt);

			if (::LoadString(hRes, AFX_IDS_HTTP_TITLE, szTitle, _countof(szTitle)) > 0)
			{
				TCHAR szTitleCopy[512];
				_sntprintf(szTitleCopy, 512, szTitle, pCtxt->m_pECB->dwHttpStatusCode);
				szTitleCopy[511] = 0;
				*pCtxt << szTitleCopy;
			}

			if (pszObject != NULL)
			{
				TCHAR* pstrFormat = new TCHAR[lstrlen(szBuffer) + lstrlen(pszObject) + 1];
				if (pstrFormat != NULL)
				{
					wsprintf(pstrFormat, szBuffer, pszObject);
					*pCtxt << pstrFormat;
					delete [] pstrFormat;
				}
			}
			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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -