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

📄 impiopcbrowseserveraddressspace.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// @parm FILTERTYPE		 | dwFilterType		| Filtering type
//
// @retval	S_OK if the function was successful
//			S_FAIL if the function failed in some way. If
//				this happens, then all of the memory associated
//				with the entries in the map will be freed.
//			E_OUTOFMEMORY if a call to the new operator
//				returns NULL. Again, all of the memory associated
//				with the entries in the map will be freed.
//
// TODO	This function should not need to be changed. It returns a list
//		of all device names across all channels on the driver and adds
//		those names to pMap.
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::GetDeviceList(CLongPtrMap		*pMap,				/* OUT */
											long			*lNumEntries,		/* OUT */
											OPCBROWSETYPE	dwBrowseType,		/* IN */
											CString			szFilterString,	/* IN */
											FILTERTYPE		dwFilterType)		/* IN */
{
	HRESULT		hr;
	VARIANT		vChanHandlesHolder,
				vChanNamesHolder,
				vChanNames,
				vChanHandles,
				vDevHandlesHolder,
				vDevNamesHolder,
				vDevNames;
	CString		szDeviceName;
	long		lNumChannels	= 0,
				lNumDevices		= 0,
				lChanHandle		= 0,
				lDevHandle		= 0,
				lKey			= 0;
	int			nLength			= 0;
	WCHAR		*pwcDeviceName	= NULL,
				*pwcTemp		= NULL;


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

	// Initialize the variants
	VariantInit(&vChanHandlesHolder);
	VariantInit(&vChanNamesHolder);
	VariantInit(&vDevHandlesHolder);
	VariantInit(&vDevNamesHolder);
	VariantInit(&vChanNames);
	VariantInit(&vChanHandles);
	VariantInit(&vDevNames);

	// Make sure we were able load the DLL and connect to the OLE Server
	//
	if (NULL == m_pParentServer->m_pIDriver)
	{
		FreeMapMemory(pMap);
		return E_FAIL;
	}

	// Get a list of the channels available in this driver
	hr = m_pParentServer->m_pIDriver->GetChannels(&vChanHandlesHolder, 
												  &vChanNamesHolder, 
												  &lNumChannels);
	if (FAILED(hr))
	{
		FreeMapMemory(pMap);
		return E_FAIL;
	}

	// Here we are going to loop through all of the channels to get all
	// of the devices on each channel. We will place the device in a temp
	// CTypedPtrMap and then build the LPOLESTR array later to pass to
	// the enumerator.
	//
	for (long i = 0; i < lNumChannels; i++)
	{
		// Extract the channel handle and name
		hr	= SafeArrayGetElement(vChanHandlesHolder.parray,
								  &i, &vChanHandles);
		if (SUCCEEDED(hr))
		{
			// Get the channel handle and name
			lChanHandle = vChanHandles.lVal;

			// Get the list of devices for this channel
			hr = m_pParentServer->m_pIDriver->GetDevices(lChanHandle, 
														 &vDevHandlesHolder, 
														 &vDevNamesHolder, 
														 &lNumDevices);
			if (FAILED(hr))
			{
				FreeMapMemory(pMap);
				return E_FAIL;
			}

			// Save the device names in the map
			for (long j = 0; j < lNumDevices; j++)
			{
				if (SUCCEEDED(hr = SafeArrayGetElement(vDevNamesHolder.parray,
													   &j, &vDevNames)))
				{
					szDeviceName = vDevNames.bstrVal;

					// If the device name does not match the filtering criteria, then
					// continue on to the next one.
					//
					if (FALSE == FilterString(szDeviceName, szFilterString, dwFilterType))
					{
						continue;
					}

					nLength	= szDeviceName.GetLength();
					pwcTemp	= A2W(szDeviceName.GetBuffer(nLength+1));
					szDeviceName.ReleaseBuffer();

					pwcDeviceName	= new WCHAR [nLength+1];
					if (NULL == pwcDeviceName)
					{
						FreeMapMemory(pMap);
						return E_OUTOFMEMORY;
					}
					wcscpy(pwcDeviceName, pwcTemp);

					// Store the name in the map.
					//
					pMap->SetAt(lKey, pwcDeviceName);
					(*lNumEntries)++;
					lKey++;
				}
				else
				{
					FreeMapMemory(pMap);
					return E_FAIL;
				}

				// Clear out the variants for the next pass.
				//
				VariantClear(&vDevNames);

			}	// END for (long j = 0; j < lNumDevices; j++)

			// Clear out the variants for the next pass.
			//
			VariantClear(&vDevHandlesHolder);
			VariantClear(&vDevNamesHolder);
			VariantClear(&vChanHandles);
		}
		else
		{
			FreeMapMemory(pMap);
			return E_FAIL;
		}

		// Clear the variants for the next channel
		//
		VariantClear(&vChanNames);
		VariantClear(&vDevNames);

	}	// END for (long i = 0; i < lNumChannels; i++)

	// jra 101498
	// Clear any remaining variants. This was moved out of the above loop.
	//
	VariantClear(&vChanHandlesHolder);
	VariantClear(&vChanNamesHolder);

	return S_OK;
}


