Fix
This commit is contained in:
441
Technosoftware/DaAeHdaClient.Com/Hda/Browser.cs
Normal file
441
Technosoftware/DaAeHdaClient.Com/Hda/Browser.cs
Normal file
@@ -0,0 +1,441 @@
|
||||
#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
// Web: https://www.technosoftware.com
|
||||
//
|
||||
// The source code in this file is covered under a dual-license scenario:
|
||||
// - Owner of a purchased license: SCLA 1.0
|
||||
// - GPL V3: everybody else
|
||||
//
|
||||
// SCLA license terms accompanied with this source code.
|
||||
// See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf
|
||||
//
|
||||
// GNU General Public License as published by the Free Software Foundation;
|
||||
// version 3 of the License are accompanied with this source code.
|
||||
// See https://technosoftware.com/license/GPLv3License.txt
|
||||
//
|
||||
// This source code is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
|
||||
#region Using Directives
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Technosoftware.DaAeHdaClient.Hda;
|
||||
using Technosoftware.OpcRcw.Hda;
|
||||
using Technosoftware.OpcRcw.Comn;
|
||||
#endregion
|
||||
|
||||
namespace Technosoftware.DaAeHdaClient.Com.Hda
|
||||
{
|
||||
/// <summary>
|
||||
/// An in-process wrapper an OPC HDA browser object.
|
||||
/// </summary>
|
||||
internal class Browser : ITsCHdaBrowser
|
||||
{
|
||||
//======================================================================
|
||||
// Construction
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the object with the specifed COM server.
|
||||
/// </summary>
|
||||
internal Browser(Server server, IOPCHDA_Browser browser, TsCHdaBrowseFilter[] filters, OpcResult[] results)
|
||||
{
|
||||
if (browser == null) throw new ArgumentNullException(nameof(browser));
|
||||
|
||||
// save the server object that created the browser.
|
||||
m_server = server;
|
||||
|
||||
// save the COM server (released in Dispose()).
|
||||
m_browser = browser;
|
||||
|
||||
// save only the filters that were accepted.
|
||||
if (filters != null)
|
||||
{
|
||||
var validFilters = new ArrayList();
|
||||
|
||||
for (var ii = 0; ii < filters.Length; ii++)
|
||||
{
|
||||
if (results[ii].Succeeded())
|
||||
{
|
||||
validFilters.Add(filters[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
m_filters = new TsCHdaBrowseFilterCollection(validFilters);
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
/// <summary>
|
||||
/// This must be called explicitly by clients to ensure the COM server is released.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
m_server = null;
|
||||
Utilities.Interop.ReleaseServer(m_browser);
|
||||
m_browser = null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//======================================================================
|
||||
// Filters
|
||||
|
||||
/// <summary>
|
||||
/// Returns the set of attribute filters used by the browser.
|
||||
/// </summary>
|
||||
public TsCHdaBrowseFilterCollection Filters
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
return (TsCHdaBrowseFilterCollection)m_filters.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Browse
|
||||
|
||||
/// <summary>
|
||||
/// Browses the server's address space at the specified branch.
|
||||
/// </summary>
|
||||
/// <param name="itemID">The item id of the branch to search.</param>
|
||||
/// <returns>The set of elements that meet the filter criteria.</returns>
|
||||
public TsCHdaBrowseElement[] Browse(OpcItem itemID)
|
||||
{
|
||||
IOpcBrowsePosition position;
|
||||
var elements = Browse(itemID, 0, out position);
|
||||
|
||||
if (position != null)
|
||||
{
|
||||
position.Dispose();
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begins a browsing the server's address space at the specified branch.
|
||||
/// </summary>
|
||||
/// <param name="itemID">The item id of the branch to search.</param>
|
||||
/// <param name="maxElements">The maximum number of elements to return.</param>
|
||||
/// <param name="position">The position object used to continue a browse operation.</param>
|
||||
/// <returns>The set of elements that meet the filter criteria.</returns>
|
||||
public TsCHdaBrowseElement[] Browse(OpcItem itemID, int maxElements, out IOpcBrowsePosition position)
|
||||
{
|
||||
position = null;
|
||||
|
||||
// interpret invalid values as 'no limit'.
|
||||
if (maxElements <= 0)
|
||||
{
|
||||
maxElements = int.MaxValue;
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
var branchPath = (itemID != null && itemID.ItemName != null)?itemID.ItemName:"";
|
||||
|
||||
// move to the correct position in the server's address space.
|
||||
try
|
||||
{
|
||||
m_browser.ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, branchPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Utilities.Interop.CreateException("IOPCHDA_Browser.ChangeBrowsePosition", e);
|
||||
}
|
||||
|
||||
// browse for branches
|
||||
var enumerator = GetEnumerator(true);
|
||||
|
||||
var elements = FetchElements(enumerator, maxElements, true);
|
||||
|
||||
// check if max element count reached.
|
||||
if (elements.Count >= maxElements)
|
||||
{
|
||||
position = new BrowsePosition(branchPath, enumerator, false);
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
|
||||
// release enumerator.
|
||||
enumerator.Dispose();
|
||||
|
||||
// browse for items
|
||||
enumerator = GetEnumerator(false);
|
||||
|
||||
var items = FetchElements(enumerator, maxElements-elements.Count, false);
|
||||
|
||||
if (items != null)
|
||||
{
|
||||
elements.AddRange(items);
|
||||
}
|
||||
|
||||
// check if max element count reached.
|
||||
if (elements.Count >= maxElements)
|
||||
{
|
||||
position = new BrowsePosition(branchPath, enumerator, true);
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
|
||||
// release enumerator.
|
||||
enumerator.Dispose();
|
||||
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// BrowseNext
|
||||
|
||||
/// <summary>
|
||||
/// Continues browsing the server's address space at the specified position.
|
||||
/// </summary>
|
||||
/// <param name="maxElements">The maximum number of elements to return.</param>
|
||||
/// <param name="position">The position object used to continue a browse operation.</param>
|
||||
/// <returns>The set of elements that meet the filter criteria.</returns>
|
||||
public TsCHdaBrowseElement[] BrowseNext(int maxElements, ref IOpcBrowsePosition position)
|
||||
{
|
||||
// check arguments.
|
||||
if (position == null || position.GetType() != typeof(BrowsePosition))
|
||||
{
|
||||
throw new ArgumentException("Not a valid browse position object.", nameof(position));
|
||||
}
|
||||
|
||||
// interpret invalid values as 'no limit'.
|
||||
if (maxElements <= 0)
|
||||
{
|
||||
maxElements = int.MaxValue;
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
var pos = (BrowsePosition)position;
|
||||
|
||||
var elements = new ArrayList();
|
||||
|
||||
if (!pos.FetchingItems)
|
||||
{
|
||||
elements = FetchElements(pos.Enumerator, maxElements, true);
|
||||
|
||||
// check if max element count reached.
|
||||
if (elements.Count >= maxElements)
|
||||
{
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
|
||||
// release enumerator.
|
||||
pos.Enumerator.Dispose();
|
||||
|
||||
pos.Enumerator = null;
|
||||
pos.FetchingItems = true;
|
||||
|
||||
// move to the correct position in the server's address space.
|
||||
try
|
||||
{
|
||||
m_browser.ChangeBrowsePosition(OPCHDA_BROWSEDIRECTION.OPCHDA_BROWSE_DIRECT, pos.BranchPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Utilities.Interop.CreateException("IOPCHDA_Browser.ChangeBrowsePosition", e);
|
||||
}
|
||||
|
||||
// create enumerator for items.
|
||||
pos.Enumerator = GetEnumerator(false);
|
||||
}
|
||||
|
||||
// fetch next set of items.
|
||||
var items = FetchElements(pos.Enumerator, maxElements-elements.Count, false);
|
||||
|
||||
if (items != null)
|
||||
{
|
||||
elements.AddRange(items);
|
||||
}
|
||||
|
||||
// check if max element count reached.
|
||||
if (elements.Count >= maxElements)
|
||||
{
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
|
||||
// release position object.
|
||||
position.Dispose();
|
||||
position = null;
|
||||
|
||||
// return elements.
|
||||
return (TsCHdaBrowseElement[])elements.ToArray(typeof(TsCHdaBrowseElement));
|
||||
}
|
||||
}
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Creates an enumerator for the elements contained with the current branch.
|
||||
/// </summary>
|
||||
private EnumString GetEnumerator(bool isBranch)
|
||||
{
|
||||
try
|
||||
{
|
||||
var browseType = (isBranch)?OPCHDA_BROWSETYPE.OPCHDA_BRANCH:OPCHDA_BROWSETYPE.OPCHDA_LEAF;
|
||||
|
||||
IEnumString pEnumerator = null;
|
||||
m_browser.GetEnum(browseType, out pEnumerator);
|
||||
|
||||
return new EnumString(pEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Utilities.Interop.CreateException("IOPCHDA_Browser.GetEnum", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the element names and item ids for each element.
|
||||
/// </summary>
|
||||
private ArrayList FetchElements(EnumString enumerator, int maxElements, bool isBranch)
|
||||
{
|
||||
var elements = new ArrayList();
|
||||
|
||||
while (elements.Count < maxElements)
|
||||
{
|
||||
// fetch next batch of element names.
|
||||
var count = BLOCK_SIZE;
|
||||
|
||||
if (elements.Count + count > maxElements)
|
||||
{
|
||||
count = maxElements - elements.Count;
|
||||
}
|
||||
var names = enumerator.Next(count);
|
||||
|
||||
// check if no more elements found.
|
||||
if (names == null || names.Length == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// create new element objects.
|
||||
foreach (var name in names)
|
||||
{
|
||||
var element = new TsCHdaBrowseElement();
|
||||
|
||||
element.Name = name;
|
||||
// lookup item id for element.
|
||||
try
|
||||
{
|
||||
string itemID = null;
|
||||
m_browser.GetItemID(name, out itemID);
|
||||
|
||||
element.ItemName = itemID;
|
||||
element.ItemPath = null;
|
||||
element.HasChildren = isBranch;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors.
|
||||
}
|
||||
|
||||
elements.Add(element);
|
||||
}
|
||||
}
|
||||
|
||||
// validate items - this is necessary to set the IsItem flag correctly.
|
||||
var results = m_server.ValidateItems((OpcItem[])elements.ToArray(typeof(OpcItem)));
|
||||
|
||||
if (results != null)
|
||||
{
|
||||
for (var ii = 0; ii < results.Length; ii++)
|
||||
{
|
||||
if (results[ii].Result.Succeeded())
|
||||
{
|
||||
((TsCHdaBrowseElement)elements[ii]).IsItem = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return results.
|
||||
return elements;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
private Server m_server = null;
|
||||
private IOPCHDA_Browser m_browser = null;
|
||||
private TsCHdaBrowseFilterCollection m_filters = new TsCHdaBrowseFilterCollection();
|
||||
private const int BLOCK_SIZE = 10;
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the state of a browse operation that was halted.
|
||||
/// </summary>
|
||||
internal class BrowsePosition : TsCHdaBrowsePosition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a the object with the browse operation state information.
|
||||
/// </summary>
|
||||
/// <param name="branchPath">The item id of branch used in the browse operation.</param>
|
||||
/// <param name="enumerator">The enumerator used for the browse operation.</param>
|
||||
/// <param name="fetchingItems">Whether the enumerator is return branches or items.</param>
|
||||
internal BrowsePosition(string branchPath, EnumString enumerator, bool fetchingItems)
|
||||
{
|
||||
m_branchPath = branchPath;
|
||||
m_enumerator = enumerator;
|
||||
m_fetchingItems = fetchingItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The item id of the branch being browsed.
|
||||
/// </summary>
|
||||
internal string BranchPath
|
||||
{
|
||||
get => m_branchPath;
|
||||
set => m_branchPath = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The enumerator that was in use when the browse halted.
|
||||
/// </summary>
|
||||
internal EnumString Enumerator
|
||||
{
|
||||
get => m_enumerator;
|
||||
set => m_enumerator = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the browse halted while fetching items.
|
||||
/// </summary>
|
||||
internal bool FetchingItems
|
||||
{
|
||||
get => m_fetchingItems;
|
||||
set => m_fetchingItems = value;
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
/// <summary>
|
||||
/// Releases any unmanaged resources held by the object.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
if (m_enumerator != null)
|
||||
{
|
||||
m_enumerator.Dispose();
|
||||
m_enumerator = null;
|
||||
}
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
private string m_branchPath = null;
|
||||
private EnumString m_enumerator = null;
|
||||
private bool m_fetchingItems = false;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
591
Technosoftware/DaAeHdaClient.Com/Hda/DataCallback.cs
Normal file
591
Technosoftware/DaAeHdaClient.Com/Hda/DataCallback.cs
Normal file
@@ -0,0 +1,591 @@
|
||||
#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
// Web: https://www.technosoftware.com
|
||||
//
|
||||
// The source code in this file is covered under a dual-license scenario:
|
||||
// - Owner of a purchased license: SCLA 1.0
|
||||
// - GPL V3: everybody else
|
||||
//
|
||||
// SCLA license terms accompanied with this source code.
|
||||
// See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf
|
||||
//
|
||||
// GNU General Public License as published by the Free Software Foundation;
|
||||
// version 3 of the License are accompanied with this source code.
|
||||
// See https://technosoftware.com/license/GPLv3License.txt
|
||||
//
|
||||
// This source code is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
|
||||
#region Using Directives
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Technosoftware.DaAeHdaClient.Hda;
|
||||
using Technosoftware.OpcRcw.Hda;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Technosoftware.DaAeHdaClient.Com.Hda
|
||||
{
|
||||
/// <summary>
|
||||
/// A class that implements the HDA data callback interface.
|
||||
/// </summary>
|
||||
internal class DataCallback : IOPCHDA_DataCallback
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the object with the containing subscription object.
|
||||
/// </summary>
|
||||
public DataCallback() {}
|
||||
|
||||
/// <summary>
|
||||
/// Fired when an exception occurs during callback processing.
|
||||
/// </summary>
|
||||
public event TsCHdaCallbackExceptionEventHandler CallbackExceptionEvent
|
||||
{
|
||||
add {lock (this) { _callbackExceptionEvent += value; }}
|
||||
remove {lock (this) { _callbackExceptionEvent -= value; }}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new request object.
|
||||
/// </summary>
|
||||
public Request CreateRequest(object requestHandle, Delegate callback)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// create a new request.
|
||||
var request = new Request(requestHandle, callback, ++m_nextID);
|
||||
|
||||
// no items yet - callback may return before async call returns.
|
||||
m_requests[request.RequestID] = request;
|
||||
|
||||
// return requests.
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels an existing request.
|
||||
/// </summary>
|
||||
public bool CancelRequest(Request request, TsCHdaCancelCompleteEventHandler callback)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// check if it is a valid request.
|
||||
if (!m_requests.Contains(request.RequestID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// request will be removed when the cancel complete callback arrives.
|
||||
if (callback != null)
|
||||
{
|
||||
request.CancelCompleteEvent += callback;
|
||||
}
|
||||
|
||||
// no confirmation required - remove request immediately.
|
||||
else
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
|
||||
// request will be cancelled.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#region IOPCHDA_DataCallback Members
|
||||
/// <summary>
|
||||
/// Called when new data arrives for a subscription.
|
||||
/// </summary>
|
||||
public void OnDataChange(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwNumItems,
|
||||
OPCHDA_ITEM[] pItemValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaItemValueCollection[pItemValues.Length];
|
||||
|
||||
for (var ii = 0; ii < pItemValues.Length; ii++)
|
||||
{
|
||||
results[ii] = Interop.GetItemValueCollection(pItemValues[ii], false);
|
||||
|
||||
results[ii].ServerHandle = results[ii].ClientHandle;
|
||||
results[ii].ClientHandle = null;
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if unexpected error occured.
|
||||
if (request.InvokeCallback(results))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous read request completes.
|
||||
/// </summary>
|
||||
public void OnReadComplete(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwNumItems,
|
||||
OPCHDA_ITEM[] pItemValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaItemValueCollection[pItemValues.Length];
|
||||
|
||||
for (var ii = 0; ii < pItemValues.Length; ii++)
|
||||
{
|
||||
results[ii] = Interop.GetItemValueCollection(pItemValues[ii], false);
|
||||
|
||||
results[ii].ServerHandle = pItemValues[ii].hClient;
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback(results))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous read modified request completes.
|
||||
/// </summary>
|
||||
public void OnReadModifiedComplete(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwNumItems,
|
||||
OPCHDA_MODIFIEDITEM[] pItemValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaModifiedValueCollection[pItemValues.Length];
|
||||
|
||||
for (var ii = 0; ii < pItemValues.Length; ii++)
|
||||
{
|
||||
results[ii] = Interop.GetModifiedValueCollection(pItemValues[ii], false);
|
||||
|
||||
results[ii].ServerHandle = pItemValues[ii].hClient;
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback(results))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous read attributes request completes.
|
||||
/// </summary>
|
||||
public void OnReadAttributeComplete(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int hClient,
|
||||
int dwNumItems,
|
||||
OPCHDA_ATTRIBUTE[] pAttributeValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// create item object to collect results.
|
||||
var item = new TsCHdaItemAttributeCollection();
|
||||
item.ServerHandle = hClient;
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaAttributeValueCollection[pAttributeValues.Length];
|
||||
|
||||
for (var ii = 0; ii < pAttributeValues.Length; ii++)
|
||||
{
|
||||
results[ii] = Interop.GetAttributeValueCollection(pAttributeValues[ii], false);
|
||||
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
|
||||
item.Add(results[ii]);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback(item))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous read annotations request completes.
|
||||
/// </summary>
|
||||
public void OnReadAnnotations(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwNumItems,
|
||||
OPCHDA_ANNOTATION[] pAnnotationValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaAnnotationValueCollection[pAnnotationValues.Length];
|
||||
|
||||
for (var ii = 0; ii < pAnnotationValues.Length; ii++)
|
||||
{
|
||||
results[ii] = Interop.GetAnnotationValueCollection(pAnnotationValues[ii], false);
|
||||
|
||||
results[ii].ServerHandle = pAnnotationValues[ii].hClient;
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback(results))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous insert annotations request completes.
|
||||
/// </summary>
|
||||
public void OnInsertAnnotations(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwCount,
|
||||
int[] phClients,
|
||||
int[] phrErrors)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new ArrayList();
|
||||
|
||||
if (dwCount > 0)
|
||||
{
|
||||
// subscription results in collections for the same item id.
|
||||
var currentHandle = phClients[0];
|
||||
|
||||
var itemResults = new TsCHdaResultCollection();
|
||||
|
||||
for (var ii = 0; ii < dwCount; ii++)
|
||||
{
|
||||
// create a new collection for the next item's results.
|
||||
if (phClients[ii] != currentHandle)
|
||||
{
|
||||
itemResults.ServerHandle = currentHandle;
|
||||
results.Add(itemResults);
|
||||
|
||||
currentHandle = phClients[ii];
|
||||
itemResults = new TsCHdaResultCollection();
|
||||
}
|
||||
|
||||
var result = new TsCHdaResult(Utilities.Interop.GetResultId(phrErrors[ii]));
|
||||
itemResults.Add(result);
|
||||
}
|
||||
|
||||
// add the last set of item results.
|
||||
itemResults.ServerHandle = currentHandle;
|
||||
results.Add(itemResults);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback((TsCHdaResultCollection[])results.ToArray(typeof(TsCHdaResultCollection))))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a batch of data from playback request arrives.
|
||||
/// </summary>
|
||||
public void OnPlayback(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwNumItems,
|
||||
IntPtr ppItemValues,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new TsCHdaItemValueCollection[dwNumItems];
|
||||
|
||||
// the data is transfered as a array of pointers to items instead of simply
|
||||
// as an array of items. This is due to a mistake in the HDA IDL.
|
||||
var pItems = Utilities.Interop.GetInt32s(ref ppItemValues, dwNumItems, false);
|
||||
|
||||
for (var ii = 0; ii < dwNumItems; ii++)
|
||||
{
|
||||
// get pointer to item.
|
||||
var pItem = (IntPtr)pItems[ii];
|
||||
|
||||
// unmarshal item as an array of length 1.
|
||||
var item = Interop.GetItemValueCollections(ref pItem, 1, false);
|
||||
|
||||
if (item != null && item.Length == 1)
|
||||
{
|
||||
results[ii] = item[0];
|
||||
results[ii].ServerHandle = results[ii].ClientHandle;
|
||||
results[ii].ClientHandle = null;
|
||||
results[ii].Result = Utilities.Interop.GetResultId(phrErrors[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
// invoke callback - remove request if unexpected error occured.
|
||||
if (request.InvokeCallback(results))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous update request completes.
|
||||
/// </summary>
|
||||
public void OnUpdateComplete(
|
||||
int dwTransactionID,
|
||||
int hrStatus,
|
||||
int dwCount,
|
||||
int[] phClients,
|
||||
int[] phrErrors)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request transaction.
|
||||
var request = (Request)m_requests[dwTransactionID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unmarshal results.
|
||||
var results = new ArrayList();
|
||||
|
||||
if (dwCount > 0)
|
||||
{
|
||||
// subscription results in collections for the same item id.
|
||||
var currentHandle = phClients[0];
|
||||
|
||||
var itemResults = new TsCHdaResultCollection();
|
||||
|
||||
for (var ii = 0; ii < dwCount; ii++)
|
||||
{
|
||||
// create a new collection for the next item's results.
|
||||
if (phClients[ii] != currentHandle)
|
||||
{
|
||||
itemResults.ServerHandle = currentHandle;
|
||||
results.Add(itemResults);
|
||||
|
||||
currentHandle = phClients[ii];
|
||||
itemResults = new TsCHdaResultCollection();
|
||||
}
|
||||
|
||||
var result = new TsCHdaResult(Utilities.Interop.GetResultId(phrErrors[ii]));
|
||||
itemResults.Add(result);
|
||||
}
|
||||
|
||||
// add the last set of item results.
|
||||
itemResults.ServerHandle = currentHandle;
|
||||
results.Add(itemResults);
|
||||
}
|
||||
|
||||
// invoke callback - remove request if all results arrived.
|
||||
if (request.InvokeCallback((TsCHdaResultCollection[])results.ToArray(typeof(TsCHdaResultCollection))))
|
||||
{
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwTransactionID, exception);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an asynchronous request was cancelled successfully.
|
||||
/// </summary>
|
||||
public void OnCancelComplete(int dwCancelID)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request.
|
||||
var request = (Request)m_requests[dwCancelID];
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// send the cancel complete notification.
|
||||
request.OnCancelComplete();
|
||||
|
||||
// remove the request.
|
||||
m_requests.Remove(request.RequestID);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
HandleException(dwCancelID, exception);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Fires an event indicating an exception occurred during callback processing.
|
||||
/// </summary>
|
||||
void HandleException(int requestID, Exception exception)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// lookup request.
|
||||
var request = (Request)m_requests[requestID];
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
// send notification.
|
||||
if (_callbackExceptionEvent != null)
|
||||
{
|
||||
_callbackExceptionEvent(request, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
private int m_nextID;
|
||||
private Hashtable m_requests = new Hashtable();
|
||||
private TsCHdaCallbackExceptionEventHandler _callbackExceptionEvent;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
441
Technosoftware/DaAeHdaClient.Com/Hda/Interop.cs
Normal file
441
Technosoftware/DaAeHdaClient.Com/Hda/Interop.cs
Normal file
@@ -0,0 +1,441 @@
|
||||
#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
// Web: https://www.technosoftware.com
|
||||
//
|
||||
// The source code in this file is covered under a dual-license scenario:
|
||||
// - Owner of a purchased license: SCLA 1.0
|
||||
// - GPL V3: everybody else
|
||||
//
|
||||
// SCLA license terms accompanied with this source code.
|
||||
// See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf
|
||||
//
|
||||
// GNU General Public License as published by the Free Software Foundation;
|
||||
// version 3 of the License are accompanied with this source code.
|
||||
// See https://technosoftware.com/license/GPLv3License.txt
|
||||
//
|
||||
// This source code is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
|
||||
#region Using Directives
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Technosoftware.DaAeHdaClient.Da;
|
||||
using Technosoftware.DaAeHdaClient.Hda;
|
||||
#endregion
|
||||
|
||||
#pragma warning disable 0618
|
||||
|
||||
namespace Technosoftware.DaAeHdaClient.Com.Hda
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains state information for a single asynchronous Technosoftware.DaAeHdaClient.Com.Hda.Interop.
|
||||
/// </summary>
|
||||
internal class Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a standard FILETIME to an OpcRcw.Da.FILETIME structure.
|
||||
/// </summary>
|
||||
internal static OpcRcw.Hda.OPCHDA_FILETIME Convert(FILETIME input)
|
||||
{
|
||||
var output = new OpcRcw.Hda.OPCHDA_FILETIME();
|
||||
output.dwLowDateTime = input.dwLowDateTime;
|
||||
output.dwHighDateTime = input.dwHighDateTime;
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an OpcRcw.Da.FILETIME to a standard FILETIME structure.
|
||||
/// </summary>
|
||||
internal static FILETIME Convert(OpcRcw.Hda.OPCHDA_FILETIME input)
|
||||
{
|
||||
var output = new FILETIME();
|
||||
output.dwLowDateTime = input.dwLowDateTime;
|
||||
output.dwHighDateTime = input.dwHighDateTime;
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a decimal value to a OpcRcw.Hda.OPCHDA_TIME structure.
|
||||
/// </summary>
|
||||
internal static OpcRcw.Hda.OPCHDA_FILETIME GetFILETIME(decimal input)
|
||||
{
|
||||
var output = new OpcRcw.Hda.OPCHDA_FILETIME();
|
||||
|
||||
output.dwHighDateTime = (int)((((ulong)(input*10000000)) & 0xFFFFFFFF00000000)>>32);
|
||||
output.dwLowDateTime = (int)((((ulong)(input*10000000)) & 0x00000000FFFFFFFF));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of FILETIMEs.
|
||||
/// </summary>
|
||||
internal static OpcRcw.Hda.OPCHDA_FILETIME[] GetFILETIMEs(DateTime[] input)
|
||||
{
|
||||
OpcRcw.Hda.OPCHDA_FILETIME[] output = null;
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
output = new OpcRcw.Hda.OPCHDA_FILETIME[input.Length];
|
||||
|
||||
for (var ii = 0; ii < input.Length; ii++)
|
||||
{
|
||||
output[ii] = Convert(Technosoftware.DaAeHdaClient.Com.Interop.GetFILETIME(input[ii]));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Technosoftware.DaAeHdaClient.Time object to a Technosoftware.DaAeHdaClient.Com.Hda.OPCHDA_TIME structure.
|
||||
/// </summary>
|
||||
internal static OpcRcw.Hda.OPCHDA_TIME GetTime(TsCHdaTime input)
|
||||
{
|
||||
var output = new OpcRcw.Hda.OPCHDA_TIME();
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
output.ftTime = Convert(Technosoftware.DaAeHdaClient.Com.Interop.GetFILETIME(input.AbsoluteTime));
|
||||
output.szTime = (input.IsRelative)?input.ToString():"";
|
||||
output.bString = (input.IsRelative)?1:0;
|
||||
}
|
||||
|
||||
// create a null value for a time structure.
|
||||
else
|
||||
{
|
||||
output.ftTime = Convert(Technosoftware.DaAeHdaClient.Com.Interop.GetFILETIME(DateTime.MinValue));
|
||||
output.szTime = "";
|
||||
output.bString = 1;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an array of OPCHDA_ITEM structures.
|
||||
/// </summary>
|
||||
internal static TsCHdaItemValueCollection[] GetItemValueCollections(ref IntPtr pInput, int count, bool deallocate)
|
||||
{
|
||||
TsCHdaItemValueCollection[] output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero && count > 0)
|
||||
{
|
||||
output = new TsCHdaItemValueCollection[count];
|
||||
|
||||
var pos = pInput;
|
||||
|
||||
for (var ii = 0; ii < count; ii++)
|
||||
{
|
||||
output[ii] = GetItemValueCollection(pos, deallocate);
|
||||
pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OpcRcw.Hda.OPCHDA_ITEM)));
|
||||
}
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInput);
|
||||
pInput = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ITEM structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaItemValueCollection GetItemValueCollection(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
TsCHdaItemValueCollection output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
var item = Marshal.PtrToStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ITEM));
|
||||
|
||||
output = GetItemValueCollection((OpcRcw.Hda.OPCHDA_ITEM)item, deallocate);
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.DestroyStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ITEM));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ITEM structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaItemValueCollection GetItemValueCollection(OpcRcw.Hda.OPCHDA_ITEM input, bool deallocate)
|
||||
{
|
||||
var output = new TsCHdaItemValueCollection();
|
||||
|
||||
output.ClientHandle = input.hClient;
|
||||
output.Aggregate = input.haAggregate;
|
||||
|
||||
var values = Com.Interop.GetVARIANTs(ref input.pvDataValues, input.dwCount, deallocate);
|
||||
var timestamps = Utilities.Interop.GetDateTimes(ref input.pftTimeStamps, input.dwCount, deallocate);
|
||||
var qualities = Utilities.Interop.GetInt32s(ref input.pdwQualities, input.dwCount, deallocate);
|
||||
|
||||
for (var ii = 0; ii < input.dwCount; ii++)
|
||||
{
|
||||
var value = new TsCHdaItemValue();
|
||||
|
||||
value.Value = values[ii];
|
||||
value.Timestamp = timestamps[ii];
|
||||
value.Quality = new TsCDaQuality((short)(qualities[ii] & 0x0000FFFF));
|
||||
value.HistorianQuality = (TsCHdaQuality)((int)(qualities[ii] & 0xFFFF0000));
|
||||
|
||||
output.Add(value);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an array of OPCHDA_MODIFIEDITEM structures.
|
||||
/// </summary>
|
||||
internal static TsCHdaModifiedValueCollection[] GetModifiedValueCollections(ref IntPtr pInput, int count, bool deallocate)
|
||||
{
|
||||
TsCHdaModifiedValueCollection[] output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero && count > 0)
|
||||
{
|
||||
output = new TsCHdaModifiedValueCollection[count];
|
||||
|
||||
var pos = pInput;
|
||||
|
||||
for (var ii = 0; ii < count; ii++)
|
||||
{
|
||||
output[ii] = GetModifiedValueCollection(pos, deallocate);
|
||||
pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OpcRcw.Hda.OPCHDA_MODIFIEDITEM)));
|
||||
}
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInput);
|
||||
pInput = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_MODIFIEDITEM structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaModifiedValueCollection GetModifiedValueCollection(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
TsCHdaModifiedValueCollection output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
var item = Marshal.PtrToStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_MODIFIEDITEM));
|
||||
|
||||
output = GetModifiedValueCollection((OpcRcw.Hda.OPCHDA_MODIFIEDITEM)item, deallocate);
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.DestroyStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_MODIFIEDITEM));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_MODIFIEDITEM structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaModifiedValueCollection GetModifiedValueCollection(OpcRcw.Hda.OPCHDA_MODIFIEDITEM input, bool deallocate)
|
||||
{
|
||||
var output = new TsCHdaModifiedValueCollection();
|
||||
|
||||
output.ClientHandle = input.hClient;
|
||||
|
||||
var values = Com.Interop.GetVARIANTs(ref input.pvDataValues, input.dwCount, deallocate);
|
||||
var timestamps = Utilities.Interop.GetDateTimes(ref input.pftTimeStamps, input.dwCount, deallocate);
|
||||
var qualities = Utilities.Interop.GetInt32s(ref input.pdwQualities, input.dwCount, deallocate);
|
||||
var modificationTimes = Utilities.Interop.GetDateTimes(ref input.pftModificationTime, input.dwCount, deallocate);
|
||||
var editTypes = Utilities.Interop.GetInt32s(ref input.pEditType, input.dwCount, deallocate);
|
||||
var users = Utilities.Interop.GetUnicodeStrings(ref input.szUser, input.dwCount, deallocate);
|
||||
|
||||
for (var ii = 0; ii < input.dwCount; ii++)
|
||||
{
|
||||
var value = new TsCHdaModifiedValue();
|
||||
|
||||
value.Value = values[ii];
|
||||
value.Timestamp = timestamps[ii];
|
||||
value.Quality = new TsCDaQuality((short)(qualities[ii] & 0x0000FFFF));
|
||||
value.HistorianQuality = (TsCHdaQuality)((int)(qualities[ii] & 0xFFFF0000));
|
||||
value.ModificationTime = modificationTimes[ii];
|
||||
value.EditType = (TsCHdaEditType)editTypes[ii];
|
||||
value.User = users[ii];
|
||||
|
||||
output.Add(value);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an array of OPCHDA_ATTRIBUTE structures.
|
||||
/// </summary>
|
||||
internal static TsCHdaAttributeValueCollection[] GetAttributeValueCollections(ref IntPtr pInput, int count, bool deallocate)
|
||||
{
|
||||
TsCHdaAttributeValueCollection[] output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero && count > 0)
|
||||
{
|
||||
output = new TsCHdaAttributeValueCollection[count];
|
||||
|
||||
var pos = pInput;
|
||||
|
||||
for (var ii = 0; ii < count; ii++)
|
||||
{
|
||||
output[ii] = GetAttributeValueCollection(pos, deallocate);
|
||||
pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OpcRcw.Hda.OPCHDA_ATTRIBUTE)));
|
||||
}
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInput);
|
||||
pInput = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ATTRIBUTE structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaAttributeValueCollection GetAttributeValueCollection(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
TsCHdaAttributeValueCollection output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
var item = Marshal.PtrToStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ATTRIBUTE));
|
||||
|
||||
output = GetAttributeValueCollection((OpcRcw.Hda.OPCHDA_ATTRIBUTE)item, deallocate);
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.DestroyStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ATTRIBUTE));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ATTRIBUTE structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaAttributeValueCollection GetAttributeValueCollection(OpcRcw.Hda.OPCHDA_ATTRIBUTE input, bool deallocate)
|
||||
{
|
||||
var output = new TsCHdaAttributeValueCollection();
|
||||
|
||||
output.AttributeID = input.dwAttributeID;
|
||||
|
||||
var values = Com.Interop.GetVARIANTs(ref input.vAttributeValues, input.dwNumValues, deallocate);
|
||||
var timestamps = Utilities.Interop.GetDateTimes(ref input.ftTimeStamps, input.dwNumValues, deallocate);
|
||||
|
||||
for (var ii = 0; ii < input.dwNumValues; ii++)
|
||||
{
|
||||
var value = new TsCHdaAttributeValue();
|
||||
|
||||
value.Value = values[ii];
|
||||
value.Timestamp = timestamps[ii];
|
||||
|
||||
output.Add(value);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an array of OPCHDA_ANNOTATION structures.
|
||||
/// </summary>
|
||||
internal static TsCHdaAnnotationValueCollection[] GetAnnotationValueCollections(ref IntPtr pInput, int count, bool deallocate)
|
||||
{
|
||||
TsCHdaAnnotationValueCollection[] output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero && count > 0)
|
||||
{
|
||||
output = new TsCHdaAnnotationValueCollection[count];
|
||||
|
||||
var pos = pInput;
|
||||
|
||||
for (var ii = 0; ii < count; ii++)
|
||||
{
|
||||
output[ii] = GetAnnotationValueCollection(pos, deallocate);
|
||||
pos = (IntPtr)(pos.ToInt64() + Marshal.SizeOf(typeof(OpcRcw.Hda.OPCHDA_ANNOTATION)));
|
||||
}
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(pInput);
|
||||
pInput = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ANNOTATION structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaAnnotationValueCollection GetAnnotationValueCollection(IntPtr pInput, bool deallocate)
|
||||
{
|
||||
TsCHdaAnnotationValueCollection output = null;
|
||||
|
||||
if (pInput != IntPtr.Zero)
|
||||
{
|
||||
var item = Marshal.PtrToStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ANNOTATION));
|
||||
|
||||
output = GetAnnotationValueCollection((OpcRcw.Hda.OPCHDA_ANNOTATION)item, deallocate);
|
||||
|
||||
if (deallocate)
|
||||
{
|
||||
Marshal.DestroyStructure(pInput, typeof(OpcRcw.Hda.OPCHDA_ANNOTATION));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unmarshals and deallocates an OPCHDA_ANNOTATION structure.
|
||||
/// </summary>
|
||||
internal static TsCHdaAnnotationValueCollection GetAnnotationValueCollection(OpcRcw.Hda.OPCHDA_ANNOTATION input, bool deallocate)
|
||||
{
|
||||
var output = new TsCHdaAnnotationValueCollection();
|
||||
|
||||
output.ClientHandle = input.hClient;
|
||||
|
||||
var timestamps = Utilities.Interop.GetDateTimes(ref input.ftTimeStamps, input.dwNumValues, deallocate);
|
||||
var annotations = Utilities.Interop.GetUnicodeStrings(ref input.szAnnotation, input.dwNumValues, deallocate);
|
||||
var creationTimes = Utilities.Interop.GetDateTimes(ref input.ftAnnotationTime, input.dwNumValues, deallocate);
|
||||
var users = Utilities.Interop.GetUnicodeStrings(ref input.szUser, input.dwNumValues, deallocate);
|
||||
|
||||
for (var ii = 0; ii < input.dwNumValues; ii++)
|
||||
{
|
||||
var value = new TsCHdaAnnotationValue();
|
||||
|
||||
value.Timestamp = timestamps[ii];
|
||||
value.Annotation = annotations[ii];
|
||||
value.CreationTime = creationTimes[ii];
|
||||
value.User = users[ii];
|
||||
|
||||
output.Add(value);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
404
Technosoftware/DaAeHdaClient.Com/Hda/Request.cs
Normal file
404
Technosoftware/DaAeHdaClient.Com/Hda/Request.cs
Normal file
@@ -0,0 +1,404 @@
|
||||
#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
// Web: https://www.technosoftware.com
|
||||
//
|
||||
// The source code in this file is covered under a dual-license scenario:
|
||||
// - Owner of a purchased license: SCLA 1.0
|
||||
// - GPL V3: everybody else
|
||||
//
|
||||
// SCLA license terms accompanied with this source code.
|
||||
// See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf
|
||||
//
|
||||
// GNU General Public License as published by the Free Software Foundation;
|
||||
// version 3 of the License are accompanied with this source code.
|
||||
// See https://technosoftware.com/license/GPLv3License.txt
|
||||
//
|
||||
// This source code is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
|
||||
#region Using Directives
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
using Technosoftware.DaAeHdaClient.Hda;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Technosoftware.DaAeHdaClient.Com.Hda
|
||||
{
|
||||
/// <summary>
|
||||
/// An object that mainatains the state of asynchronous requests.
|
||||
/// </summary>
|
||||
internal class Request : IOpcRequest, ITsCHdaActualTime
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique id assigned to the request when it was created.
|
||||
/// </summary>
|
||||
public int RequestID => m_requestID;
|
||||
|
||||
/// <summary>
|
||||
/// The unqiue id assigned by the server when it was created.
|
||||
/// </summary>
|
||||
public int CancelID => m_cancelID;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the server acknowledges that a request was cancelled.
|
||||
/// </summary>
|
||||
public event TsCHdaCancelCompleteEventHandler CancelCompleteEvent
|
||||
{
|
||||
add { lock (this) { m_cancelCompleteEvent += value; } }
|
||||
remove { lock (this) { m_cancelCompleteEvent -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the object with all required information.
|
||||
/// </summary>
|
||||
public Request(object requestHandle, Delegate callback, int requestID)
|
||||
{
|
||||
m_requestHandle = requestHandle;
|
||||
m_callback = callback;
|
||||
m_requestID = requestID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the request with the initial results.
|
||||
/// </summary>
|
||||
public bool Update(int cancelID, OpcItem[] results)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// save the server assigned id.
|
||||
m_cancelID = cancelID;
|
||||
|
||||
// create a table of items indexed by the handle returned by the server in a callback.
|
||||
m_items = new Hashtable();
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
if (!typeof(IOpcResult).IsInstanceOfType(result) || ((IOpcResult)result).Result.Succeeded())
|
||||
{
|
||||
m_items[result.ServerHandle] = new OpcItem(result);
|
||||
}
|
||||
}
|
||||
|
||||
// nothing more to do - no good items.
|
||||
if (m_items.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// invoke callbacks for results that have already arrived.
|
||||
var complete = false;
|
||||
|
||||
if (m_results != null)
|
||||
{
|
||||
foreach (var result in m_results)
|
||||
{
|
||||
complete = InvokeCallback(result);
|
||||
}
|
||||
}
|
||||
|
||||
// all done.
|
||||
return complete;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the callback for the request.
|
||||
/// </summary>
|
||||
public bool InvokeCallback(object results)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
// save the results if the initial call to the server has not completed yet.
|
||||
if (m_items == null)
|
||||
{
|
||||
// create cache for results.
|
||||
if (m_results == null)
|
||||
{
|
||||
m_results = new ArrayList();
|
||||
}
|
||||
|
||||
m_results.Add(results);
|
||||
|
||||
// request not initialized completely
|
||||
return false;
|
||||
}
|
||||
|
||||
// invoke on data update callback.
|
||||
if (typeof(TsCHdaDataUpdateEventHandler).IsInstanceOfType(m_callback))
|
||||
{
|
||||
return InvokeCallback((TsCHdaDataUpdateEventHandler)m_callback, results);
|
||||
}
|
||||
|
||||
// invoke read completed callback.
|
||||
if (typeof(TsCHdaReadValuesCompleteEventHandler).IsInstanceOfType(m_callback))
|
||||
{
|
||||
return InvokeCallback((TsCHdaReadValuesCompleteEventHandler)m_callback, results);
|
||||
}
|
||||
|
||||
// invoke read attributes completed callback.
|
||||
if (typeof(TsCHdaReadAttributesCompleteEventHandler).IsInstanceOfType(m_callback))
|
||||
{
|
||||
return InvokeCallback((TsCHdaReadAttributesCompleteEventHandler)m_callback, results);
|
||||
}
|
||||
|
||||
// invoke read annotations completed callback.
|
||||
if (typeof(TsCHdaReadAnnotationsCompleteEventHandler).IsInstanceOfType(m_callback))
|
||||
{
|
||||
return InvokeCallback((TsCHdaReadAnnotationsCompleteEventHandler)m_callback, results);
|
||||
}
|
||||
|
||||
// invoke update completed callback.
|
||||
if (typeof(TsCHdaUpdateCompleteEventHandler).IsInstanceOfType(m_callback))
|
||||
{
|
||||
return InvokeCallback((TsCHdaUpdateCompleteEventHandler)m_callback, results);
|
||||
}
|
||||
|
||||
// callback not supported.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the server acknowledges that a request was cancelled.
|
||||
/// </summary>
|
||||
public void OnCancelComplete()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (m_cancelCompleteEvent != null)
|
||||
{
|
||||
m_cancelCompleteEvent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region IOpcRequest Members
|
||||
/// <summary>
|
||||
/// An unique identifier, assigned by the client, for the request.
|
||||
/// </summary>
|
||||
public object Handle => m_requestHandle;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IActualTime Members
|
||||
/// <summary>
|
||||
/// The actual start time used by a server while processing a request.
|
||||
/// </summary>
|
||||
public DateTime StartTime
|
||||
{
|
||||
get => m_startTime;
|
||||
set => m_startTime = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The actual end time used by a server while processing a request.
|
||||
/// </summary>
|
||||
public DateTime EndTime
|
||||
{
|
||||
get => m_endTime;
|
||||
set => m_endTime = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// Invokes callback for a data change update.
|
||||
/// </summary>
|
||||
private bool InvokeCallback(TsCHdaDataUpdateEventHandler callback, object results)
|
||||
{
|
||||
// check for valid result type.
|
||||
if (!typeof(TsCHdaItemValueCollection[]).IsInstanceOfType(results))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = (TsCHdaItemValueCollection[])results;
|
||||
|
||||
// update item handles and actual times.
|
||||
UpdateResults(values);
|
||||
|
||||
try
|
||||
{
|
||||
callback(this, values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions in the callbacks.
|
||||
}
|
||||
|
||||
// request never completes.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes callback for a read request.
|
||||
/// </summary>
|
||||
private bool InvokeCallback(TsCHdaReadValuesCompleteEventHandler callback, object results)
|
||||
{
|
||||
// check for valid result type.
|
||||
if (!typeof(TsCHdaItemValueCollection[]).IsInstanceOfType(results))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = (TsCHdaItemValueCollection[])results;
|
||||
|
||||
// update item handles and actual times.
|
||||
UpdateResults(values);
|
||||
|
||||
try
|
||||
{
|
||||
callback(this, values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions in the callbacks.
|
||||
}
|
||||
|
||||
// check if all data has been sent.
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value.Result == OpcResult.Hda.S_MOREDATA)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// request is complete.
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes callback for a read attributes request.
|
||||
/// </summary>
|
||||
private bool InvokeCallback(TsCHdaReadAttributesCompleteEventHandler callback, object results)
|
||||
{
|
||||
// check for valid result type.
|
||||
if (!typeof(TsCHdaItemAttributeCollection).IsInstanceOfType(results))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = (TsCHdaItemAttributeCollection)results;
|
||||
|
||||
// update item handles and actual times.
|
||||
UpdateResults(new TsCHdaItemAttributeCollection[] { values });
|
||||
|
||||
try
|
||||
{
|
||||
callback(this, values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions in the callbacks.
|
||||
}
|
||||
|
||||
// request always completes
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes callback for a read annotations request.
|
||||
/// </summary>
|
||||
private bool InvokeCallback(TsCHdaReadAnnotationsCompleteEventHandler callback, object results)
|
||||
{
|
||||
// check for valid result type.
|
||||
if (!typeof(TsCHdaAnnotationValueCollection[]).IsInstanceOfType(results))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = (TsCHdaAnnotationValueCollection[])results;
|
||||
|
||||
// update item handles and actual times.
|
||||
UpdateResults(values);
|
||||
|
||||
try
|
||||
{
|
||||
callback(this, values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions in the callbacks.
|
||||
}
|
||||
|
||||
// request always completes
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes callback for a read annotations request.
|
||||
/// </summary>
|
||||
private bool InvokeCallback(TsCHdaUpdateCompleteEventHandler callback, object results)
|
||||
{
|
||||
// check for valid result type.
|
||||
if (!typeof(TsCHdaResultCollection[]).IsInstanceOfType(results))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = (TsCHdaResultCollection[])results;
|
||||
|
||||
// update item handles and actual times.
|
||||
UpdateResults(values);
|
||||
|
||||
try
|
||||
{
|
||||
callback(this, values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions in the callbacks.
|
||||
}
|
||||
|
||||
// request always completes
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the result objects with locally cached information.
|
||||
/// </summary>
|
||||
private void UpdateResults(OpcItem[] results)
|
||||
{
|
||||
foreach (var result in results)
|
||||
{
|
||||
// update actual times.
|
||||
if (typeof(ITsCHdaActualTime).IsInstanceOfType(result))
|
||||
{
|
||||
((ITsCHdaActualTime)result).StartTime = StartTime;
|
||||
((ITsCHdaActualTime)result).EndTime = EndTime;
|
||||
}
|
||||
|
||||
// add item identifier to value collection.
|
||||
var itemID = (OpcItem)m_items[result.ServerHandle];
|
||||
|
||||
if (itemID != null)
|
||||
{
|
||||
result.ItemName = itemID.ItemName;
|
||||
result.ItemPath = itemID.ItemPath;
|
||||
result.ServerHandle = itemID.ServerHandle;
|
||||
result.ClientHandle = itemID.ClientHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
private object m_requestHandle = null;
|
||||
private Delegate m_callback = null;
|
||||
private int m_requestID = 0;
|
||||
private int m_cancelID = 0;
|
||||
private DateTime m_startTime = DateTime.MinValue;
|
||||
private DateTime m_endTime = DateTime.MinValue;
|
||||
private Hashtable m_items = null;
|
||||
private ArrayList m_results = null;
|
||||
private event TsCHdaCancelCompleteEventHandler m_cancelCompleteEvent = null;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
68
Technosoftware/DaAeHdaClient.Com/Hda/Result.cs
Normal file
68
Technosoftware/DaAeHdaClient.Com/Hda/Result.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
#region Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
// Web: https://www.technosoftware.com
|
||||
//
|
||||
// The source code in this file is covered under a dual-license scenario:
|
||||
// - Owner of a purchased license: SCLA 1.0
|
||||
// - GPL V3: everybody else
|
||||
//
|
||||
// SCLA license terms accompanied with this source code.
|
||||
// See SCLA 1.0: https://technosoftware.com/license/Source_Code_License_Agreement.pdf
|
||||
//
|
||||
// GNU General Public License as published by the Free Software Foundation;
|
||||
// version 3 of the License are accompanied with this source code.
|
||||
// See https://technosoftware.com/license/GPLv3License.txt
|
||||
//
|
||||
// This source code is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#endregion Copyright (c) 2011-2023 Technosoftware GmbH. All rights reserved
|
||||
|
||||
#region Using Directives
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Technosoftware.DaAeHdaClient.Com
|
||||
{
|
||||
namespace Hda
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines all well known COM HDA HRESULT codes.
|
||||
/// </summary>
|
||||
internal struct Result
|
||||
{
|
||||
/// <remarks/>
|
||||
public const int E_MAXEXCEEDED = -0X3FFBEFFF; // 0xC0041001
|
||||
/// <remarks/>
|
||||
public const int S_NODATA = +0x40041002; // 0x40041002
|
||||
/// <remarks/>
|
||||
public const int S_MOREDATA = +0x40041003; // 0x40041003
|
||||
/// <remarks/>
|
||||
public const int E_INVALIDAGGREGATE = -0X3FFBEFFC; // 0xC0041004
|
||||
/// <remarks/>
|
||||
public const int S_CURRENTVALUE = +0x40041005; // 0x40041005
|
||||
/// <remarks/>
|
||||
public const int S_EXTRADATA = +0x40041006; // 0x40041006
|
||||
/// <remarks/>
|
||||
public const int W_NOFILTER = -0x7FFBEFF9; // 0x80041007
|
||||
/// <remarks/>
|
||||
public const int E_UNKNOWNATTRID = -0x3FFBEFF8; // 0xC0041008
|
||||
/// <remarks/>
|
||||
public const int E_NOT_AVAIL = -0x3FFBEFF7; // 0xC0041009
|
||||
/// <remarks/>
|
||||
public const int E_INVALIDDATATYPE = -0x3FFBEFF6; // 0xC004100A
|
||||
/// <remarks/>
|
||||
public const int E_DATAEXISTS = -0x3FFBEFF5; // 0xC004100B
|
||||
/// <remarks/>
|
||||
public const int E_INVALIDATTRID = -0x3FFBEFF4; // 0xC004100C
|
||||
/// <remarks/>
|
||||
public const int E_NODATAEXISTS = -0x3FFBEFF3; // 0xC004100D
|
||||
/// <remarks/>
|
||||
public const int S_INSERTED = +0x4004100E; // 0x4004100E
|
||||
/// <remarks/>
|
||||
public const int S_REPLACED = +0x4004100F; // 0x4004100F
|
||||
}
|
||||
}
|
||||
}
|
||||
3473
Technosoftware/DaAeHdaClient.Com/Hda/Server.cs
Normal file
3473
Technosoftware/DaAeHdaClient.Com/Hda/Server.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user