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

📄 filters.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: filters.cpp
Abstract: ISAPI Filter handling classes
--*/

#include "httpd.h"

CISAPIFilterCon* g_pFilterCon;

const DWORD g_fIsapiFilterModule = TRUE;


const LPCWSTR cwszFilterSep = L",";   // what seperates filter ids in the registry

//  Used to increment the filter, goes up 1 normally, down 1 for RAW DATA prio inversion
#define NEXTFILTER(dwNotifyType, i)     { (dwNotifyType == SF_NOTIFY_SEND_RAW_DATA) ? i-- : i++;}

void FreeLogParams(PHTTP_FILTER_LOG pLog);

//   Creates new filter info used globally
BOOL InitFilters() {
	g_pFilterCon = new CISAPIFilterCon();
	return (g_pFilterCon && g_pFilterCon->m_nFilters!=0);
}

//  Destroys the global filter information
void CleanupFilters() {	
	if (g_pFilterCon)
		delete g_pFilterCon;
	g_pFilterCon = 0;
}

CFilterInfo* CreateCFilterInfo(void) {
	if (0 == g_pFilterCon->m_nFilters)
		return NULL;

	return new CFilterInfo;
}

//  CFilterInfo is an internal member of CHttpRequest.  Allocate buffers for it
CFilterInfo::CFilterInfo() {
	ZEROMEM(this);

	m_pdwEnable = MyRgAllocNZ(DWORD,g_pFilterCon->m_nFilters);
	if (!m_pdwEnable) {
		DEBUGMSG(ZONE_ERROR, (L"HTTPD: CFilterInfo::Init died on Alloc!\r\n"));
		return;
	}

	m_ppvContext = MyRgAllocZ(PVOID,g_pFilterCon->m_nFilters);
	if (!m_ppvContext) {
		MyFree(m_pdwEnable);
		DEBUGMSG(ZONE_ERROR, (L"HTTPD: CFilterInfo::Init died on Alloc!\r\n"));
		return;
	}

	//  A filter can disable itself for events in a session, m_pdwEnable stores this.
	memset(m_pdwEnable,0xFFFF,g_pFilterCon->m_nFilters*sizeof(DWORD));  // all true at first

	m_dwStartTick = GetTickCount();
	m_fFAccept = TRUE;
	return;
}

//  Notes:  If http request is to be persisted, this is called. 
//  Do NOT Free the Allocated Mem or the context structure here, these are persisted
//  across requests, delete at end of session.


BOOL CFilterInfo::ReInit() {
	MyFree(m_pszDenyHeader);

	if (m_pFLog) {
		MyFree(m_pFLog);  
	}
	
	//  Reset the enable structure to all 1's, starting over.
	memset(m_pdwEnable,0xFFFF,g_pFilterCon->m_nFilters*sizeof(DWORD));  // all true at first

	// The context struct and AllocMem data lasts through the session, not just a request.
	m_dwStartTick = GetTickCount();
	m_fFAccept = TRUE;
	m_dwNextReadSize = 0;
	m_dwBytesSent = 0;
	m_dwBytesReceived = 0;

	return TRUE;
}

CFilterInfo::~CFilterInfo() {
	MyFree(m_pszDenyHeader);

	if (m_pFLog) {
		MyFree(m_pFLog);
	}
	MyFree(m_pdwEnable);	
	MyFree(m_ppvContext);

	
	FreeAllocMem();	// frees m_pAllocBlock
}

//  Initilization routine for global filters.  This looks in the registry for the
//  filters, loads any dlls into memory, and puts them into a list that is 
//  ordered from Highest prio filters to lowest.

