public DWORD AddTag(Tag.TAGENTRY tTagEntry, DWORD relativeOffset, out Tag _refTag)
        {
            DWORD readOffset = 0;
            DWORD writeOffset = 0;
            DWORD nextAvailableDataOffset = 0; //offset for next data block
            DWORD nextAvailableTagOffset = 0; //offset for next tag

            Tag refTag; //= NULL;

            Device refDevice = this;
            //Create new Tag
            refTag = new Tag(ref refDevice, tTagEntry, relativeOffset, GetSharedMemoryOffset());

            _refTag = refTag;

            if (refTag.Equals(null))
            {
                Trace.Assert(false);
                return (relativeOffset); //re-use this offset for the next tag
            }

            //Determine register's read offset
            if (refTag.IsReadable())
            {
                readOffset = Register.DATA_MIN_OFFSET;
                nextAvailableDataOffset = readOffset + Register.DATA_SIZE_MIN + refTag.GetReadValueExtSize();

                //Determine register's write offset
                if (refTag.IsWriteable())
                {
                    //read/write
                    writeOffset = nextAvailableDataOffset;
                    nextAvailableDataOffset = writeOffset + Register.DATA_SIZE_MIN + refTag.GetWriteValueExtSize();
                }
                else
                {
                    //read-only
                    writeOffset = 0;
                }

            }
            else
            {
                readOffset = 0;

                //Determine register's write offset
                if (refTag.IsWriteable())
                {
                    //write-only
                    writeOffset = Register.DATA_MIN_OFFSET;
                    nextAvailableDataOffset = writeOffset + Register.DATA_SIZE_MIN + refTag.GetWriteValueExtSize();
                }
                else
                {
                    //neither read or write
                    Debug.Assert(false);
                    writeOffset = 0;
                }
            }

            //Prepare the register offset for the next tag (if applicable)
            nextAvailableTagOffset = relativeOffset + nextAvailableDataOffset;

            string msg = "";

            //Check for Shared Memory file overrun
            if ((GetSharedMemoryOffset() + nextAvailableTagOffset) > SharedMemServer.MAPSIZE)
            {
                //Reached the limits of our Shared Memory file
                //Don't add tag

                msg = string.Format("Tag {0,0:T} could not be added.", refTag.GetName()) +
                    string.Format("Register {0,0:D} with size ", refTag.GetSharedMemoryOffset()) +
                    string.Format("{0,0:D} bytes would exceed Shared Memory file size of ", (DWORD)(writeOffset + Register.DATA_SIZE_MIN + refTag.GetExtendedSize())) +
                    string.Format("{0,0:D}", SharedMemServer.MAPSIZE);
                logger.Trace(msg);

                return (relativeOffset);
            }

            int nRC = TagData.SMRC_NO_ERROR;

            //Initialize register if we have access to shared memory
            if (CID.memStream != null)
            {
                Register.SetReadOffset(CID.memStream, (long)refTag.GetSharedMemoryOffset(), readOffset);

                Register.SetWriteOffset(CID.memStream, (long)refTag.GetSharedMemoryOffset(), writeOffset);

                Register.SetReadValueType(CID.memStream, (long)refTag.GetSharedMemoryOffset(), refTag.GetReadValueType());

                if (writeOffset != 0)
                {
                    Register.SetWriteValueType(CID.memStream, (long)refTag.GetSharedMemoryOffset(), refTag.GetWriteValueType());
                }
                Register.SetReadValueExtSize(CID.memStream, (long)refTag.GetSharedMemoryOffset(), refTag.GetReadValueExtSize());

                if (writeOffset != 0)
                {
                    Register.SetWriteValueExtSize(CID.memStream, (long)refTag.GetSharedMemoryOffset(), refTag.GetWriteValueExtSize());

                }

                if (refTag.GetDataType() == (ushort)(Value.T_ARRAY | Value.T_STRING))
                {
                    nRC = Register.SetReadValueArrayStringSize(CID.memStream, (long)refTag.GetSharedMemoryOffset(), refTag.GetReadValueArrayStringSize());

                    if (writeOffset != 0)
                    {
                        nRC = Register.SetWriteValueArrayStringSize(CID.memStream, (long)refTag.GetSharedMemoryOffset(), (WORD)refTag.GetWriteValueArrayStringSize());
                    }
                }

            } //if (pSharedMemoryBaseMem != null)

            //Add tag to our tag set
            tagSet.Add(refTag);
            msg = string.Format("Tag {0,0:T}: assigned to Register " +
                "{1,0:D} with size " +
                "{2,0:D} bytes.  Relative offset = " +
                "{3,0:D}", refTag.GetName(), refTag.GetSharedMemoryOffset(),
                    nextAvailableDataOffset,
                    refTag.GetRelativeOffset());
            logger.Trace(msg);

            return (nextAvailableTagOffset);
        }
 public TAGENTRY(Tag.TAGENTRY te)
 {
     strName = te.strName;
     stringSize = te.stringSize;
     arrayRows = te.arrayRows;
     arrayCols = te.arrayCols;
     dataType = te.dataType;
     Access = te.Access;
     description = te.description;
     groupName = te.groupName;
 }