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

📄 impiopcbrowseserveraddressspace.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// ImpIOPCBrowseServerAddressSpace.cpp
//
//  This file contains the implementation of 
//  the IOPCBrowseServerAddressSpace interface for the OPC server.
//
//
//	(c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
//	Functions defined in this module:
//
//			CImpIOPCBrowseServer::CImpIOPCBrowseServer()
//			CImpIOPCBrowseServer::~CImpIOPCBrowseServer()
//			CImpIOPCBrowseServer::AddRef()
//			CImpIOPCBrowseServer::Release()
//			CImpIOPCBrowseServer::QueryInterface()
//			CImpIOPCBrowseServer::QueryOrganization()
//			CImpIOPCBrowseServer::BrowseOPCItemIDs()
//			CImpIOPCBrowseServer::GetItemID()
//			CImpIOPCBrowseServer::BrowseAccessPaths()
//			CImpIOPCBrowseServer::BrowseHierarchial()
//			CImpIOPCBrowseServer::BrowseFlat()
//			CImpIOPCBrowseServer::GetDeviceList()
//			CImpIOPCBrowseServer::GetDatablockList()
//			CImpIOPCBrowseServer::GetVariableStringFromName()
//			CImpIOPCBrowseServer::GetDataBlockPropertyList()
//			CImpIOPCBrowseServer::FreeDataBlockPropertyList()
//			CImpIOPCBrowseServer::GetDataBlockPropertyData()
//			CImpIOPCBrowseServer::FreeMapMemory()
//			CImpIOPCBrowseServer::GetHandleFromName()
//			CImpIOPCBrowseServer::GetFilter()
//			CImpIOPCBrowseServer::FilterString()
//			CreateEmptyStringEnumerator()
//
//
//
// Modification Log:
//	Vers	Date     By		Notes
//	----	-------- ---	-----
//	1.1		09/04/97 jra	Created
//	1.3		03/10/98 jra	Modified to be wizard generated and driver specific.
//	7.11	10/14/98 jra	Modified GetDeviceList() because browsing would not work
//							if the driver had multiple channels defined. Basically,
//							we cleared the variant that held the channel handles too soon.
//
//

#define WIN32_LEAN_AND_MEAN

// Microsoft headers
#include "OpcStdAfx.h"
#include <afxconv.h>
#include <malloc.h>

// Project headers
#include "OPCDrv.h"
#include "OPC.h"
#include <InterfaceDef.h>


////////////////////////////////////////////////////////////////
// External global variables
extern IMalloc *pIMalloc;
extern TCHAR	g_tszAcronym[];


////////////////////////////////////////////////////////////////
// Local functions
static HRESULT	CreateEmptyStringEnumerator(IEnumString **);


////////////////////////////////////////////////////////////////
// External functions
extern HRESULT NewArray(unsigned long lElements, SAFEARRAY ** ppsaArray);


////////////////////////////////////////////////////////////////
// Local definitions
#define	IOADDRESS_DELIM					':'
#define	HINT_STRING						" (*hint: StartAddr - EndAddr)"
#define HINT_DELIM						" - "
#define KEY_BUFF_SIZE					20
#define SIZE_OF_PROPERTY_STRINGS		20
#define	SIZE_OF_PROPERTY_DATA_STRINGS	20


////////////////////////////////////////////////////////////////
// Globals defined in this module
//
// TODO:	Add/remove properties to the following two-dimensional array
//			for browsing datablocks
//
//////////////////////////////////////////////////////////////
static char g_pszDataBlockProps[][SIZE_OF_PROPERTY_STRINGS] = {
	"StartAddress",
	"EndAddress"
};
static long g_lNumDataBlockProps = sizeof(g_pszDataBlockProps) / SIZE_OF_PROPERTY_STRINGS;

// Macros used for retrieving property data from the data list.
//
// TODO:	The macros index must correspond to the index of the property string in
//			the g_pszDataBlockProps[][] list above, so if you add/remove properties
//			from it, you must add/remove/change the property indexes below.
//			Do NOT change GetDataFromList().
//
//////////////////////////////////////////////////////////////
#define	START_ADDRESS_PROP		0
#define END_ADDRESS_PROP		1
//mvs11272000 - Get size of property data strings
#define	GetDataFromList(pszList, nIndex)	(pszList + (SIZE_OF_PROPERTY_DATA_STRINGS * nIndex))


