/// <summary>
        /// Returns a list of items that are not consistent between the configuration
        /// of the program and the device.
        /// </summary>
        /// <param name="strProgramName">The name of the program to validate against.</param>
        /// <returns>
        /// A list of items that failed the validation. Returns an empty list if
        /// all items match.
        /// </returns>
        //  Revision History
        //  MM/DD/YY Who Version Issue# Description
        //  -------- --- ------- ------ -------------------------------------------
        //  07/08/10 AF  2.42.03        Created
        //
        public override List <ProgramValidationItem> ValidateProgram(string strProgramName)
        {
            PSEMResponse Response = PSEMResponse.Ok;

            List <ProgramValidationItem> InvalidItemsList = new List <ProgramValidationItem>();
            List <EDLValidationItem>     ItemsToValidate  = GetValidationList();
            List <ushort> ValidationTablesToRead          = GetValidationTablesToRead();

            FileStream    EDLFileStream = new FileStream(strProgramName, FileMode.Open, FileAccess.Read, FileShare.Read);
            XmlTextReader EDLReader     = new XmlTextReader(EDLFileStream);

            GatewayTables ProgramTables = new GatewayTables();
            GatewayTables MeterTables   = new GatewayTables();

            OnShowProgress(new ShowProgressEventArgs(1, ValidationTablesToRead.Count));

            // Read the data from the meter.
            // NOTE: ReadTable is defined in M2_Gateway_ICreateEDL so this will not compile if
            //       that file is not included. We may want to move this method eventually, but
            //       we are keeping Interfaces separate in case we wish to support OpenWay in HH-Pro
            foreach (ushort TableID in ValidationTablesToRead)
            {
                OnStepProgress(new ProgressEventArgs());

                if (Response == PSEMResponse.Ok)
                {
                    if (MeterTables.IsTableKnown(TableID) && Table00.IsTableUsed(TableID) && (TableID == 0 || MeterTables.GetTableLength(TableID) > 0))
                    {
                        Response = ReadTable(TableID, ref MeterTables);
                    }
                }
            }

            if (Response != PSEMResponse.Ok)
            {
                throw new PSEMException(PSEMException.PSEMCommands.PSEM_READ, Response, "Error reading device for validation.");
            }
            else
            {
                // Load the EDL file.
                ProgramTables.LoadEDLFile(EDLReader);

                // Compare the values
                foreach (EDLValidationItem Item in ItemsToValidate)
                {
                    ProgramValidationItem InvalidItem;

                    // Only compare items where the meter's FW version is greater than or equal to
                    // the minimum required for that item and the FW version is less than
                    // the version in which it became obsolete.  Max set to high for active items.
                    if ((VersionChecker.CompareTo(FWRevision, Item.MinFWVersion) >= 0) &&
                        (VersionChecker.CompareTo(FWRevision, Item.MaxFWVersion) < 0))
                    {
                        // We need to handle the display items differently than the rest of the items since
                        // there can be a different number of Normal and Test items.
                        if (RequiresSpecialHandling(Item.Item) == false)
                        {
                            InvalidItem = ValidateItem(Item, MeterTables, ProgramTables);

                            // Only add the item if it does not match.
                            if (null != InvalidItem)
                            {
                                InvalidItemsList.Add(InvalidItem);
                            }
                        }
                        else
                        {
                            InvalidItemsList.AddRange(HandleSpecialCases(Item.Item, MeterTables, ProgramTables));
                        }
                    }
                }
            }

            return(InvalidItemsList);
        }