BOOL CISAPIFilterCon::Init() {
	DEBUG_CODE_INIT;
	BOOL ret = FALSE;
	BOOL fChange = FALSE;
	CISAPI *pCISAPI = NULL;
	const WCHAR *wcszReg;
	WCHAR *wszFilterNames;
	DWORD dwFilterLen = 0;
	PWSTR wszToken = NULL;
	DWORD i;
	int j;

	CReg topreg(HKEY_LOCAL_MACHINE,RK_HTTPD);

	wcszReg = topreg.ValueSZ(RV_FILTER);
	wszFilterNames = MySzDupW(wcszReg);

	DEBUGMSG(ZONE_ISAPI, (L"HTTPD: Filter DLLs Reg Value <<%s>>\r\n",wszFilterNames));

	if (NULL == wszFilterNames || 0 == (dwFilterLen = wcslen(wszFilterNames))) {
		DEBUGMSG(ZONE_ISAPI,(L"HTTPD: No filters listed in registry\r\n"));
		myleave(0);  // no values => no registered filters
	}

	// count # of commas to figure how many dlls there are
	m_nFilters = 1;   // there's at least 1 if we're this far

	for (i = 0; i < dwFilterLen && wszFilterNames[i] != L'\0'; i++) {
		if (wszFilterNames[i] == L',')
			m_nFilters++;
	}
	DEBUGMSG(ZONE_ISAPI, (L"HTTPD: # of filters = %d\r\n",m_nFilters));

	if (! (m_pFilters = MyRgAllocZ(FILTERINFO,m_nFilters)))
		myleave(203);

	// now tokenize the string and load filter libs as we do it
	j = 0;
	wszToken = wcstok(wszFilterNames,cwszFilterSep);
	while (wszToken != NULL) {
		svsutil_SkipWWhiteSpace(wszToken);

		// Handles the case where there's a comma but nothing after it.
		if (*wszToken == L'\0') {
			m_nFilters--;
			break;
		}
		
		pCISAPI = m_pFilters[j].pCISAPI = new CISAPI(SCRIPT_TYPE_FILTER);
		DEBUGMSG(ZONE_ISAPI, (L"HTTPD: Initiating filter library %s\r\n",wszToken));
		if (!pCISAPI) {
			m_nFilters = j;
			if (m_nFilters == 0)
				MyFree(m_pFilters);
			
			myleave(204);
		}

		if (TRUE == pCISAPI->Load(wszToken)) {
			m_pFilters[j].wszDLLName = MySzDupW(wszToken);	
			m_pFilters[j].dwFlags = pCISAPI->GetFilterFlags();
			if (m_pFilters[j].dwFlags & SF_NOTIFY_READ_RAW_DATA)
				g_pVars->m_fReadFilters = TRUE;
			j++;
		}
		else {
			DEBUGMSG(ZONE_ERROR,(L"HTTPD: Filter <<%s>> failed to load!\r\n",wszToken));
			// only messed up this filter, others may work so keep on moving
			m_nFilters--;
			delete pCISAPI;
		}
			
		wszToken = wcstok(NULL,cwszFilterSep);
	}
	DEBUGCHK(j == m_nFilters);

	// Case where every filter fails to load
	if (0 == m_nFilters)  {
	//	Cleanup();
		MyFree(m_pFilters);
		myleave(205);
	}

	// Reorder list based on priorities of filters.
	do 	{
		fChange = FALSE;
		for(j=0; j<m_nFilters-1; j++) {
			if ( (m_pFilters[j].dwFlags & SF_NOTIFY_ORDER_MASK) < (m_pFilters[j+1].dwFlags & SF_NOTIFY_ORDER_MASK)) {
				// swap the 2 filter infos
				FILTERINFO ftemp = m_pFilters[j+1];
				m_pFilters[j+1] = m_pFilters[j];
				m_pFilters[j] = ftemp;
				fChange = TRUE;
			}
		}
	} while(fChange);

	ret = TRUE;
done:
	DEBUGMSG_ERR(ZONE_ERROR, (L"HTTPD: CIsapiFilterCon::Init FAILED: GLE=%d err=%d\r\n", 
			GetLastError(), err));
	
	MyFree(wszFilterNames);
	return ret;
}

void CISAPIFilterCon::Cleanup() {
	if (0 == m_pFilters)
		return;
	
	for (int i = 0; i < m_nFilters; i++) {
		m_pFilters[i].pCISAPI->Unload(m_pFilters[i].wszDLLName);
		MyFree(m_pFilters[i].wszDLLName);

		delete m_pFilters[i].pCISAPI;
	}
	MyFree(m_pFilters);
}

// Determines whether or not a filter will be called based on current set of flags
BOOL CHttpRequest::IsCurrentFilterCalled(DWORD dwNotifyType, int iCurrentFilter) {
	// Filter has not requested to be notified for current call or has disabled itself through SF_REQ_DISABLE_NOTIFICATIONS.
	if (0 == ((dwNotifyType & g_pFilterCon->m_pFilters[iCurrentFilter].dwFlags) & m_pFInfo->m_pdwEnable[iCurrentFilter]))
		return FALSE;

	// Filter only wants secure notifications but we're receiving on an insecure port, or vice versa.
	if ((m_fIsSecurePort && ! (g_pFilterCon->m_pFilters[iCurrentFilter].dwFlags & SF_NOTIFY_SECURE_PORT)) || 
	    (!m_fIsSecurePort && ! (g_pFilterCon->m_pFilters[iCurrentFilter].dwFlags & SF_NOTIFY_NONSECURE_PORT)))
		return FALSE;

	return TRUE;
}

// BOOL CHttpRequest::CallFilter

// Function:   Httpd calls this function on specified events, it's goes through
// the list and calls the registered filters for that event.

// PARAMETERS:
// 		DWORD dwNotifyType - what SF_NOTIFIY type occured

