?? impiopcbrowseserveraddressspace.cpp
字號:
// 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.
// 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 + -