📄 isapi.cpp
字号:
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;
BYTE* ppszValues; // pointers to coerced actual values
// 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
ppszValues = new BYTE[pDefParams->nParams * sizeof(double)];
memcpy(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(
&(ppszValues[nIndex*sizeof(double)]),
pbParams[nIndex], pszValue);
#else
StoreStackParameter(
&(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],
&(ppszValues[nIndex*sizeof(double)]));
#else
pStack = StoreRawStackParameter(pStack,
pbParams[nIndex],
&(ppszValues[nIndex*sizeof(double)]), 0);
#endif
}
}
CleanUp:
if (pFlags != NULL)
delete [] pFlags;
if (ppszValues != NULL)
delete [] ppszValues;
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -