ClearBox Server™ v1.2 Developer's Guide

Step 4. Implementing Core Interface

In this step you will implement core ICommonExtender interface that is mandatory for implementation.

1. Select CMyFirst class in ClassView and right click it. Select "Implement Interface..." from the menu. Click OK to suppress warning message. In Browse Type Libraries dialog click Browse... and select tacradserver.tlb file from /SDK directory of ClearBox Server installation. Check ICommonExtender interface and click OK.

This action will create simple implementation of ICommonExtender where all methods return E_NOTIMPL. Surely, they must be replaced by our code.

2. Find RequestTimerCall method implementation. We do not plan to execute any periodic tasks, so this method should return S_FALSE. Now its code is

STDMETHOD(RequestTimerCall)(ULONG * secsInterval)
{
	if (secsInterval == NULL)
		return E_POINTER;
	return S_FALSE; 
}

TimerCall must not be implemented, it will never be called as RequestTimerCall returns S_FALSE.

3. Find InterfaceSupportsErrorInfo method implementation created by the ATL wizard. Replace

static const IID* arr[] = {
	&IID_IMyFirst 
};

with code

static const IID* arr[] = {
	&IID_ICommonExtender 
};

This will make server extension be able to provide extended information about its errors.

4. Now server extension initialization should be implemented. At startup, extension must open connection with Access database. So find and change Initialize method of CMyFirst class:

STDMETHOD(Initialize)(VARIANT_BOOL start)
{
	if (start==VARIANT_TRUE)
	{
		return m_DB.Open(_T("c:\\testext.mdb"));
	}
	else
		m_DB.Close();
	return S_OK;
}

It uses hard-coded path to the database for simplicity. This behavior will be changed to more complex one in step 9.

5. Finally, the largest task in this step should be performed. That is implementing GetClientConnectionKey method.

Open file with definition of CDatabase class (database.h) and insert the following class definition before CDatabase class:

class CSecretsA
{
public:
	TCHAR m_Secret[51];

	BEGIN_COLUMN_MAP(CSecretsA)
		COLUMN_ENTRY(1,m_Secret)
	END_COLUMN_MAP()
};

This class will be used to bind results of a SQL query to a variable. This is one of the possible methods. In next steps we will use CDynamicAccessor.

Find GetClientConnectionKey method defined in CMyFirst class. Replace its body with the following code:

STDMETHOD(GetClientConnectionKey)(LONG clientIPAddr, VARIANT_BOOL tacConnection, 
	VARIANT_BOOL authenPacket, BSTR * connKey)
{
	if (connKey == NULL)
		return E_POINTER;

	USES_CONVERSION;
	CCommand<CAccessor<CSecretsA> > getSecret;
	TCHAR commandStr[200];
	in_addr inad;
	inad.S_un.S_addr=clientIPAddr;

	if (tacConnection==VARIANT_TRUE)
		_stprintf(commandStr,
			_T("select Secret from Clients where NASIP='%s' and TACACShost=true"),
			A2T(inet_ntoa(inad)));
	else
		_stprintf(commandStr,
		_T("select Secret from Clients where NASIP='%s' and TACACShost=false and AuthenSecret=%s"),
		A2T(inet_ntoa(inad)),
		(authenPacket==VARIANT_TRUE)?_T("true"):_T("false"));

	HRESULT hr=getSecret.Open(m_DB.Session(),commandStr);
	if (FAILED(hr))
		return hr;

	hr=getSecret.MoveFirst();
	if (hr==S_OK)
		*connKey=SysAllocString(T2W(getSecret.m_Secret));
	return S_OK;
}

This code dynamically creates SQL query and issues it via CCommand object. The result of the query is binded to CSeretsA class if the query returns secret.

In order to use inet_ntoa function, WinSock library should be linked. Add this line at the end of stdafx.h file just after the last #include directive:

#pragma comment (lib,"ws2_32.lib")

Go to the next step.


© 2001-2003 XPerience Technologies. www.xperiencetech.com

Created by chm2web html help conversion utility.