/// <summary>
        /// Returns the structure handle for a particular tag
        /// </summary>
        /// <param name="tagName">Name of the tag</param>
        /// <returns>Structure handle or 0 if the tag wasn't found...</returns>
        internal ushort GetStructureHandle(string tagName)
        {
            bool refreshed = false;

            //lock (_lockObject)
            {
                //First we find the tag information..
                if (_tagInfo == null)
                {
                    RefreshInternalInfo();
                    refreshed = true;
                }

                LogixTagInfo ti = GetTagInfo(tagName);

                if (ti == null && !refreshed)
                {
                    RefreshInternalInfo();
                    ti = GetTagInfo(tagName);
                }

                if (ti == null)
                {
                    return(0);
                }
                else
                {
                    return((ushort)(ti.FullTypeInfo & 0x7FFF));
                }
            }
        }
        /// <summary>
        /// Get information about a tag
        /// </summary>
        /// <param name="Address">Address of the tag</param>
        /// <returns>LogixTagInfo object or null if the tag was not found</returns>
        public LogixTagInfo GetTagInformation(string Address)
        {
            List <LogixTagInfo> tagInfo = EnumerateTags();

            if (tagInfo != null && tagInfo.Count > 0)
            {
                LogixTagInfo retTag = tagInfo.Find(t => (string.Compare(t.TagName, Address, true) == 0));
                if (retTag == null)
                {
                    return(null);
                }
                if (retTag.TagName != Address)
                {
                    return(null);
                }
                return(retTag);
            }

            return(null);
        }
        /// <summary>
        /// Gets information for the specified tag
        /// </summary>
        /// <param name="tagName">Name of the tag</param>
        /// <returns>LogixTagInfo or null if not found</returns>
        internal LogixTagInfo GetInfoForTag(string tagName)
        {
            bool refreshed = false;

            //lock (_lockObject)
            {
                //First we find the tag information..
                if (_tagInfo == null)
                {
                    RefreshInternalInfo();
                    refreshed = true;
                }

                LogixTagInfo ti = GetTagInfo(tagName);

                if (ti == null && !refreshed)
                {
                    RefreshInternalInfo();
                    ti = GetTagInfo(tagName);
                }

                return(ti);
            }
        }
        private List <LogixTagInfo> DecodeTagInfo(byte[] data, out uint lastOffset)
        {
            List <LogixTagInfo> retVal = new List <LogixTagInfo>();

            lastOffset = 0;
            for (int i = 0; i < data.Length; i++)
            {
                LogixTagInfo info = new LogixTagInfo();
                lastOffset         = BitConverter.ToUInt32(data, i);
                i                 += 4;
                info.MemoryAddress = lastOffset;
                //Next two bytes are type code and dimension information
                ushort typeInfo = BitConverter.ToUInt16(data, i);
                i += 2;
                info.FullTypeInfo = typeInfo;
                //Need to decode the type info...
                info.DataType = (ushort)(typeInfo & 0x00FF);
                if ((ushort)(typeInfo & 0x8000) == 0x8000)
                {
                    info.DataType = (ushort)(info.DataType | 0x8000);
                }
                int dimInfo = (typeInfo & 0x6000) >> 13;
                info.Dimensions = (ushort)dimInfo;

                //Skip 2 bytes
                i += 2;
                if (i > data.Length)
                {
                    continue;
                }

                //Next 3 sets of 4 bytes are the dimension sizes
                info.Dimension1Size = BitConverter.ToUInt32(data, i);
                i += 4;
                if (i > data.Length)
                {
                    continue;
                }
                info.Dimension2Size = BitConverter.ToUInt32(data, i);
                i += 4;
                if (i > data.Length)
                {
                    continue;
                }
                info.Dimension3Size = BitConverter.ToUInt32(data, i);
                i += 4;
                if (i > data.Length)
                {
                    continue;
                }

                //Next 2 bytes are the length of the name...
                int strSize = BitConverter.ToUInt16(data, i);
                i += 2;
                if (i > data.Length)
                {
                    continue;
                }
                if (i + strSize > data.Length)
                {
                    continue;
                }
                info.TagName = System.Text.ASCIIEncoding.ASCII.GetString(data, i, strSize);
                i           += strSize - 1;
                retVal.Add(info);
            }

            return(retVal);
        }