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

📄 impiopcbrowseserveraddressspace.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		break;
	}	// END switch (dwBrowseFilterType)



	///////////////////////////////////////
	//
	// OK, not we have a Map containing pointers to all of the valid
	// strings to be returned, so let's build an array of LPOLESTR and
	// create an enumerator to return to the caller
	//
	///////////////////////////////////////


	// Make sure that everything jives together.
	//
	ASSERT(mapStrings.GetCount() == lNumEntries);

	// Make sure that we got something to work with
	//
	if (0L == lNumEntries)
	{
		FreeMapMemory(&mapStrings);
		return CreateEmptyStringEnumerator(ppIEnumString);
	}

	// Allocate our memory for the list of string names
	//
	ppStringArray = new LPOLESTR [lNumEntries];
	if (NULL == ppStringArray)
	{
		*ppIEnumString = NULL;
		FreeMapMemory(&mapStrings);
		return E_OUTOFMEMORY;
	}

	// Fill the LPOLESTR array with the pointers that contain the strings.
	// This array will be used to create the enumerator.
	//
	posMap = mapStrings.GetStartPosition();
	for (long i = 0; i < lNumEntries; i++)
	{
		mapStrings.GetNextAssoc(posMap, lHandle, pwcString);
		ppStringArray[i] = pwcString;
		mapStrings.RemoveKey(lHandle);
	}

	// Create the enumerator
	//
	pEnumString = new CImpIEnumString (NULL,				// Parent
									   (ULONG)lNumEntries,	// # strings in enum
									   ppStringArray,		// Enum string array
									   pIMalloc);			// IMalloc pointer
	if (NULL == pEnumString)
	{
		*ppIEnumString = NULL;
		return E_OUTOFMEMORY;
	}
	pEnumString->AddRef();

	// There shouldn't be anything in the map at this point, but just in case...
	//
	FreeMapMemory(&mapStrings);

	// Free the memory for the temp string array because the enumerator keeps its
	// own local copy.
	//
	for (i = 0; i < lNumEntries; i++)
	{
		delete [] ppStringArray[i];
	}
	delete [] ppStringArray;

	// Call QueryInterface() to get an interface pointer for the client. This will
	// do an AddRef() internally, so we don't need to explicitly do one.
	//
	hr = pEnumString->QueryInterface(IID_IEnumString, (LPVOID *)ppIEnumString);
	if (FAILED(hr))
	{
		pEnumString->Release();
		*ppIEnumString = NULL;
		return E_FAIL;
	}

	// Reset the new enumerator and release our copy of it
	//
	(*ppIEnumString)->Reset();
	pEnumString->Release();
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::GetItemID()
//
// @desc This function will assemble a fully qualified ItemID in the
//		 hierarchial address space. The ItemID we return is dependant
//		 on the browse level the the user is on. If they are on the
//		 driver level, we simply return the string they passed to us.
//		 If we are on the device level, we append the string passed
//		 to us to the end of the driver name. If we are on the
//		 datablock level, we build a string with the driver name,
//		 device name and then string they passed to us. 
//		 The driver name and device name are known because the user
//		 would have called ChangeBrowsePosition() and "drilled" into
//		 those names. 
//		 The name passed into this function through the
//		 szItemDataID parameter is not verified to be correct. This
//		 is because if this string is a datablock address, it would
//		 be very driver specific to verify if this datablock address
//		 is found in the driver. Since this is a generic server, we
//		 won't try and verify it.
//
// @parm	[in] LPCWSTR			| szItemDataID	| Current branch or leaf
// @parm	[out, string] LPCWSTR *	| ppszItemID	| Returned item id
//
// @retval	S_OK			success
// @retval	E_FAIL			failure
// @retval	E_INVALIDARG	an invalid parameter was passed
// @retval	E_OUTOFMEMORY	out of memory
//		
// TODO:	Add any browse levels, etc required to return a fully
//			qualified item id.
//
// @devnote	The datablock level returns hints, so a hint id passed into
//			GetItemID() will not return an item id that will pass when
//			added through AddItems().
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::GetItemID(LPWSTR		szItemDataID,
											 LPWSTR		*ppszItemID)
{
	CString		szTmpItemID;
	WCHAR		*pwcTemp	= NULL;
	int			nLength		= 0;


	// Make sure we didn't get a bad pointer.
	//
	if ((NULL == ppszItemID) ||
		(NULL == szItemDataID))
	{
		return E_INVALIDARG;
	}

	//////////////////////////////////////////////////////////////
	//
	// TODO: You may need to modify the following code.
	//		 This code assumes that the final browse level (DATABLOCK_LEVEL)
	//		 returns a hint address to the client. So, the client passes in 
	//		 that hint address for the server to return a fully-qualified item
	//		 id. Your driver's address space may be different, so you may need
	//		 to addjust what is returned at the following 2 levels.
	//
	//		 For example, if the final level of brosing returns a parameter
	//		 name (such as "ProcessVariable" or "SetPoint", then you can remove
	//		 the search for the HINT_DELIM in the DATABLOCK_LEVEL.
	//
	//////////////////////////////////////////////////////////////

	// Build the string dependant on the current browse level.
	//
	switch(this->m_dwLevel)
	{
	case DEVICE_LEVEL:
		// We simply return the passed string here. This id would fail if
		// passed to AddItems()
		//
		szTmpItemID = szItemDataID;
		break;

	case DATABLOCK_LEVEL:
		szTmpItemID = m_szDeviceName;
		szTmpItemID += IOADDRESS_DELIM;
		szTmpItemID += szItemDataID;

		// We need to return a fully qualified item id, so
		// since we work with hints, simply strip off the hint stuff and
		// return the start address of the hint.
		//
		if (-1 != (nLength = szTmpItemID.Find(HINT_DELIM)))
		{
			szTmpItemID = szTmpItemID.Left(nLength);
		}
		break;

	default:
		// Should never happen!!
		*ppszItemID = NULL;
		TRACE("Invalid Browse Level (%lu), File %s, Line %d\n", 
				m_dwLevel, __FILE__, __LINE__);
		return E_FAIL;
		break;
	}

	// Remove any whitespace (just in case)
	//
	szTmpItemID.TrimLeft();
	szTmpItemID.TrimRight();

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

	// Convert to a wide-character string
	//
	nLength	= szTmpItemID.GetLength() + 1; // add 1 for the NULL
	pwcTemp	= A2W(szTmpItemID.GetBuffer(nLength));
	szTmpItemID.ReleaseBuffer();

	// Allocate the memory for the assembled ItemID.
	//
	*ppszItemID = (WCHAR *)pIMalloc->Alloc(sizeof(WCHAR) * nLength);
	if (NULL == *ppszItemID)
	{
		return E_OUTOFMEMORY;
	}

	// Copy the string to be returned to the caller.
	//
	wcscpy(*ppszItemID, pwcTemp);
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::BrowseAccessPaths()
//
// @desc This function is currently not required and simply returns E_NOTIMPL
//
// @parm [in, string] LPCWSTR		| szItemID		| Fully qualified Item ID
// @parm [out]		  LPENUMSTRING *| ppIEnumString	| Where to save the returned 
//											string enumerator. This parameter
//											must be NULL is the HRESULT return is
//											anything other than S_OK.
//
// @retval E_FAIL			The function failed
// @retval E_INVALIDARG		A bad parameter was passed (i.e. a NULL pointer)
// @retval S_FALSE			There is nothing to enumerate
// @retval E_OUTOFMEMORY	A memory allocator failed (not enough memory)
// @retval S_OK				Success
// @retval E_NOTIMPL		The server does not require or support access paths
//
// @devnote	Refer to the OLE for Process Control Standard v1.0a for more information
//
// TODO: If your driver requires access path support, then you need
//		 to implement this function so an OPC client can browse
//		 the available access paths for a given item id.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCBrowseServer::BrowseAccessPaths(LPCWSTR		szItemID,
													 LPENUMSTRING	*ppIEnumString)
{ 
	return E_NOTIMPL; 
}