////////////////////////////////////////////////////////////////
// HRESULT CImpIOPCBrowseServer::GetDatablockList()
//
// @desc This function places all of the datablocks for a given driver
//			and device in a CMap. Filtering is performed on the DataBlock
//			name, not the I/O Address.
//
// @retval	S_OK	if the function was successful
//			S_FAIL	if the function failed in some way. If
//					this happens, then all of the memory associated
//					with the entries in the map will be freed.
//			E_OUTOFMEMORY if a call to the new operator
//					returns NULL. Again, all of the memory associated
//					with the entries in the map will be freed.
//
// TODO	You will probably need to change the hint string returned. Perhaps
//		your driver's datablock name is a tag name in the PLC, so you can
//		return the data block name or whatever fits the driver's need.
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::GetDatablockList(CLongPtrMap		*pMap,			/* OUT */
											   long				*lNumEntries,	/* OUT */
											   CString			szDeviceName,	/* IN */
											   OPCBROWSETYPE	dwBrowseType,	/* IN */
											   CString			szFilterString,/* IN */
											   FILTERTYPE		dwFilterType)	/* IN */
{
	HRESULT		hr;
	VARIANT		vDataBlockHandlesHolder,
				vDataBlockNamesHolder,
				vDataBlockHandle,
				vDataBlockName;
	long		lNumDataBlocks			= 0,
				lCurrentDeviceHandle	= 0,
				lDataBlockHandle		= 0,
				lIndex					= 0,
				lMapLookupKey			= 100L,
				lNumDevices				= 1L,
				lKey					= 0L,
				lCount					= 0L;
	int			nLength					= 0,
				nIndex					= 0;
	CString		szStartAddress,
				szEndAddress,
				szBrowseString,
				szDataBlockName;
	char		*pszPropertyDataList;
	WCHAR		*pwcHintAddress			= NULL,
				*pwcDeviceName			= NULL,
				*pwcTemp				= NULL;
	CLongPtrMap	mapTemp,
				*pMapTemp = &mapTemp;


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

	// Initialize the variants
	VariantInit(&vDataBlockHandlesHolder);
	VariantInit(&vDataBlockNamesHolder);
	VariantInit(&vDataBlockHandle);
	VariantInit(&vDataBlockName);

	// Make sure we were able load the DLL and connect to the OLE Server
	if (NULL == m_pParentServer->m_pIDriver)
	{
		FreeMapMemory(pMap);
		return E_FAIL;
	}

	// Allocate the memory for the data list off of the stack
	//
	pszPropertyDataList = (char *) _alloca(SIZE_OF_PROPERTY_DATA_STRINGS * g_lNumDataBlockProps);
	if (NULL == pszPropertyDataList)
	{
		return E_OUTOFMEMORY;
	}

	do
	{
		// Find the device handle that we are on
		if (FAILED(GetHandleFromName(szDeviceName, lCurrentDeviceHandle)))
		{
			FreeMapMemory(pMap);
			return E_FAIL;
		}
			
		// Get a variant array containing all of the datablock handles and
		// names for this device.
		//
		hr = m_pParentServer->m_pIDriver->GetDataBlocks(lCurrentDeviceHandle, 
														&vDataBlockHandlesHolder,
														&vDataBlockNamesHolder,
														&lNumDataBlocks);
		if (FAILED(hr))
		{
			FreeMapMemory(pMap);
			return E_FAIL;
		}

		//
		// Loop through the datablocks and do a GetPropertyData() for the
		// start and end address on all of them. We will then build a "hint"
		// address to return to the client.
		//
		for (long i = 0; i < lNumDataBlocks; i++)
		{
			hr =  SafeArrayGetElement(vDataBlockHandlesHolder.parray,
									  &i, &vDataBlockHandle);
			if (SUCCEEDED(hr))
			{
				// Save over the datablock name (currently not used).
				//
				szDataBlockName.Empty();
				hr = SafeArrayGetElement(vDataBlockNamesHolder.parray,
										 &i, &vDataBlockName);
				if (SUCCEEDED(hr))
				{
					szDataBlockName = vDataBlockName.bstrVal;
				}

				// Get the datablock handle
				lDataBlockHandle = vDataBlockHandle.lVal;

				// Reinitialize the variants
				VariantClear(&vDataBlockName);
				VariantClear(&vDataBlockHandle);

				// Get the data for the start and end address
				//
				if (FAILED(GetDataBlockPropertyData(lDataBlockHandle,
													pszPropertyDataList)))
				{
					// We were not able to get the properties, so return an error.
					FreeMapMemory(pMap);
					return E_FAIL;
				}

				//////////////////////////////////////////////////////////////
				//
				// TODO: You will need to modify the following code if your driver
				//		 does not have a start address and/or end address property.
				//
				//////////////////////////////////////////////////////////////
				szStartAddress	= GetDataFromList(pszPropertyDataList, START_ADDRESS_PROP);
				szEndAddress	= GetDataFromList(pszPropertyDataList, END_ADDRESS_PROP);

				// Build the "Hint" string that we will return to the client.
				// It will be in the following format:
				//
				//		"0 - 100  (*hint: StartAddr - EndAddr)"
				//
				szBrowseString = szStartAddress;
				szBrowseString += " - ";
				szBrowseString += szEndAddress;

				// We filter on the "start address - end address" string.
				// If the string does not match the filtering criteria, then
				// continue on to the next one.
				//
				if (FALSE == FilterString(szBrowseString, szFilterString, dwFilterType))
				{
					continue;
				}

				// Finish building the hint string
				//
				szBrowseString += HINT_STRING;

				// Convert it to a WCHAR and store it in the map
				nLength	= szBrowseString.GetLength();
				pwcTemp	= A2W(szBrowseString.GetBuffer(nLength+1));
				szBrowseString.ReleaseBuffer();

				pwcHintAddress	= new WCHAR [nLength+1];
				if (NULL == pwcHintAddress)
				{
					FreeMapMemory(pMap);
					return E_OUTOFMEMORY;
				}
				wcscpy(pwcHintAddress, pwcTemp);

				// Loop until we find an open key in the map. When we do find one,
				// add the string to it.
				//
				while(TRUE == (pMap->Lookup(lMapLookupKey, pwcTemp)))
				{
					lMapLookupKey++;
				}

				pMap->SetAt(lMapLookupKey, pwcHintAddress);
				(*lNumEntries)++;
			}
			else
			{
				FreeMapMemory(pMap);
				return E_FAIL;
			}
		}	// END for (long i = 0; i < lNumDataBlocks; i++)

		// Clear the variants for the next pass
		VariantClear(&vDataBlockHandlesHolder);
		VariantClear(&vDataBlockNamesHolder);
		VariantClear(&vDataBlockHandle);
		VariantClear(&vDataBlockName);

	} while (++lCount < lNumDevices);

	return S_OK;
}


