/// <summary>
        /// copy constructor.
        /// </summary>
        public NlmpChallengePacket(
            NlmpChallengePacket stackPacket
            )
            : base(stackPacket)
        {
            this.payload = stackPacket.payload;

            if (stackPacket.payload.TargetName != null)
            {
                this.payload.TargetName =
                    new byte[stackPacket.payload.TargetName.Length];
                Array.Copy(
                    stackPacket.payload.TargetName,
                    this.payload.TargetName,
                    stackPacket.payload.TargetName.Length);
            }

            if (stackPacket.payload.TargetInfo != null)
            {
                this.payload.TargetInfo =
                    new byte[stackPacket.payload.TargetInfo.Length];
                Array.Copy(
                    stackPacket.payload.TargetInfo,
                    this.payload.TargetInfo,
                    stackPacket.payload.TargetInfo.Length);
            }
        }
        /// <summary>
        /// copy constructor.
        /// </summary>
        public NlmpChallengePacket(
            NlmpChallengePacket stackPacket
            )
            : base(stackPacket)
        {
            this.payload = stackPacket.payload;

            if (stackPacket.payload.TargetName != null)
            {
                this.payload.TargetName =
                    new byte[stackPacket.payload.TargetName.Length];
                Array.Copy(
                    stackPacket.payload.TargetName,
                    this.payload.TargetName,
                    stackPacket.payload.TargetName.Length);
            }

            if (stackPacket.payload.TargetInfo != null)
            {
                this.payload.TargetInfo =
                    new byte[stackPacket.payload.TargetInfo.Length];
                Array.Copy(
                    stackPacket.payload.TargetInfo,
                    this.payload.TargetInfo,
                    stackPacket.payload.TargetInfo.Length);
            }
        }
        /// <summary>
        /// read struct from bytes. All sub class override this to unmarshal itself.
        /// </summary>
        /// <param name="start">the start to read bytes</param>
        /// <param name="packetBytes">the bytes of struct</param>
        /// <returns>the read result, if success, return true.</returns>
        protected override bool ReadStructFromBytes(
            byte[] packetBytes,
            int start
            )
        {
            CHALLENGE_MESSAGE challenge = new CHALLENGE_MESSAGE();

            challenge.TargetNameFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>(packetBytes, ref start);
            challenge.NegotiateFlags   = (NegotiateTypes)NlmpUtility.BytesToStruct <uint>(packetBytes, ref start);
            challenge.ServerChallenge  = NlmpUtility.BytesToStruct <ulong>(packetBytes, ref start);
            challenge.Reserved         = NlmpUtility.BytesToStruct <ulong>(packetBytes, ref start);
            challenge.TargetInfoFields = NlmpUtility.BytesToStruct <MESSAGE_FIELDS>(packetBytes, ref start);

            // Unmarshal the Version field.
            // The Version field is NOT sent or accessed by Windows NT or Windows 2000. Windows NT and Windows 2000
            // assume that the Payload field started immediately after WorkstationNameBufferOffset.
            if (challenge.TargetInfoFields.BufferOffset != start &&
                challenge.TargetNameFields.BufferOffset != start)
            {
                challenge.Version = NlmpUtility.BytesToStruct <VERSION>(packetBytes, ref start);
            }

            int currentIndex = 0;

            while (currentIndex != start)
            {
                currentIndex = start;
                if (challenge.TargetNameFields.Len != 0 && challenge.TargetNameFields.BufferOffset == start)
                {
                    challenge.TargetName = NlmpUtility.ReadBytes(
                        packetBytes, ref start, challenge.TargetNameFields.Len);
                    continue;
                }
                else if (challenge.TargetInfoFields.Len != 0 && challenge.TargetInfoFields.BufferOffset == start)
                {
                    challenge.TargetInfo = NlmpUtility.ReadBytes(
                        packetBytes, ref start, challenge.TargetInfoFields.Len);
                    continue;
                }
                else
                {
                    break;
                }
            }

            this.payload = challenge;

            return(true);
        }
        /// <summary>
        /// read struct from bytes. All sub class override this to unmarshal itself.
        /// </summary>
        /// <param name="start">the start to read bytes</param>
        /// <param name="packetBytes">the bytes of struct</param>
        /// <returns>the read result, if success, return true.</returns>
        protected override bool ReadStructFromBytes(
            byte[] packetBytes, 
            int start
            )
        {
            CHALLENGE_MESSAGE challenge = new CHALLENGE_MESSAGE();

            challenge.TargetNameFields = NlmpUtility.BytesToStruct<MESSAGE_FIELDS>(packetBytes, ref start);
            challenge.NegotiateFlags = (NegotiateTypes)NlmpUtility.BytesToStruct<uint>(packetBytes, ref start);
            challenge.ServerChallenge = NlmpUtility.BytesToStruct<ulong>(packetBytes, ref start);
            challenge.Reserved = NlmpUtility.BytesToStruct<ulong>(packetBytes, ref start);
            challenge.TargetInfoFields = NlmpUtility.BytesToStruct<MESSAGE_FIELDS>(packetBytes, ref start);

            // Unmarshal the Version field.
            // The Version field is NOT sent or accessed by Windows NT or Windows 2000. Windows NT and Windows 2000
            // assume that the Payload field started immediately after WorkstationNameBufferOffset.
            if (challenge.TargetInfoFields.BufferOffset != start
                && challenge.TargetNameFields.BufferOffset != start)
            {
                challenge.Version = NlmpUtility.BytesToStruct<VERSION>(packetBytes, ref start);
            }

            int currentIndex = 0;
            while (currentIndex != start)
            {
                currentIndex = start;
                if (challenge.TargetNameFields.Len !=0 && challenge.TargetNameFields.BufferOffset == start)
                {
                    challenge.TargetName = NlmpUtility.ReadBytes(
                        packetBytes, ref start, challenge.TargetNameFields.Len);
                    continue;
                }
                else if (challenge.TargetInfoFields.Len != 0 && challenge.TargetInfoFields.BufferOffset == start)
                {
                    challenge.TargetInfo = NlmpUtility.ReadBytes(
                        packetBytes, ref start, challenge.TargetInfoFields.Len);
                    continue;
                }
                else
                {
                    break;
                }
            }

            this.payload = challenge;

            return true;
        }