Microsoft Internet Security and Acceleration Server 2000

Implement the IFWXIOCompletion Interface

To carry out data pumping, the data filter must use an asynchronous input/output (I/O) method. To do so, the data filter has to implement the IFWXIOCompletion interface. Using this interface, the Firewall service notifies the filter upon completion of an I/O operation.

You will implement the IFWXIOCompletion::CompleteAsyncIO method.

To the CSMTPDataFilter class definition in SmtpDataFilter.h, add inheritance from the IFWXIOCompletion class:

public IFWXIOCompletion

Also, add COM interface support for this interface by adding the following line to the COM map of the CSMTPDataFilter class:

COM_INTERFACE_ENTRY(IFWXIOCompletion)

Copy the prototype of the IOCompletion::CompleteAsyncIO method from wspfwext.h and add it to SMTPDataFilter.h and SMTPDataFilter.cpp (with a simple implementation):

SMTPDataFilter.h:

//IFWXIOCompletion
 
public:
	HRESULT STDMETHODCALLTYPE CompleteAsyncIO( 
			/* [in] */ BOOL fSuccess,
			/* [in] */ DWORD Win32ErrorCode,
			/* [in] */ IFWXIOBuffer __RPC_FAR *pIOBuffer,
			/* [in] */ UserContextType UserData,
			/* [unique][in] */ LPSOCKADDR ExternalAddress,
			/* [in] */ INT ExternalAddressLength) ;
 

SMTPDataFilter.cpp:

HRESULT STDMETHODCALLTYPE CSMTPDataFilter::CompleteAsyncIO( 
		/* [in] */ BOOL fSuccess,
		/* [in] */ DWORD Win32ErrorCode,
		/* [in] */ IFWXIOBuffer __RPC_FAR *pIOBuffer,
		/* [in] */ UserContextType UserData,
		/* [unique][in] */ LPSOCKADDR ExternalAddress,
		/* [in] */ INT ExternalAddressLength)
	{
	 return S_OK;
}

This method is called when an I/O operation is completed. In this method you should implement the logic of your filter. This logic is based on the protocol in which you are working; in this case, the SMTP protocol. To start the data pump, add the code shown in bold to CSMTPDataFilter::SetSockets (in SMTPDataFilter.cpp):

#define SOURCE_IS_SERVER 0
#define SOURCE_IS_CLIENT 1
HRESULT STDMETHODCALLTYPE CSMTPDataFilter::SetSockets( 
	/* [in] */ IFWXSocket __RPC_FAR *piInternalSocket,
	/* [in] */ IFWXSocket __RPC_FAR *piExternalSocket,
	/* [in] */ IFWXConnection __RPC_FAR *piConnection,
	/* [unique][in] */ IUnknown __RPC_FAR *punkFilterContext)
 
	{
		//Keep a reference to the sockets
		Lock();
		m_spExternalSocket = piExternalSocket;
		m_spInternalSocket = piInternalSocket;
		Unlock();
	//SOURCE_IS_SERVER and SOURCE_IS_CLIENT are used
	//to differentiate between recv on external and internal sockets
	piInternalSocket ->Recv(NULL,this, SOURCE_IS_SERVER);
	piExternalSocket ->Recv(NULL,this, SOURCE_IS_CLIENT);
		return S_OK;
}