////////////////////////////////////////////////////////////////
//
// Internal utility functions that are not part of the 
// IOPCBrowseServerAddressSpace interface.
//
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::BrowseHierarchial()
//
// @desc 
//
// @parm	CLongPtrMap	*	| pMap				| Map to store strings
// @parm	long		*	| plNumEntries		| Number of entries returned in map
// @parm	OPCBROWSETYPE	| dwBrowseFilterType| Browse filter (Branch or Leaf)
// @parm	CString			| szFilterCriteria	| Filtering string
// @parm	FILTERTYPE		| dwFilterType		| Filtering type
//
// @retval	S_OK			success
// @retval	E_FAIL			failure
// @retval	E_INVALIDARG	an invalid parameter was passed
// @retval	E_OUTOFMEMORY	out of memory
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::BrowseHierarchial(CLongPtrMap		*pMap,
												long			*plNumEntries,
												OPCBROWSETYPE	dwBrowseFilterType,
												CString			szFilterCriteria,
												FILTERTYPE		dwFilterType)
{
	HRESULT	hr;


	//////////////////////////////////////////////////////////////
	//
	// TODO: Add any additional browsing levels here that your
	//		driver supports.
	//
	//////////////////////////////////////////////////////////////

	switch(m_dwLevel)
	{
	case DEVICE_LEVEL:
		hr = GetDeviceList(pMap,					// Map to store the strings in
							plNumEntries,			// Number of entries in the map
							dwBrowseFilterType,		// Browse Filter
							szFilterCriteria,		// String used for filtering
							dwFilterType);			// Filter type
		break;

	case DATABLOCK_LEVEL:
		hr = GetDatablockList(pMap,					// Map to store the strings in
							plNumEntries,			// Number of entries in the map
							m_szDeviceName,			// Device name to browse into
							dwBrowseFilterType,		// Browse Filter
							szFilterCriteria,		// String used for filtering
							dwFilterType);			// Filter type
		break;

	default:
		// Should never happen!!
		TRACE("Invalid Browse Level (%lu), File %s, Line %d\n", 
			m_dwLevel, __FILE__, __LINE__);
		return E_FAIL;
		break;
	}	// END switch(this->m_dwLevel)

	return hr;
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::BrowseFlat()
//
// @desc	This function performs a "flat" browse at the current level.
//			It will return all branches and leafs as fully qualified
//			item ids (except when hints are returned)
//
// @parm	CLongPtrMap	*	| pMap				| Map to store strings
// @parm	long		*	| plNumEntries		| Number of entries returned in map
// @parm	CString			| szFilterCriteria	| Filtering string
// @parm	FILTERTYPE		| dwFilterType		| Filtering type
//
// @retval	S_OK			success
// @retval	E_FAIL			failure
// @retval	E_INVALIDARG	an invalid parameter was passed
// @retval	E_OUTOFMEMORY	out of memory
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::BrowseFlat(CLongPtrMap	*pMap,
										 long			*plNumEntries,
										 CString		szFilterCriteria,
										 FILTERTYPE		dwFilterType)
{
	HRESULT		hr;
	long		lTempNumEntries	= 0L,
				i				= 0L,
				lKey,
				lMapIndex		= 0;
	int			nLength;
	CLongPtrMap	DevMap,
				DBMap;
	POSITION	posDevMap		= NULL,
				posDBMap		= NULL;
	WCHAR		*pwcString		= NULL,
				*pwcEntry		= NULL;
	CString		szDevice,
				szDatablock,
				szReturnString;


	USES_CONVERSION;

	switch(m_dwLevel)
	{
	case DEVICE_LEVEL:
		// Get the list of datablocks from the driver
		//
		hr = GetDeviceList(&DevMap,				// Map to store the strings in
						   &lTempNumEntries,	// Number of entries in the map
						   OPC_BRANCH,			// Browse Filter
						   szFilterCriteria,	// String used for filtering
						   dwFilterType);		// Filter type
		if (FAILED(hr))
		{
			FreeMapMemory(&DevMap);
			FreeMapMemory(&DBMap);
			return E_FAIL;
		}

		// For each device in the list, get its datablocks
		//
		posDevMap = DevMap.GetStartPosition();
		while (posDevMap != NULL)
		{
			DevMap.GetNextAssoc(posDevMap, lKey, pwcString);
			szDevice = pwcString;

			// Get the variables that are leafs
			hr = GetDatablockList(&DBMap,
								  &lTempNumEntries,
								  szDevice,
								  OPC_LEAF,
								  szFilterCriteria,
								  dwFilterType);
			if (FAILED(hr))
			{
				FreeMapMemory(&DevMap);
				FreeMapMemory(&DBMap);
				return E_FAIL;
			}

			// For each datablock in the list, add it to the return map
			//
			posDBMap = DBMap.GetStartPosition();
			while (posDBMap != NULL)
			{
				DBMap.GetNextAssoc(posDBMap, lKey, pwcString);
				szDatablock = pwcString;

				// Build up the string to add
				szReturnString = szDevice + IOADDRESS_DELIM + szDatablock;

				// Allocate the memory and add it to the map
				nLength = szReturnString.GetLength();
				pwcString = A2W(szReturnString.GetBuffer(nLength+ 1));	
				szReturnString.ReleaseBuffer();

				pwcEntry = new WCHAR [nLength + 1];
				if (NULL == pwcEntry)
				{
					FreeMapMemory(&DevMap);
					FreeMapMemory(&DBMap);
					return E_OUTOFMEMORY;
				}

				wcscpy(pwcEntry, pwcString);
				pMap->SetAt(lMapIndex, pwcEntry);
				lMapIndex++;
			}

			// Free the map memory so we can use it for the next pass
			FreeMapMemory(&DBMap);
		}

		// Free the map memory so we can use it for the next pass
		FreeMapMemory(&DevMap);
		break;

	case DATABLOCK_LEVEL:
		// Get the variables that are leafs
		hr = GetDatablockList(&DBMap,
							  &lTempNumEntries,
							  m_szDeviceName,
							  OPC_LEAF,
							  szFilterCriteria,
							  dwFilterType);
		if (FAILED(hr))
		{
			FreeMapMemory(&DBMap);
			return E_FAIL;
		}

		// For each datablock in the list, add it to the return map
		//
		posDBMap = DBMap.GetStartPosition();
		while (posDBMap != NULL)
		{
			DBMap.GetNextAssoc(posDBMap, lKey, pwcString);
			szDatablock = pwcString;

			// Build up the string to add
			szReturnString = m_szDeviceName + IOADDRESS_DELIM + szDatablock;

			// Allocate the memory and add it to the map
			nLength = szReturnString.GetLength();
			pwcString = A2W(szReturnString.GetBuffer(nLength+ 1));	
			szReturnString.ReleaseBuffer();

			pwcEntry = new WCHAR [nLength + 1];
			if (NULL == pwcEntry)
			{
				FreeMapMemory(&DBMap);
				return E_OUTOFMEMORY;
			}

			wcscpy(pwcEntry, pwcString);
			pMap->SetAt(lMapIndex, pwcEntry);
			lMapIndex++;
		}

		// Free the map memory so we can use it for the next pass
		FreeMapMemory(&DBMap);
		break;

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

	(*plNumEntries) = pMap->GetCount();
	return hr;
}


////////////////////////////////////////////////////////////////
// CImpIOPCBrowseServer::GetDeviceList()
//
// @desc This function places all of the devices for a given driver
//			in a CMap.
//
// @parm CLongPtrMap   * | pMap				| Map to store the strings in
// @parm long		   * | lNumEntries		| Number of entries in the map
// @parm OPCBROWSETYPE	 | dwBrowseType		| Browse type (flat or hierarchial)
// @parm CString		 | szFilterString	| Filtering string

⌨️ 快捷键说明

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