//		The last 3 parameters are optional; only 3 filter calls use them.
// 		They are used when extra data needs to be passed to the filter that isn't
// 		part of the CHttpRequest structure.  

//		PSTR *ppszBuf1  ---> SF_NOTIFY_SEND_RAW_DATA   --> The buffer about to be sent
//						---> SF_NOTIFY_URL_MAP 	       --> The virtual path (only
//							    on ServerSupportFunction with HSE_REQ_MAP_URL_TO_PATH,
//							    otherwise use CHttpRequest values.)
//					 	---> SF_NOTIFY_AUTHENTECATION  --> The remote user name
//						---> SF_NOTIFY_READ_RAW_DATA   --> Buffer about to be read

//		PSTR *ppszBuf2  ---> SF_NOTIFY_SEND_RAW_DATA   --> Unused
//						---> SF_NOTIFY_URL_MAP		   --> The physical mapping
//						---> SF_NOTIFY_AUTHENTECATION  --> The user's password
//						---> SF_NOTIFY_READ_RAW_DATA   --> Buffer about to be read
//
//		int *pcbBuf		---> SF_NOTIFY_SEND_RAW_DATA   --> Length of buffer to be sent
//						---> SF_NOTIFY_URL_MAP		   --> Length of physical path buf
//						---> SF_NOTIFY_AUTHENTECATION  --> Unused
//						---> SF_NOTIFY_READ_RAW_DATA   --> Buffer about to be read

//      int *pcbBuf2    ---> SF_NOTIFY_READ_RAW_DATA   --> size of the buffer reading into

// return values
// 		TRUE  tells calling fcn to continue normal execution
// 		FALSE tells calling fcn to terminate this request.

// Notes:
// if FALSE is returned, m_pFilterInfo->m_fAccept is also set to false.  This
// helps the filter handle unwinding from nested filter calls.

// For example, the http server calls a filter with URL_MAP flags.  The filter
// then calls a WriteClient, which will call the filter again with event
// SF_NOTIFY_SEND_RAW_DATA.  If on the SEND_RAW_DATA call the filter returns a 
// code to stop the session, we need to store it for the original MAP_URL call,
// so that it knows to stop the session too.


BOOL CHttpRequest::CallFilter(DWORD dwNotifyType, PSTR *ppszBuf1, 
							  int *pcbBuf, PSTR *ppszBuf2, int *pcbBuf2)
{
	DEBUG_CODE_INIT;
	HTTP_FILTER_CONTEXT fc;
	LPVOID pStFilter;		// 3rd param passed on HttpFilterProc
	LPVOID pStFilterOrg; 	// stores a copy of pStFilter, so we remember alloc'd mem to cleanup, if any
	BOOL fFillStructs = TRUE;
	BOOL fReqReadNext;
	BOOL ret = FALSE;
	DWORD dwFilterCode;
	int i;

	if (0 == g_pFilterCon->m_nFilters)
		return TRUE;

	// m_pFInfo->m_fFAccept = FALSE implies no more filter calls, except on the "cleanup" calls
	DEBUGMSG(ZONE_ISAPI,(L"HTTPD: Filter notify type = 0x%08x\r\n",dwNotifyType));
	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)))
	{
		return FALSE;
	}
	m_pFInfo->m_dwSFEvent = dwNotifyType;

	do {
		pStFilter = pStFilterOrg = NULL;
		fReqReadNext = FALSE;
		
		// Filters implement priority inversion for SEND_RAW_DATA events.
		i = (dwNotifyType == SF_NOTIFY_SEND_RAW_DATA) ? g_pFilterCon->m_nFilters - 1 : 0;
		
		while ( (dwNotifyType == SF_NOTIFY_SEND_RAW_DATA) ? i >= 0 : i < g_pFilterCon->m_nFilters ) {
			// we still reference g_pFilterCon just in case a filter failed in another request
			if (! IsCurrentFilterCalled(dwNotifyType,i)) {			
				// ith filter didn't request this notification, move along
				NEXTFILTER(dwNotifyType, i);
				continue;
			}

			m_pFInfo->m_iFIndex = i;
			if (fFillStructs && (!FillFC(&fc,dwNotifyType,&pStFilter,&pStFilterOrg,
										 ppszBuf1, pcbBuf, ppszBuf2, pcbBuf2)))
				myretleave(FALSE,210);  // memory error on FillFC
			fFillStructs = FALSE;	// after structs or filled don't refill them

			fc.pFilterContext = m_pFInfo->m_ppvContext[i];

			__try  {
				dwFilterCode = 	g_pFilterCon->m_pFilters[i].pCISAPI->CallFilter(&fc,dwNotifyType,pStFilter);
			}
			__except(ReportFault(GetExceptionInformation(),0), EXCEPTION_EXECUTE_HANDLER) {

⌨️ 快捷键说明

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