/////////////////////////////////////////////////////////////////////////////
// Constructor /Destructor functions
//


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::CImpIOPCBrowseServer()
//
// @desc Constructor for this Interface
//
// TODO:	Add any initialization code here
//
////////////////////////////////////////////////////////////////
CImpIOPCBrowseServer::CImpIOPCBrowseServer(LPUNKNOWN pUnkOuter)
{
	// Initialize object members
	m_dwLevel			= DEVICE_LEVEL;
	m_pUnkOuter			= pUnkOuter;
	m_pParentServer		= (COPCDrvServer *)pUnkOuter;

	InitializeCriticalSection(&this->m_Lock);

	if (FAILED(GetDataBlockPropertyList()))
	{
		LogEventMessage(TEXT("Unable to create datablock property array"),
						g_tszAcronym,
						3);
	}
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::~CImpIOPCBrowseServer()
//
// @desc Destructor for this Interface
//
// TODO:	Add any clean-up code here
//
////////////////////////////////////////////////////////////////
CImpIOPCBrowseServer::~CImpIOPCBrowseServer()
{
	m_pParentServer->m_pCImpIOPCBrowseServer = NULL;
	
	if (FAILED(FreeDataBlockPropertyList()))
	{
		LogEventMessage(TEXT("Unable to free datablock property array"),
						g_tszAcronym,
						3);
	}

	DeleteCriticalSection(&this->m_Lock);
}



////////////////////////////////////////////////////////////////
//
// IUnknown functions Delegate to Parent.
//
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::QueryInterface()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::QueryInterface(REFIID	iid, 
												  LPVOID	*ppInterface)
{
	return m_pUnkOuter->QueryInterface(iid, ppInterface);
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::AddRef()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIOPCBrowseServer::AddRef(void)
{
	return m_pUnkOuter->AddRef(); 
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::Release()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIOPCBrowseServer::Release(void)
{
	return m_pUnkOuter->Release(); 
}



////////////////////////////////////////////////////////////////
// IOPCBrowseServerAddressSpace interface functions


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::QueryOrganization()
//
// @desc Returns to the calling client that this server uses a 
//			Hierarchical name space format.
//
// @parm	[out] OPCNAMESPACETYPE * | pNameSpaceType| Returned name space type
//
// @retval	S_OK			success
// @retval	E_INVALIDARG	an invalid parameter was passed
//
// TODO:	Generally nothing, unless your driver requires flat browsing
//			instead of hierarchial.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::QueryOrganization(OPCNAMESPACETYPE *pNameSpaceType)
{ 
	// Make sure we don't get a bad pointer.
	//
	if (NULL == pNameSpaceType)
	{
		return E_INVALIDARG;
	}

	// This server supports a hierarchial address space.
	//
	*pNameSpaceType = OPC_NS_HIERARCHIAL;	
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::ChangeBrowsePosition()
//
// @desc This function provides a way to move 'up' and 'down' in the
//			OPC Server's Hierarchial address space.
//
// @parm	[in] OPCBROWSEDIRECTION	| dwDirection | Direction to change the browse to
// @parm	[in, string] LPCWSTR	| wszString	  | When browsing down, this is the branch
//													to move into
// 
// @retval	S_OK			success
// @retval	E_INVALIDARG	an invalid parameter was passed
// @retval	E_FAIL			failure
//
// TODO:	Modify the switch statement to add/remove any levels of
//			browsing required.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::ChangeBrowsePosition(OPCBROWSEDIRECTION	dwDirection,
														LPCWSTR				wszString)
{
	// Check for bad pointers...
	//
	if (NULL == wszString)
	{
		return E_INVALIDARG;
	}


	// If we get a NULL string, that indicates they want the ROOT level
	//
	if ((NULL == *wszString) && (OPC_BROWSE_DOWN == dwDirection))
	{
		m_dwLevel = DEVICE_LEVEL;
		m_szDeviceName.Empty();
		return S_OK;
	}

	// See which direction the user wants to go
	//
	switch(dwDirection)
	{
	case OPC_BROWSE_UP:
		switch(m_dwLevel)
		{
		case DEVICE_LEVEL:
			return E_INVALIDARG;	// No where to go!!
			break;

		case DATABLOCK_LEVEL:
			m_dwLevel = DEVICE_LEVEL;
			break;

		default:
			// Should never happen!
			TRACE("Invalid browse level (%lu), File %s, Line %d\n", 
				m_dwLevel, __FILE__, __LINE__);
			return E_FAIL;
			break;
		}
		break;

	case OPC_BROWSE_DOWN:
		switch(m_dwLevel)
		{
		case DEVICE_LEVEL:
			m_szDeviceName = wszString;
			m_dwLevel = DATABLOCK_LEVEL;
			break;

		case DATABLOCK_LEVEL:
			return E_INVALIDARG;	// No where to go!!
			break;

		default:
			// Should never happen!
			TRACE("Invalid browse level (%lu), File %s, Line %d\n", 
				m_dwLevel, __FILE__, __LINE__);
			return E_FAIL;
			break;
		}
		break;

	default:
		return E_INVALIDARG;
		break;
	}

	return S_OK; 
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::BrowseOPCItemIDs()
//
// @desc This function returns a string enumeration list for a list
//		 of ItemIDs depending on the given parameters and filtering.
//		 The position from which to browse can be changed by calling
//		 ChangeBrowsePosition().
//
// @parm	[in] OPCBROWSETYPE	 | dwBrowseFilterType	| browse type
// @parm	[in, string] LPCWSTR | szFilterCriteria		| filtering string
// @parm	[in] VARTYPE		 | vtDataTypeFilter		| datatype filter
// @parm	[in] DWORD			 | dwAccessRightsFilter	| access rights filter
// @parm	[out] LPENUMSTRING * | ppIEnumString		| returned string enumerator
//
// @retval	S_OK			success
// @retval	E_FAIL			failure
// @retval	E_INVALIDARG	an invalid parameter was passed in
// @retval	E_OUTOFMEMORY	out of memory (allocator failed)
// @retval	S_FALSE			There is nothing to enumerate
//
// @devnote The client is responsible for freeing any allocated
//			memory associated with the enumeration list.
//
// TODO:	Add any filtering, browse levels, etc that your driver requires.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::BrowseOPCItemIDs(OPCBROWSETYPE	dwBrowseFilterType,
													LPCWSTR			szFilterCriteria,
													VARTYPE			vtDataTypeFilter,
													DWORD			dwAccessRightsFilter,
													LPENUMSTRING	*ppIEnumString)
{
	LPOLESTR			*ppStringArray			= NULL;
	WCHAR				*pwcString				= NULL;
	int					nIndex					= 0,
						nNumLoops				= 1;
	long				lNumEntries				= 0L,
						lHandle					= 0L;
	CImpIEnumString		*pEnumString			= NULL;
	CString				szFilterSearchString	= szFilterCriteria;
	DWORD				dwTempLevel				= this->m_dwLevel;
	BOOL				bFilterFromEnd			= FALSE;
	HRESULT				hr;
	POSITION			posMap;
	CLongPtrMap			mapStrings;
	FILTERTYPE			dwFilterType;
	

	// Make sure that we have a good pointer for the enumeration
	//
	if (NULL == ppIEnumString)
	{
		return E_INVALIDARG;
	}

	// Macro required for ATL string conversions
	//
	USES_CONVERSION;

	///////////////////////////////////////
	//
	// See if the user wants to do anything with filtering
	//
	///////////////////////////////////////


	//
	// Switch on the datatype filtering
	//
	switch(vtDataTypeFilter)
	{
	// These datatypes are inherently supported by the toolkit
	//
	case VT_R4:
	case VT_BSTR:
	case VT_BOOL:
	case VT_I2:
	case VT_I4:
	case VT_EMPTY:
	/////////////////////////////////////////////////////////////
	//
	// TODO: Add any additional datatypes here that your driver supports
	//		 or remove datatypes that your driver does not support
	//
	/////////////////////////////////////////////////////////////
		break;

	// Anything else is not supported, so return that there is nothing
	// to enumerate
	default:
		return CreateEmptyStringEnumerator(ppIEnumString);
	}


	//
	// switch on the access rights filtering type (currently not used)
	//
	switch(dwAccessRightsFilter)
	{
	default:
	case OPC_READABLE:
	case OPC_WRITEABLE:
	case (OPC_READABLE | OPC_WRITEABLE):
		break;
	}


	//
	// Go get the filtering type and search string.
	//
	GetFilter(szFilterSearchString, dwFilterType);


	//
	// Switch on the browse filtering type
	//
	switch (dwBrowseFilterType)
	{
	// Only datablocks don't have children, so if we are not at that level, then
	// return that their is nothing to enumerate.
	//
	case OPC_LEAF:
		if (DATABLOCK_LEVEL != m_dwLevel)
		{
			return CreateEmptyStringEnumerator(ppIEnumString);
		}

		hr = BrowseHierarchial(&mapStrings,
							   &lNumEntries,
							   dwBrowseFilterType,
							   szFilterSearchString,
							   dwFilterType);
		if (FAILED(hr))
		{
			*ppIEnumString = NULL;
			FreeMapMemory(&mapStrings);
			return E_FAIL;
		}
		break;

	// Only devices have children, so if we are not at that
	// level, then return that their is nothing to enumerate
	//
	case OPC_BRANCH:
		if (DEVICE_LEVEL != m_dwLevel)
		{
			return CreateEmptyStringEnumerator(ppIEnumString);
		}

		hr = BrowseHierarchial(&mapStrings,
							   &lNumEntries,
							   dwBrowseFilterType,
							   szFilterSearchString,
							   dwFilterType);
		if (FAILED(hr))
		{
			*ppIEnumString = NULL;
			FreeMapMemory(&mapStrings);
			return E_FAIL;
		}
		break;

	case OPC_FLAT:
		hr = BrowseFlat(&mapStrings,
						&lNumEntries,
						szFilterSearchString,
						dwFilterType);
		if (FAILED(hr))
		{
			*ppIEnumString = NULL;
			FreeMapMemory(&mapStrings);
			return hr;
		}
		break;

	default:
		// Should never happen!!
		*ppIEnumString = NULL;
		TRACE("Invalid Search Filter type, File %s, Line %d\n", 
				__FILE__, __LINE__);
		return E_INVALIDARG;

⌨️ 快捷键说明

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