////////////////////////////////////////////////////////////////
// void CImpIOPCBrowseServer::GetDataBlockPropertyList()
//
// @desc Gets the required properties for a given datablock.
//
// @parm none
//
// @retval	S_OK	success
//			E_FAIL	failure
//
// TODO:	Modified the g_pszDataBlockProps array to add/remove whatever
//			properties you need to obtain from the driver.
//
// @ref	GetDataBlockPropertyData(), FreeDataBlockPropertyList()
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::GetDataBlockPropertyList()
{
	VARIANT		vPropertyName;
	CString		szProperty;


	// Initialize the variants
	//
	VariantInit(&m_vPropertyNames);
	VariantInit(&vPropertyName);

	// Create a new array to hold the property names
	//
	m_vPropertyNames.vt = VT_ARRAY | VT_VARIANT;
	if (FAILED(NewArray(g_lNumDataBlockProps, &m_vPropertyNames.parray)))
	{
		VariantClear(&m_vPropertyNames);
		return E_FAIL;
	}

	// Add the property names to the variant array
	//
	for (long lIndex = 0; lIndex < g_lNumDataBlockProps; lIndex++)
	{
		szProperty = g_pszDataBlockProps[lIndex];
		vPropertyName.vt = VT_BSTR;
		vPropertyName.bstrVal = szProperty.AllocSysString();

		if (FAILED(SafeArrayPutElement(m_vPropertyNames.parray, &lIndex, &vPropertyName)))
		{
			VariantClear(&m_vPropertyNames);
			VariantClear(&vPropertyName);
			return E_FAIL;
		}
		VariantClear(&vPropertyName);
	}

	return S_OK;
}


////////////////////////////////////////////////////////////////
// void CImpIOPCBrowseServer::FreeDataBlockPropertyList()
//
// @desc Gets the required properties for a given datablock.
//
// @parm none
//
// @retval	S_OK	success
// @retval	Any valid return from VariantClear()
//
// TODO:	Nothing
//
// @ref	GetDataBlockPropertyList(), GetDataBlockPropertyData()
//
////////////////////////////////////////////////////////////////
HRESULT	CImpIOPCBrowseServer::FreeDataBlockPropertyList()
{
	return VariantClear(&m_vPropertyNames);
}


////////////////////////////////////////////////////////////////
// HRESULT CImpIOPCBrowseServer::GetDataBlockPropertyData()
//
// @desc Gets the required properties for a given datablock.
//
// @parm long		| lDataBlockHandle	| Handle to the datablock
// @parm CString &	| szStartAddress	| Returned start address
// @parm CString &	| szEndAddress		| Returned end address
//
// @retval	S_OK	successful
//			E_FAIL	failure
//
// TODO:	Modify function parameter list to pass in a reference to
//			whatever properties you need to get. Also change the switch
//			statement to save the returned data for each property.
//
// @ref		GetDataBlockPropertyList()
//
// @devnote You must have called GetDataBlockPropertyList() at some
//			point before calling this function!
//
////////////////////////////////////////////////////////////////
HRESULT CImpIOPCBrowseServer::GetDataBlockPropertyData(long		lDataBlockHandle,
													   char		*pszPropertyData)
{
	HRESULT	hr;
	VARIANT	vPropertyData,
			vErrors,
			vTemp;
	CString	szData;


	// Initialize the variants
	//
	VariantInit(&vPropertyData);
	VariantInit(&vErrors);
	VariantInit(&vTemp);

	hr = m_pParentServer->m_pIDriver->GetPropertyData(lDataBlockHandle,
													  m_vPropertyNames,
													  &vPropertyData,
													  &vErrors);
	if (hr != S_OK)
	{
		return E_FAIL;
	}

	// Init the string buffer
	//
	memset(pszPropertyData, NULL, g_lNumDataBlockProps * SIZE_OF_PROPERTY_DATA_STRINGS);

	// Extract the data from the returned array
	//

⌨️ 快捷键说明

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