📄 impiopcbrowseserveraddressspace.cpp
字号:
// @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 + -