📄 filters.cpp
字号:
DEBUGMSG(ZONE_ERROR, (L"HTTPD: ISAPI Filter DLL <<%s>> caused exception 0x%08x\r\n",
g_pFilterCon->m_pFilters[i].wszDLLName, GetExceptionCode()));
g_pVars->m_pLog->WriteEvent(IDS_HTTPD_FILT_EXCEPTION,g_pFilterCon->m_pFilters[i].wszDLLName,GetExceptionCode(),L"HttpFilterProc",GetLastError());
m_fKeepAlive = FALSE;
myleave(216);
}
// bail out if another filter call said to, but not on certain events (for compat with IIS)
// This would happen if a filter triggered an event to occur which caused another filter call
// to be made, and if that nested filter returned an error code indicating the end of session.
if ( (! m_pFInfo->m_fFAccept) &&
! (dwNotifyType & (SF_NOTIFY_END_OF_REQUEST | SF_NOTIFY_LOG | SF_NOTIFY_END_OF_NET_SESSION | SF_NOTIFY_SEND_RESPONSE | SF_NOTIFY_SEND_RAW_DATA)))
{
DEBUGMSG(ZONE_ISAPI,(L"HTTPD: Filter indirectly set us to end, ending CallFilter for event= %x,i=%d\r\n",dwNotifyType,i));
myretleave(FALSE,0);
}
m_pFInfo->m_ppvContext[i] = fc.pFilterContext;
DEBUGMSG(ZONE_ISAPI, (L"HTTPD: Filter returned response code of 0x%08x\r\n",dwFilterCode));
switch (dwFilterCode) {
// alert calling class that this request + net session is over
case SF_STATUS_REQ_FINISHED:
m_fKeepAlive = FALSE;
m_pFInfo->m_fSentHeaders = TRUE; // don't send back headers in these cases.
myretleave(FALSE,0);
break;
// alert calling class that this request but not the net session is over
case SF_STATUS_REQ_FINISHED_KEEP_CONN:
m_fKeepAlive = TRUE;
m_pFInfo->m_fSentHeaders = TRUE; // don't send back headers in these cases.
myretleave(FALSE,0);
break;
// goes to top of loop, handle next filter in line
case SF_STATUS_REQ_NEXT_NOTIFICATION:
NEXTFILTER(dwNotifyType, i);
break;
// not an error, just done handling current httpd event
case SF_STATUS_REQ_HANDLED_NOTIFICATION:
myretleave(TRUE,0);
break;
// alert calling class that this request is over
case SF_STATUS_REQ_ERROR:
m_fKeepAlive = FALSE;
m_rs = STATUS_INTERNALERR;
myretleave(FALSE,214);
break;
case SF_STATUS_REQ_READ_NEXT:
// only valid for read raw data events. IIS ignores if returned by other filters
// Continue running through remaining filters before reading more data
if (dwNotifyType == SF_NOTIFY_READ_RAW_DATA) {
fReqReadNext = TRUE;
}
NEXTFILTER(dwNotifyType, i);
break;
default: // treat like SF_STATUS_REQ_NEXT_NOTIFICATION
DEBUGMSG(ZONE_ERROR, (L"HTTPD: Filter returned unknown/unhandled return code\r\n"));
NEXTFILTER(dwNotifyType, i);
break;
}
}
// Only after all filters have been serviced to we handle READ_NEXT event
// Note that having a filter call SF_READ_REQ_NEXT during a call to an
// ISAPI ext ReadClient is completly unsupported. This has been docced.
if (fReqReadNext) {
PHTTP_FILTER_RAW_DATA pRaw = (PHTTP_FILTER_RAW_DATA) pStFilter;
fFillStructs = TRUE; // set here in case we don't read any data and
// exit loop, so we don't call CleanupFC 2 times.
DEBUGCHK(dwNotifyType == SF_NOTIFY_READ_RAW_DATA);
CleanupFC(dwNotifyType, &pStFilter,&pStFilterOrg,ppszBuf1, pcbBuf, ppszBuf2);
m_bufRequest.RecvBody(m_socket,m_pFInfo->m_dwNextReadSize ? m_pFInfo->m_dwNextReadSize : g_pVars->m_dwPostReadSize,TRUE, FALSE, this, FALSE);
// only stop reading if we didn't get any data. Timeouts are OK, we'll call read filter again
if (m_bufRequest.UnaccessedCount() == 0)
fReqReadNext = FALSE;
else
m_pFInfo->m_dwBytesReceived += pRaw->cbInData; // from HTTP recv
}
} while (fReqReadNext);
ret = TRUE;
done:
DEBUGMSG_ERR(ZONE_ERROR, (L"HTTPD: CIsapiFilterCon::CallFilter FAILED: GLE=%d err=%d\r\n",
GetLastError(), err));
// Udpate our bytes sent/received if need be.
// Send bytes update must after we do our cleanup, Read bytes must happen before.
if (dwNotifyType == SF_NOTIFY_READ_RAW_DATA) {
// We only allocate pRaw if we need to (ie someone notified for read),
// if this is so use that value for rx bytes. If no one notefied for read filt, use
// the value we were passed for bytes read by calling fcn.
PHTTP_FILTER_RAW_DATA pRaw = (PHTTP_FILTER_RAW_DATA) pStFilter;
if (pRaw)
m_pFInfo->m_dwBytesReceived += pRaw->cbInData;
else if (ppszBuf1)
m_pFInfo->m_dwBytesReceived += *pcbBuf; // from ISAPI ReadClient
else
m_pFInfo->m_dwBytesReceived += m_bufRequest.UnaccessedCount(); // from HTTP recv
}
// fFillStructs will be false if no filter registered for this event, which means
// we have no cleanup
if (FALSE == fFillStructs)
ret = CleanupFC(dwNotifyType, &pStFilter,&pStFilterOrg,ppszBuf1, pcbBuf, ppszBuf2);
if (dwNotifyType == SF_NOTIFY_SEND_RAW_DATA)
m_pFInfo->m_dwBytesSent += *pcbBuf;
if (!ret) {
m_pFInfo->m_fFAccept = FALSE;
}
return ret;
}
// sets up the FilterContext data structure so it makes sense to filterr being called.
// Only called once per filter event.
// ppStFilter is sent to filter dlls.
// ppStFilterOrg is a copy, it stores what we've allocated and is used to free up mem, as
// the filter would cause server mem leaks without it as a reference
// Last three parameters are the same as CallFilter
BOOL CHttpRequest::FillFC(PHTTP_FILTER_CONTEXT pfc, DWORD dwNotifyType,
LPVOID *ppStFilter, LPVOID *ppStFilterOrg,
PSTR *ppszBuf1, int *pcbBuf, PSTR *ppszBuf2, int *pcbBuf2)
{
DEBUG_CODE_INIT;
BOOL ret = FALSE;
DEBUGCHK((*ppStFilterOrg) == NULL);
DEBUGCHK((*ppStFilter) == NULL);
switch (dwNotifyType) {
case SF_NOTIFY_END_OF_NET_SESSION:
case SF_NOTIFY_END_OF_REQUEST:
break;
case SF_NOTIFY_READ_RAW_DATA:
{
PHTTP_FILTER_RAW_DATA pRawData = NULL;
*ppStFilter = pRawData = MyAllocNZ(HTTP_FILTER_RAW_DATA);
if (!pRawData)
myleave(220);
// We use UnaccessedCount() rather than Count() member of Buffio class
// because we want the entire buffer for the Filter to read. For instance,
// if we had http headers and POST data, Count would only return the size
// of the headers, while UnaccessedCount returns the size of everything.
// We give filter the whole buffer. For IIS compat.
if (!ppszBuf1) { // Use buffer in CHttpResponse class
pRawData->cbInData = m_bufRequest.UnaccessedCount();
pRawData->cbInBuffer = m_bufRequest.AvailableBufferSize();
pRawData->pvInData = m_bufRequest.FilterRawData();
}
else { // Called from ISAPI ReadClient()
pRawData->cbInBuffer = *pcbBuf2;
pRawData->cbInData = *pcbBuf;
pRawData->pvInData = (PVOID) *ppszBuf1;
}
pRawData->dwReserved = 0;
*ppStFilterOrg = MyAllocNZ(HTTP_FILTER_RAW_DATA);
if (!(*ppStFilterOrg)) {
MyFree(pRawData);
*ppStFilter = NULL;
myleave(240);
}
memcpy(*ppStFilterOrg,*ppStFilter,sizeof(HTTP_FILTER_RAW_DATA));
}
break;
case SF_NOTIFY_PREPROC_HEADERS:
{
PHTTP_FILTER_PREPROC_HEADERS pPreProc = NULL;
*ppStFilter = pPreProc = MyAllocNZ(HTTP_FILTER_PREPROC_HEADERS);
*ppStFilterOrg = NULL;
if (!pPreProc)
myleave(221);
pPreProc->GetHeader = ::GetHeader;
pPreProc->SetHeader = ::SetHeader;
pPreProc->AddHeader = ::SetHeader;
pPreProc->HttpStatus = 0; // no response status code this return
pPreProc->dwReserved = 0;
}
break;
case SF_NOTIFY_URL_MAP:
{
PHTTP_FILTER_URL_MAP pUrlMap = NULL;
*ppStFilter = pUrlMap = MyAllocNZ(HTTP_FILTER_URL_MAP);
if (!pUrlMap)
myleave(222);
if (NULL == ppszBuf1) { // usual case, use data in CHttpRequest
pUrlMap->pszURL = m_pszURL;
pUrlMap->pszPhysicalPath = MySzDupWtoA(m_wszPath);
if (pUrlMap->pszPhysicalPath)
pUrlMap->cbPathBuff = MyStrlenA(pUrlMap->pszPhysicalPath);
}
else { // called from ISAPI ext with HSE_REQ_MAP_URL_TO_PATH
pUrlMap->pszURL = (PSTR) *ppszBuf1;
pUrlMap->pszPhysicalPath = (PSTR) *ppszBuf2;
pUrlMap->cbPathBuff = *pcbBuf;
}
*ppStFilterOrg = MyAllocNZ(HTTP_FILTER_URL_MAP);
if ( !pUrlMap->pszURL || ! pUrlMap->pszPhysicalPath || ! (*ppStFilterOrg)) {
if (NULL == ppszBuf1) // only in this case do we have to clean this up.
MyFree(pUrlMap->pszPhysicalPath);
MyFree((*ppStFilterOrg));
*ppStFilterOrg = NULL;
MyFree(pUrlMap);
*ppStFilter = NULL;
myleave(320);
}
memcpy(*ppStFilterOrg,*ppStFilter,sizeof(HTTP_FILTER_URL_MAP));
}
break;
case SF_NOTIFY_AUTHENTICATION:
{
DEBUGCHK(NULL != ppszBuf1 && NULL != ppszBuf2);
PHTTP_FILTER_AUTHENT pAuth = NULL;
*ppStFilter = pAuth = MyAllocNZ(HTTP_FILTER_AUTHENT);
if (!pAuth)
myleave(223);
// pszUser + pszPassword are static buffers made in AuthenticateFilter fcn
pAuth->pszUser = (PSTR) *ppszBuf1;
pAuth->cbUserBuff = SF_MAX_USERNAME;
pAuth->pszPassword = (PSTR) *ppszBuf2;
pAuth->cbPasswordBuff = SF_MAX_PASSWORD;
}
break;
case SF_NOTIFY_ACCESS_DENIED:
{
PHTTP_FILTER_ACCESS_DENIED pDenied = NULL;
*ppStFilter = pDenied = MyAllocNZ(HTTP_FILTER_ACCESS_DENIED);
if (!pDenied)
myleave(224);
pDenied->pszURL = m_pszURL;
pDenied->pszPhysicalPath = MySzDupWtoA(m_wszPath);
pDenied->dwReason = SF_DENIED_LOGON;
*ppStFilterOrg = MyAllocNZ(HTTP_FILTER_ACCESS_DENIED);
if (! pDenied->pszURL || ! pDenied->pszPhysicalPath || !(*ppStFilterOrg)) {
MyFree(pDenied->pszPhysicalPath);
MyFree((*ppStFilterOrg));
MyFree(pDenied);
*ppStFilter = NULL;
myleave(322);
}
memcpy(*ppStFilterOrg,*ppStFilter,sizeof(HTTP_FILTER_ACCESS_DENIED));
}
break;
case SF_NOTIFY_SEND_RESPONSE:
{
PHTTP_FILTER_SEND_RESPONSE pSendRes = NULL;
*ppStFilter = pSendRes = MyAllocNZ(HTTP_FILTER_PREPROC_HEADERS);
if (!pSendRes)
myleave(225);
pSendRes->GetHeader = ::GetHeader;
pSendRes->SetHeader = ::SetHeader;
pSendRes->AddHeader = ::SetHeader;
pSendRes->HttpStatus = rgStatus[m_rs].dwStatusNumber;
pSendRes->dwReserved = 0;
}
break;
case SF_NOTIFY_SEND_RAW_DATA:
{
PHTTP_FILTER_RAW_DATA pRawData = NULL;
*ppStFilter = pRawData = MyAllocNZ(HTTP_FILTER_RAW_DATA);
*ppStFilterOrg = MyAllocNZ(HTTP_FILTER_RAW_DATA);
if (!pRawData || !(*ppStFilterOrg)) {
MyFree(pRawData);
MyFree((*ppStFilterOrg));
*ppStFilter = *ppStFilterOrg = NULL;
myleave(220);
}
pRawData->pvInData = *ppszBuf1;
pRawData->cbInData = *pcbBuf;
pRawData->cbInBuffer = *pcbBuf;
pRawData->dwReserved = 0;
memcpy(*ppStFilterOrg,*ppStFilter,sizeof(HTTP_FILTER_RAW_DATA));
}
break;
case SF_NOTIFY_LOG:
{
PHTTP_FILTER_LOG pLog = NULL;
CHAR szHostBuf[MAX_PATH];
*ppStFilter = pLog = MyAllocZ(HTTP_FILTER_LOG);
if (!pLog)
myleave(226);
if (NULL == (pLog->pszClientHostName = (CHAR*)svsutil_AllocZ(LOG_REMOTE_ADDR_SIZE*sizeof(CHAR))))
goto cleanupFCLog;
GetRemoteAddress(m_socket,(PSTR) pLog->pszClientHostName,FALSE,LOG_REMOTE_ADDR_SIZE);
if ( 0 == gethostname(szHostBuf, sizeof(szHostBuf))) {
if (NULL == (pLog->pszServerName = MySzDupA(szHostBuf)))
goto cleanupFCLog;
}
else
pLog->pszServerName = cszEmpty;
pLog->pszClientUserName = m_pszRemoteUser;
pLog->pszOperation = m_pszMethod;
pLog->pszTarget = m_pszURL;
pLog->pszParameters = m_pszQueryString;
pLog->dwWin32Status = GetLastError();
pLog->dwBytesSent = m_pFInfo->m_dwBytesSent;
pLog->dwBytesRecvd = m_pFInfo->m_dwBytesReceived;
pLog->msTimeForProcessing = GetTickCount() - m_pFInfo->m_dwStartTick;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -