public void MSOXNSPI_S02_TC21_GetMatchesComparedWithNspiQueryRows()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;

            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches method to restrict a specific table based on the input parameters and return the resultant Explicit Table.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;
            PropertyName_r? propNameOfGetMatches = null;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction1 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName + "\0");
            }

            propertyRestriction1.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction1.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r propertyRestriction2 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            string administratorName = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(administratorName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(administratorName + "\0");
            }

            propertyRestriction2.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction2.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r restrictionOr = new Restriction_r
            {
                Rt = 0x01,
                Res =
                    new RestrictionUnion_r
                    {
                        ResOr = new OrRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                propertyRestriction1, propertyRestriction2
                            }
                        }
                    }
            };

            Restriction_r? filter = restrictionOr;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 4,
                AulPropTag = new uint[4]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    (uint)AulProp.PidTagAddressBookDisplayNamePrintable,
                    (uint)AulProp.PidTagDisplayType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success");
            #endregion

            #region Call NspiQueryRows method to compare with NspiGetMatches result.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount = outMIds.Value.CValues;
            uint[] table = new uint[outMIds.Value.CValues];
            Array.Copy(outMIds.Value.AulPropTag, table, outMIds.Value.CValues);

            uint count = outMIds.Value.CValues;
            PropertyRowSet_r? rowsOfQueryRows;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return Success!");

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1696");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1696
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rowsOfGetMatches, rowsOfQueryRows),
                1696,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [constraint 18] This PropertyRowSet_r MUST be exactly the same PropertyRowSet_r that would be returned in the ppRows parameter of a call to the NspiQueryRows method with the following parameters:
                The NspiGetMatches parameter hRpc is used as the NspiQueryRows parameter hRpc. 
                The value ""fEphID"" is used as the NspiQueryRows parameter dwFlags.
                The NspiGetMatches output parameter pStat (as modified by the prior constraints) is used as the NspiQueryRows parameter pStat.
                The number of Minimal Entry IDs in the constructed Explicit Table is used as the NspiQueryRows parameter dwETableCount.
                The constructed Explicit Table is used as the NspiQueryRows parameter lpETable. These Minimal Entry IDs are expressed as a simple array of DWORD values rather than as a PropertyTagArray_r value.
                The number of Minimal Entry IDs in the constructed Explicit Table is used as the NspiQueryRows parameter Count.
                The NspiGetMatches parameter proptags is used as the NspiQueryRows parameter proptags.");

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1165: the SortType of output stat is {0}, the ContainerID of output stat is {1}, the CurrentRec of output stat is {2}, the Delta of output stat is {3}, the NumPos of output stat is {4}, the TotalRecs of output stat is {5}, the CodePage of output stat is {6}, the TemplateLocale of output stat is {7}, the SortLocale of output stat is {8};" +
                "the SortType of inputStat is {9}, the ContainerID of inputStat is {10}, the CurrentRec of inputStat is {11}, the Delta of inputStat is {12}, the NumPos of inputStat is {13}, the TotalRecs of inputStat is {13}, the CodePage of inputStat is {14}, the TemplateLocale of inputStat is {15}, the SortLocale of inputStat is {16}",
                stat.SortType,
                stat.ContainerID,
                stat.CurrentRec,
                stat.Delta,
                stat.NumPos,
                stat.TotalRecs,
                stat.CodePage,
                stat.TemplateLocale,
                stat.SortLocale,
                inputStat.SortType,
                inputStat.ContainerID,
                inputStat.CurrentRec,
                inputStat.Delta,
                inputStat.NumPos,
                inputStat.TotalRecs,
                inputStat.CodePage,
                inputStat.TemplateLocale,
                inputStat.SortLocale);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1165
            bool isVerifyR1165 = (stat.SortType == inputStat.SortType)
                                && (stat.ContainerID == inputStat.ContainerID)
                                && (stat.CurrentRec == inputStat.CurrentRec)
                                && (stat.Delta == inputStat.Delta)
                                && (stat.NumPos == inputStat.NumPos)
                                && (stat.TotalRecs == inputStat.TotalRecs)
                                && (stat.CodePage == inputStat.CodePage)
                                && (stat.TemplateLocale == inputStat.TemplateLocale)
                                && (stat.SortLocale == inputStat.SortLocale);

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1165,
                1165,
                @"[In NspiGetMatches] Note that the server MUST NOT modify the return value of 
                the NspiGetMatches method output parameter pStat in any way in the process of constructing the output PropertyRowSet_r.");

            #endregion Capture
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S02_TC23_ResortRestrictionSuccessCheckRowNumber()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches method to get a list of valid MIDs (Minimal Entry ID).
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags1;

            // Set value for propNameOfGetMatches.
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiResortRestriction method to resort MIDs got from NspiGetMatches method.
            uint reservedOfResortRestriction = 0;
            PropertyTagArray_r inmids = outMIds.Value;

            PropertyTagArray_r? outMIdOfResort = null;
            this.Result = this.ProtocolAdatper.NspiResortRestriction(reservedOfResortRestriction, ref stat, inmids, ref outMIdOfResort);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiResortRestriction should return Success!");
            #endregion

            #region Call NspiQueryRows method using MIDs of NspiResortRestriction as the input parameter lpETable to check whether the specified row is inserted.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount = outMIds.Value.CValues;
            uint[] table = new uint[outMIds.Value.CValues];
            Array.Copy(outMIds.Value.AulPropTag, table, outMIds.Value.CValues);
            uint count = tableCount + 1;
            PropertyRowSet_r? rowsOfQueryRows;

            PropertyTagArray_r propTagsInstance = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagEntryId
                }
            };
            PropertyTagArray_r? propTags = propTagsInstance;

            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return Success!");

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1198");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1198
            // If the number of the queried row equals the number of minimal entry id in outMids, 
            // it means the when each object located, a row is inserted into the constructed Explicit Table.
            Site.CaptureRequirementIfAreEqual<uint>(
                outMIdOfResort.Value.CValues,
                rowsOfQueryRows.Value.CRows,
                1198,
                @"[In NspiResortRestriction] [Server Processing Rules: Upon receiving message NspiResortRestriction, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] For each such object located, a row is inserted into the constructed Explicit Table.");

            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S02_TC19_GetMatchesWithDifferentSortOrder()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;

            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches method with SortType field of STAT block set to SortTypeDisplayName_RO.
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName_RO;
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;
            PropertyName_r? propNameOfGetMatches = null;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                AulPropTag = new uint[]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    (uint)AulProp.PidTagAddressBookDisplayNamePrintable,
                    (uint)AulProp.PidTagDisplayType
                }
            };
            propTags.CValues = (uint)propTags.AulPropTag.Length;
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success");

            #region Capture code

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R99");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R99
            // The field LpszW indicates a single Unicode string value.
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.Success,
                this.Result,
                99,
                "[In Table Sort Orders] [SortTypeDisplayName_RO] The client MUST set this value only when using the NspiGetMatches method, as specified in section 3.1.4.1.10, to open a nonwritable table on an object-valued property.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R98");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R98
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.IsSortByName(rowsOfGetMatches, 1),
                98,
                @"[In Table Sort Orders] SortTypeDisplayName_RO (0x000003E8): The table is sorted ascending on the PidTagDisplayName property.");
            #endregion
            #endregion

            #region Call NspiGetMatches method with SortType field of STAT block set to SortTypeDisplayName_W.
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName_W;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);

            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R100");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R100
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.IsSortByName(rowsOfGetMatches, 1),
                100,
                @"[In Table Sort Orders] SortTypeDisplayName_W (0x000003E9): The table is sorted ascending on the PidTagDisplayName property.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R101");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R101
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.Success,
                this.Result,
                101,
                "[In Table Sort Orders] [SortTypeDisplayName_W] The client MUST set this value only when using the NspiGetMatches method to open a writable table on an object-valued property.");
            #endregion
            #endregion

            #region Call NspiGetMatches method with specified filter and prop tags.
            res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagAddressBookPhoneticDisplayName
                            }
                    }
            };
            filter = res_r;

            PropertyTagArray_r prop = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    (uint)AulProp.PidTagAddressBookPhoneticDisplayName
                }
            };

            propTagsOfGetMatches = prop;
            propNameOfGetMatches = null;

            stat.SortType = (uint)TableSortOrder.SortTypePhoneticDisplayName;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success.");

            #region Capture

            // Whether the row is sorted by display name.
            bool isSortyByPhoneticDisplayName = false;

            // Store name of each row.
            string[] phoneticDisplayName = new string[rowsOfGetMatches.Value.CRows];
            Site.Log.Add(LogEntryKind.Debug, "The rows sorted by phonetic display name are:");
            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                phoneticDisplayName[i] = System.Text.Encoding.UTF8.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);
                Site.Log.Add(LogEntryKind.Debug, "Row {0}: {1}", i, phoneticDisplayName[i]);
            }

            for (int i = 0; i < phoneticDisplayName.Length - 1; i++)
            {
                if (string.Compare(phoneticDisplayName[i], phoneticDisplayName[i + 1], StringComparison.Ordinal) < 0)
                {
                    isSortyByPhoneticDisplayName = true;
                }
                else
                {
                    isSortyByPhoneticDisplayName = false;
                    break;
                }
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R95");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R95
            Site.CaptureRequirementIfIsTrue(
                isSortyByPhoneticDisplayName,
                95,
                @"[In Table Sort Orders] SortTypePhoneticDisplayName (0x00000003): The table is sorted ascending on the PidTagAddressBookPhoneticDisplayName property, as specified in [MS-OXOABK] section 2.2.3.9.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R495");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R495
            this.Site.CaptureRequirementIfIsTrue(
                isSortyByPhoneticDisplayName,
                495,
                @"[In String Sorting] If the server supports the SortTypePhoneticDisplayName sort order, it [server] MUST also support sorting on Unicode string representation for the PidTagAddressBookPhoneticDisplayName property.");
            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S02_TC20_GetMatchesSuccess()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;

            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiQueryRows with fEphID dwFlags to get an EphemeralEntryID.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount = 0;
            uint[] table = null;
            uint count = 10;
            PropertyRowSet_r? rowsOfQueryRows1;

            PropertyTagArray_r propTagsInstance = new PropertyTagArray_r
            {
                CValues = 2,
                AulPropTag = new uint[2]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                }
            };
            PropertyTagArray_r? propTags1 = propTagsInstance;

            stat.CodePage = (uint)RequiredCodePage.CP_TELETEX;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags1, out rowsOfQueryRows1);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return Success!");
            Site.Assert.IsNotNull(rowsOfQueryRows1.Value.ARow, "The returned rows should not be empty. The row number is {0}.", rowsOfQueryRows1 == null ? 0 : rowsOfQueryRows1.Value.CRows);
            #endregion

            #region Call NspiUpdateStat to update STAT block.
            uint reserved = 0;
            int? delta = 1;
            this.Result = this.ProtocolAdatper.NspiUpdateStat(reserved, ref stat, ref delta);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiUpdateStat should return Success!");
            #endregion

            #region Call NspiGetMatches method with the specified filter and proptags.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r entryIdExist = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = entryIdExist;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1155");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1155
            // The parameter rowsOfGetMatches which contains a PropertyRowSet_r structure is returned from the server, if this value is not null, 
            // it illustrates  that the server must have constructed the structure.
            Site.CaptureRequirementIfIsNotNull(
                rowsOfGetMatches,
                1155,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 18] Subject to the prior constraints, the server MUST construct a PropertyRowSet_r to return to the client in the output parameter ppRows.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1167");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1167
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.Success,
                this.Result,
                1167,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 10] If no other return values have been specified by these constraints [constraints 1-9], the server MUST return the return value ""Success"".");

            // Add the debug information
            this.Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1090, the maximum number of rows to return in a restricted address book container is {0}, the actual number is {1}",
                requested,
                rowsOfGetMatches.Value.CRows);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1090
            this.Site.CaptureRequirementIfIsTrue(
                rowsOfGetMatches.Value.CRows <= requested,
                1090,
                @"[In NspiGetMatches] [ulRequested] Contains the maximum number of rows to return in a restricted address book container.");

            int index = 0;
            foreach (PropertyRow_r arow in rowsOfGetMatches.Value.ARow)
            {
                EphemeralEntryID temp = AdapterHelper.ParseEphemeralEntryIDFromBytes(arow.LpProps[0].Value.Bin.Lpb);
                Site.Assert.AreEqual<uint>(outMIds.Value.AulPropTag[index], temp.Mid, "The Minimal Entry ID hold by ppOutMIds should be same with the MID in the EphemeralEntryID.");
                index++;
            }

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1092
            // All the Minimal Entry IDs contained in ppOutMIds had been checked, MS-OXNSPI_R1092 can be verified directly.
            this.Site.CaptureRequirement(
                1092,
                @"[In NspiGetMatches] [ppOutMIds] On return, it holds a list of Minimal Entry IDs that comprise a restricted address book container.");

            PropertyRow_r rowValue = rowsOfGetMatches.Value.ARow[0];

            // Add the debug information
            this.Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1094, the first property tag value of row value is {0}, the second is {1}, the third is {2}",
                rowValue.LpProps[0].PropTag,
                rowValue.LpProps[1].PropTag,
                rowValue.LpProps[2].PropTag);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1094
            bool isVerifiedR1094 = rowValue.LpProps[0].PropTag.Equals((uint)AulProp.PidTagEntryId) &&
                                   rowValue.LpProps[1].PropTag.Equals((uint)AulProp.PidTagDisplayType) &&
                                   rowValue.LpProps[2].PropTag.Equals((uint)AulProp.PidTagObjectType);

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR1094,
                1094,
                @"[In NspiGetMatches] [pPropTags] Contains list of the proptags of the columns that client wants to be returned for each row returned.");

            // pStat is defined to the type of STAT in this test suite, and the CurrentRec describes the logical position. 
            // So this requirement can be captured if code can reach here.
            this.Site.CaptureRequirement(
                1081,
                @"[In NspiGetMatches] pStat: A reference to a STAT block describing a logical position in a specific address book container.");

            #endregion
            #endregion

            #region Call NspiGetMatches method with another Reserved2 value.
            uint reserved2WithAnotherValue = 1;

            // Output parameters.
            PropertyTagArray_r? outMIdsWithAnotherReserved2Value;
            PropertyRowSet_r? rowsOfGetMatchesWithAnotherReserved2Value;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserved2WithAnotherValue, filter, propNameOfGetMatches, requested, out outMIdsWithAnotherReserved2Value, propTagsOfGetMatches, out rowsOfGetMatchesWithAnotherReserved2Value);

            #region Capture

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1899
            bool isMidEqual = true;
            if (outMIds.Value.CValues == outMIdsWithAnotherReserved2Value.Value.CValues)
            {
                for (int i = 0; i < outMIds.Value.CValues; i++)
                {
                    if (outMIds.Value.AulPropTag[i] != outMIdsWithAnotherReserved2Value.Value.AulPropTag[i])
                    {
                        isMidEqual = false;
                        break;
                    }
                }
            }
            else
            {
                isMidEqual = false;
            }

            bool isRowsOfGetMatchesEqual = true;
            if (rowsOfGetMatches.Value.CRows == rowsOfGetMatchesWithAnotherReserved2Value.Value.CRows)
            {
                for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
                {
                    if (rowsOfGetMatches.Value.ARow[i].CValues == rowsOfGetMatchesWithAnotherReserved2Value.Value.ARow[i].CValues)
                    {
                        for (int j = 0; j < rowsOfGetMatches.Value.ARow[1].CValues; j++)
                        {
                            if (rowsOfGetMatches.Value.ARow[i].LpProps[j].PropTag != rowsOfGetMatchesWithAnotherReserved2Value.Value.ARow[i].LpProps[j].PropTag)
                            {
                                isRowsOfGetMatchesEqual = false;
                                break;
                            }
                        }
                    }
                    else
                    {
                        isRowsOfGetMatchesEqual = false;
                        break;
                    }
                }
            }
            else
            {
                isRowsOfGetMatchesEqual = false;
            }

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1899.");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1899
            this.Site.CaptureRequirementIfIsTrue(
                isMidEqual && isRowsOfGetMatchesEqual,
                1899,
                @"[In NspiGetMatches] If this field [Reserved2] is set to different values, the server will return the same result.");

            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S04_TC02_ModLinkAttSuccessWithPidTagAddressBookMember()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();
            bool isR2003009Enabled = Common.IsRequirementEnabled(2003009, this.Site);

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");

            #endregion

            #region Call NspiGetMatches method to get the valid Minimal Entry IDs and rows.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction1 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string memberName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(memberName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(memberName + "\0");
            }

            propertyRestriction1.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction1.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r propertyRestriction2 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            string dlistName = Common.GetConfigurationPropertyValue("DistributionListName", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(dlistName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(dlistName + "\0");
            }

            propertyRestriction2.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction2.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r restrictionOr = new Restriction_r
            {
                Rt = 0x01,
                Res =
                    new RestrictionUnion_r
                    {
                        ResOr = new OrRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                propertyRestriction1, propertyRestriction2
                            }
                        }
                    }
            };

            Restriction_r? filter = restrictionOr;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    unchecked((uint)AulProp.PidTagAddressBookMember),
                }
            };

            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiModLinkAtt method with the specified PidTagAddressBookMember value.
            uint flagsOfModLinkAtt = 0; // A value which does not contain fDelete flag (0x1).
            uint propTagOfModLinkAtt = (uint)AulProp.PidTagAddressBookMember;
            uint midOfModLinkAtt = 0;
            BinaryArray_r entryId = new BinaryArray_r
            {
                CValues = 1,
                Lpbin = new Binary_r[1]
            };

            int i;
            string name = string.Empty;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(dlistName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // The current Address Book object is a distribution list.
                    // Save the distribution list location.
                    midOfModLinkAtt = outMIds.Value.AulPropTag[i];
                    this.MidToBeModified = midOfModLinkAtt;
                }
                else if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(memberName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // Save the EntryID of this user which will be added as a member of the distribution list.
                    entryId.Lpbin[0] = rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.Bin;
                    this.EntryIdToBeDeleted = entryId;
                }

                if (this.MidToBeModified != 0 && this.EntryIdToBeDeleted.Lpbin[0].Cb != 0)
                {
                    break;
                }
            }

            Site.Assert.AreEqual<uint>(0x87, entryId.Lpbin[0].Lpb[0], "Ephemeral Entry ID's ID Type should be 0x87.");
            this.IsEphemeralEntryID = true;

            // Add the property value.
            ErrorCodeValue result1;
            if (!isR2003009Enabled)
            {
                result1 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1340");

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R1340
                Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                    ErrorCodeValue.Success,
                    result1,
                    1340,
                    @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 9] If no other return values have been specified by these constraints [constraints 1-8], the server MUST return the return value ""Success"" (0x00000000).");
            }
            else
            {
                result1 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R2003009");

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R2003009
                Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                    ErrorCodeValue.GeneralFailure,
                    result1,
                    2003009,
                    @"[In Appendix A: Product Behavior] Implementation does return ""GeneralFailure"" when modify either the PidTagAddressBookMember property or the PidTagAddressBookPublicDelegates property of any objects in the address book. <6> Section 3.1.4.1.15:  Exchange 2013 and Exchange 2016 return ""GeneralFailure"" (0x80004005) when modification of either the PidTagAddressBookMember property ([MS-OXOABK] section 2.2.6.1) or the PidTagAddressBookPublicDelegates property ([MS-OXOABK] section 2.2.5.5) is attempted.");
            }

            this.IsRequireToDeleteAddressBookMember = true;
            #endregion

            #region Call NspiGetMatches to check the NspiModLinkAtt result.
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            #region Capture code
            // PidTagAddressBookMember proptag after adding value.
            uint addressBookMemberTagAfterAdd = 0;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(dlistName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // After adding value this value should not be 0x8009000a.
                    addressBookMemberTagAfterAdd = rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag;

                    break;
                }
            }

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1335, the property tag of address book member after adding value is {0}",
                addressBookMemberTagAfterAdd);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1335
            // The proptag of PidTagAddressBookMember property is 0x8009101e as defined in [MS-OXPROPS]. If the last four bytes is 0x000a when being returned, it means that the property has no value.
            // Since the property has no value before the NspiModLinkAtt method is called and has value after that, this requirement can be verified.
            Site.CaptureRequirementIfIsTrue(
                addressBookMemberTagAfterAdd != 0x8009000a,
                1335,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 7] If the input parameter dwFlags does not contain the bit value fDelete, the server MUST add all values specified by the input parameter lpEntryIDs to the property specified by ulPropTag for the object specified by the input parameter dwMId.");

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R129, the property tag of address book member after adding value is {0}",
                addressBookMemberTagAfterAdd);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R129
            // Since the property has no value before the NspiModLinkAtt method is called and has value after that, this requirement can be verified.
            Site.CaptureRequirementIfIsTrue(
                addressBookMemberTagAfterAdd != 0x8009000a,
                129,
                @"[In NspiModLinkAtt Flags] If the fDelete flag is not set, the server adds values when modifying.");

            // MS-OXNSPI_R129 has already verified that modifying property PidTagAddressBookMember succeeds, so MS-OXNSPI_R1893 can be verified directly here.
            this.Site.CaptureRequirement(
                1893,
                @"[In NspiModLinkAtt] This protocol supports modifying the value of the PidTagAddressBookMember ([MS-OXPROPS] section 2.541) property of an address book object with display type DT_DISTLIST.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1306");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1306
            this.Site.CaptureRequirement(
                1306,
                @"[In NspiModLinkAtt] The NspiModLinkAtt method modifies the values of a specific property of a specific row in the address book.");

            #endregion
            #endregion

            #region Call NspiModLinkAtt with fDelete flag to delete the specified value.
            flagsOfModLinkAtt = (uint)NspiModLinkAtFlag.fDelete;
            ErrorCodeValue result2;
            if (!isR2003009Enabled)
            {
                result2 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, result2, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                result2 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookMember = false;
            #endregion

            #region Call NspiGetMatches to check the NspiModLinkAtt delete result.
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            #region Capture code
            bool isDeleteSuccess = false;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(dlistName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // 0x8009000A means that no member exists in distribute list, so the added member has been deleted.
                    if (rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag == 0x8009000A)
                    {
                        isDeleteSuccess = true;
                        break;
                    }
                }
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1332: the returned PidTagAddressBookMember proptag value of the address book object named {0} is {1}", name, rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1332
            // 0x8009000A means that no member exists in distribute list, so the added member has been deleted.
            Site.CaptureRequirementIfIsTrue(
                isDeleteSuccess,
                1332,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] If the input parameter dwFlags contains the bit value fDelete, the server MUST remove all values specified by the input parameter lpEntryIDs from the property specified by ulPropTag for the object specified by input parameter dwMId.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R128: the returned PidTagAddressBookMember property tag value of the address book object named {0} is {1}", name, rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R128
            // 0x8009000A means that no member exists in distribute list, so the added member has been deleted.
            Site.CaptureRequirementIfIsTrue(
                isDeleteSuccess,
                128,
                @"[In NspiModLinkAtt Flags] fDelete (0x00000001): Specifies that the server is to remove values when modifying.");

            #endregion
            #endregion

            #region Call NspiModLinkAtt to add value with the changed Display Type in EphemeralEntryID.
            // If the original display type is DT_MAILUSER (0x00), change it to DT_PRIVATE_DISTLIST (0x05), otherwise to DT_MAILUSER (0x00), to see if the server ignores this field.
            // The Display Type begins with the 25th position in the Entry ID structure.
            if (entryId.Lpbin[0].Lpb[24] == 0x00)
            {
                entryId.Lpbin[0].Lpb[24] = 0x05;
            }
            else
            {
                entryId.Lpbin[0].Lpb[24] = 0x00;
            }

            ErrorCodeValue result3;
            if (!isR2003009Enabled)
            {
                result3 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, result3, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                result3 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookMember = true;
            this.EntryIdToBeDeleted = entryId;
            #endregion

            #region Call NspiModLinkAtt to delete value with the changed Display Type in EphemeralEntryID.
            flagsOfModLinkAtt = (uint)NspiModLinkAtFlag.fDelete;
            ErrorCodeValue result4;
            if (!isR2003009Enabled)
            {
                result4 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, result4, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                result4 = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookMember = false;

            #region Capture code
            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1665, the value of result1 is {0}, the value of result2 is {1}, the value of result3 is {2}, the value of result4 is {3}",
                result1,
                result2,
                result3,
                result4);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1665
            // Since the server returns the same value when the display type field is set to different values in the input parameter, whenever the property value is to be added (result1 and result3) or to be deleted (result2 and result4), this requirement can be verified.
            Site.CaptureRequirementIfIsTrue(
                result1 == result3 && result2 == result4,
                1665,
                @"[In EphemeralEntryID] If this field[Display Type ] is set to different values, the server will return the same value.");

            #endregion
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC13_ModLinkAttFailedWithNotFound()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches to get an Explicit Table.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName + "\0");
            }

            propertyRestriction.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r? filter = propertyRestriction;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    unchecked((uint)AulProp.PidTagAddressBookPublicDelegates),
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiModLinkAtt with an invalid input parameter ulPropTag, so that the server cannot recognize the proptag specified by the invalid ulPropTag.
            uint flagsOfModLinkAtt = 0; // A value which does not contain fDelete flag (0x1).
            uint midOfModLinkAtt = 0;
            BinaryArray_r entryId = new BinaryArray_r
            {
                CValues = 1,
                Lpbin = new Binary_r[1]
            };

            // Get user name.
            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    midOfModLinkAtt = outMIds.Value.AulPropTag[i];
                    entryId.Lpbin[0] = rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.Bin;
                    break;
                }
            }

            uint propTagOfModLinkAtt = (uint)AulProp.PidTagDisplayName;
            this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1326");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1326
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.NotFound,
                this.Result,
                1326,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 3] If the input parameter ulPropTag does not specify a proptag the server recognizes, the server MUST return NotFound.");

            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC32_VerifyNotFoundErrorCode()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;
            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return success!");

            #endregion

            #region Call NspiGetMatches to get valid Minimal Entry IDs and rows.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagDisplayName
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagDisplayName,
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return success!");
            #endregion

            #region Call NspiGetProps to get the property PidTagUserX509Certificate which doesn't not exist in the address book object.
            propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagUserX509Certificate,
                }
            };
            propTagsOfGetMatches = propTags;
            PropertyRow_r? rows;

            this.Result = this.ProtocolAdatper.NspiGetProps(flags, stat, propTagsOfGetMatches, out rows);
            uint errorcode = (uint)rows.Value.LpProps[0].Value.Err;

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2055");

            // Verify MS-OXNSPI requirement: MS-OXCDATA_R2055
            Site.CaptureRequirementIfAreEqual<uint>(
                0x8004010f,
                errorcode,
                "MS-OXCDATA",
                2055,
                @"[In Additional Error Codes] The numeric value (hex) for error code NotFound is 0x8004010F, %x0F.01.04.80.");

            // Verify MS-OXNSPI requirement: MS-OXCDATA_R2054
            // If the error code %x0F.01.04.80 has been captured in MS-OXCDATA_R2055, MS-OXCDATA_R2054 can be verified directly.
            Site.CaptureRequirement(
                "MS-OXCDATA",
                2054,
                @"[In Additional Error Codes] NotFound (MAPI_E_NOT_FOUND) will be returned, On get, indicates that the property or column has no value for this object.");
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        /// <summary>
        /// The NspiGetMatches method returns an Explicit Table. 
        /// </summary>
        /// <param name="reserved">A DWORD value reserved for future use.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="proReserved">A PropertyTagArray_r reserved for future use.</param>
        /// <param name="reserved2">A DWORD value reserved for future use. Ignored by the server.</param>
        /// <param name="filter">The value NULL or a Restriction_r value. 
        /// It holds a logical restriction to apply to the rows in the address book container specified in the stat parameter.</param>
        /// <param name="propName">The value NULL or a PropertyName_r value. 
        /// It holds the property to be opened as a restricted address book container.</param>
        /// <param name="requested">A DWORD value. It contains the maximum number of rows to return in a restricted address book container.</param>
        /// <param name="outMids">A PropertyTagArray_r value. On return, it holds a list of Minimal Entry IDs that comprise a restricted address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. 
        /// It contains a list of the proptags of the columns that client wants to be returned for each row returned.</param>
        /// <param name="rows">A reference to a PropertyRowSet_r value. It contains the address book container rows the server returns in response to the request.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue GetMatches(uint reserved, ref STAT stat, PropertyTagArray_r? proReserved, uint reserved2, Restriction_r? filter, PropertyName_r? propName, uint requested, out PropertyTagArray_r? outMids, PropertyTagArray_r? propTags, out PropertyRowSet_r? rows)
        {
            ErrorCodeValue result;
            byte[] auxIn = new byte[] { };
            GetMatchesRequestBody getMatchesRequestBody = new GetMatchesRequestBody()
            {
                Reserved = reserved,
                HasState = true,
                State = stat,
                InterfaceOptionFlags = reserved2,
                HasPropertyName = false,
                RowCount = requested,
                AuxiliaryBuffer = auxIn,
                AuxiliaryBufferSize = (uint)auxIn.Length
            };

            if (propTags != null)
            {
                LargePropTagArray propetyTags = new LargePropTagArray();
                propetyTags.PropertyTagCount = propTags.Value.CValues;
                propetyTags.PropertyTags = new PropertyTag[propetyTags.PropertyTagCount];
                for (int i = 0; i < propTags.Value.CValues; i++)
                {
                    propetyTags.PropertyTags[i].PropertyId = (ushort)((propTags.Value.AulPropTag[i] & 0xFFFF0000) >> 16);
                    propetyTags.PropertyTags[i].PropertyType = (ushort)(propTags.Value.AulPropTag[i] & 0x0000FFFF);
                }

                getMatchesRequestBody.HasColumns = true;
                getMatchesRequestBody.Columns = propetyTags;
            }

            if (proReserved != null)
            {
                getMatchesRequestBody.HasMinimalIds = true;
                getMatchesRequestBody.MinimalIdCount = proReserved.Value.CValues;
                getMatchesRequestBody.MinimalIds = proReserved.Value.AulPropTag;
            }

            if (filter != null)
            {
                getMatchesRequestBody.HasFilter = true;
                getMatchesRequestBody.Filter = AdapterHelper.ConvertRestriction_rToRestriction(filter.Value);
            }

            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(getMatchesRequestBody, RequestType.GetMatches);
            GetMatchesResponseBody getMatchesResponseBody = GetMatchesResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)getMatchesResponseBody.ErrorCode;
            if (getMatchesResponseBody.HasMinimalIds)
            {
                PropertyTagArray_r propertyTagArray = new PropertyTagArray_r();
                propertyTagArray.CValues = getMatchesResponseBody.MinimalIdCount.Value;
                propertyTagArray.AulPropTag = getMatchesResponseBody.MinimalIds;
                outMids = propertyTagArray;
            }
            else
            {
                outMids = null;
            }

            if (getMatchesResponseBody.RowCount != null)
            {
                PropertyRowSet_r newRows = AdapterHelper.ParsePropertyRowSet_r(getMatchesResponseBody.Columns.Value, getMatchesResponseBody.RowCount.Value, getMatchesResponseBody.RowData);
                rows = newRows;
            }
            else
            {
                rows = null;
            }

            if (getMatchesResponseBody.HasState)
            {
                stat = getMatchesResponseBody.State.Value;
            }

            return result;
        }
        public void MSOXNSPI_S05_TC17_GetMatchesFailedWithTableTooBig()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches with ulRequested set to 0 which is less than the number of rows in the Explicit Table.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;

            // Set request value less than the count of the row number.
            uint requested = 0;
            PropertyName_r? propNameOfGetMatches = null;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagEntryId,
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);

            #region Capture

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1149");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1149
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.TableTooBig,
                this.Result,
                1149,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 16] If the number of rows in the constructed Explicit Table is greater than the input parameter ulRequested, the server MUST return the value ""TableTooBig"".");

            this.VerifyParametersRelatedWithNspiGetMatches(this.Result, outMIds, rowsOfGetMatches, stat, inputStat);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R989");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R989
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.TableTooBig,
                this.Result,
                "MS-OXCDATA",
                989,
                @"[In Error Codes] TableTooBig(MAPI_E_TABLE_TOO_BIG, ecTableTooBig) will be returned, if the table is too big for the requested operation to complete.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R990");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R990
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040403,
                (uint)this.Result,
                "MS-OXCDATA",
                990,
                @"[In Error Codes] The numeric value (hex) for error code TableTooBig is 0x80040403, %x03.04.04.80.");

            #endregion capture
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC19_GetMatchesWithNonZeroReserved1()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches with the input parameter Reserved1 set to 1.
            uint reserved1 = 0x1;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1109, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1109
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1109,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 3] If the input parameter Reserved1 contains any value other than 0, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");

            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC16_GetMatchesFailedWithInvalidBookmark()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches with the SortType field of the input parameter pStat set to SortTypeDisplayName and the ContainerID field of the input parameter pStat set to an invalid value.
            uint reserved1 = 0;
            uint reserver2 = 0;
            uint requested = Constants.GetMatchesRequestedRowNumber;
            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r? proReserved = null;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagEntryId,
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            // If the input SortType field of the input parameter pStat is SortTypeDisplayName or SortTypePhoneticDisplayName and the server is unable to 
            // locate the address book container specified by the ContainerID field in the input parameter pStat, the server MUST return the return value "InvalidBookmark".
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName;
            stat.ContainerID = (uint)MinimalEntryID.MID_CURRENT;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);

            #region Capture

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1122");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1122
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.InvalidBookmark,
                this.Result,
                1122,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 7] If the input SortType field of the input parameter pStat is SortTypeDisplayName or SortTypePhoneticDisplayName and the server is unable to locate the address book container specified by the ContainerID field in the input parameter pStat, the server MUST return the return value ""InvalidBookmark"".");

            this.VerifyParametersRelatedWithNspiGetMatches(this.Result, outMIds, rowsOfGetMatches, stat, inputStat);

            #endregion capture
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC15_GetMatchesFailedWithTooComplex()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches with the input parameter pReserved not set to NULL.
            uint reserved1 = 0;
            uint reserver2 = 0;
            uint requested = Constants.GetMatchesRequestedRowNumber;
            PropertyName_r? propNameOfGetMatches = null;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist = new ExistRestriction_r
                        {
                            Reserved1 = 0,
                            Reserved2 = 0,
                            PropTag = 0x0
                        }
                    }
            };
            Restriction_r? filter = res_r;

            // If the reserved input parameter pReserved contains any value other than NULL, the server MUST return the value "TooComplex".
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagEntryId,
                }
            };
            PropertyTagArray_r? proReserved = propTags;
            PropertyTagArray_r? propTagsOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);

            #region Capture

            this.VerifyParametersRelatedWithNspiGetMatches(this.Result, outMIds, rowsOfGetMatches, stat, inputStat);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R965");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R965
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.TooComplex,
                this.Result,
                "MS-OXCDATA",
                965,
                @"[In Error Codes] TooComplex(MAPI_E_TOO_COMPLEX, ecTooComplex) will be returned, if the operation requested is too complex for
                the server to handle; often applied to restrictions.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R966");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R966
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80040117,
                (uint)this.Result,
                "MS-OXCDATA",
                966,
                @"[In Error Codes] The numeric value (hex) for error code TooComplex is 0x80040117, %x17.01.04.80.");

            #endregion capture
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC14_ModLinkAttFailedWithAccessDenied()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0; // A value which does not contain fDelete flag (0x1).
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches to get an Explicit Table.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction1 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string memberName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(memberName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(memberName + "\0");
            }

            propertyRestriction1.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction1.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r propertyRestriction2 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            string agentName = Common.GetConfigurationPropertyValue("AgentName", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(agentName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(agentName + "\0");
            }

            propertyRestriction2.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction2.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r restrictionOr = new Restriction_r
            {
                Rt = 0x01,
                Res =
                    new RestrictionUnion_r
                    {
                        ResOr = new OrRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                propertyRestriction1, propertyRestriction2
                            }
                        }
                    }
            };

            Restriction_r? filter = restrictionOr;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    unchecked((uint)AulProp.PidTagAddressBookMember),
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiModLinkAtt to modify the value of the PidTagAddressBookMember property of an address book object with display type DT_AGENT, which is not allowed by the server.

            // A value which does not contain fDelete flag (0x1).
            uint flagsOfModLinkAtt = 0;
            uint propTagOfModLinkAtt = (uint)AulProp.PidTagAddressBookMember;
            uint midOfModLinkAtt = 0;
            BinaryArray_r entryId = new BinaryArray_r
            {
                CValues = 1,
                Lpbin = new Binary_r[1]
            };

            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(agentName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    midOfModLinkAtt = outMIds.Value.AulPropTag[i];
                }
                else if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(memberName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    entryId.Lpbin[0] = rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.Bin;
                }

                if (midOfModLinkAtt != 0 && entryId.Lpbin[0].Cb != 0)
                {
                    break;
                }
            }
            
            // Modify the PidTagAddressBookMember.
            this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.AccessDenied, this.Result, "NspiModLinkAtt method should return access denied.");
            #endregion

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1647");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1647
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.AccessDenied,
                this.Result,
                1647,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 5] [If the server is able to locate the object, but will not allow modifications to the object due to its display type,] the server MUST return the value AccessDenied (0x80070005).");
            #endregion

            #region Call NspiGetMatches to get an Explicit Table.
            // Output parameters.
            PropertyTagArray_r? outMIds1;
            PropertyRowSet_r? rowsOfGetMatches1;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds1, propTagsOfGetMatches, out rowsOfGetMatches1);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1646");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1646
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rowsOfGetMatches, rowsOfGetMatches1),
                1646,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 5] If the server is able to locate the object, but will not allow modifications to the object due to its display type, the server MUST NOT modify any properties of any objects in the address book.");
            #endregion

            #region Call NspiModLinkAtt to modify the value of the PidTagAddressBookPublicDelegates property of an address book object with display type DT_AGENT, which is not allowed by the server.
            // Set an invalid mail user name.
            string userName = Common.GetConfigurationPropertyValue("AgentName", this.Site);
            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    midOfModLinkAtt = outMIds.Value.AulPropTag[i];
                    entryId.Lpbin[0] = rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.Bin;
                    break;
                }
            }

            // Modify PidTagAddressBookPublicDelegates.
            propTagOfModLinkAtt = (uint)AulProp.PidTagAddressBookPublicDelegates;
            this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1338");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1338
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.AccessDenied,
                this.Result,
                1338,
                @"[In NspiModLinkAtt] [Server Processing Rules: Upon receiving message NspiModLinkAtt, the server MUST process the data from the message subject to the following constraints:] [Constraint 8] If the server is unable to apply the modifications specified, the server MUST return the value ""AccessDenied"" (0x80070005).");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R907");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R907
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.AccessDenied,
                this.Result,
                "MS-OXCDATA",
                907,
                @"[In Error Codes] AccessDenied(E_ACCESSDENIED, MAPI_E_NO_ACCESS, ecaccessdenied, ecpropsecurityviolation) will be returned, if the caller does not have sufficient access rights to perform the operation.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R908");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R908
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80070005,
                (uint)this.Result,
                "MS-OXCDATA",
                908,
                @"[In Error Codes] The numeric value (hex) for error code AccessDenied is 0x80070005, %x05.00.07.80.");

            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S02_TC31_NspiGetMatchesRestrictionVerification()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches with ExistRestriction and AndRestriction.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r resExist_r = new Restriction_r
            {
                Rt = 0x08,
                Res = new RestrictionUnion_r
                {
                    ResExist =
                        new ExistRestriction_r
                        {
                            Reserved1 = 0,
                            Reserved2 = 0,
                            PropTag = (uint)AulProp.PidTagEntryId
                        }
                }
            };

            Restriction_r resExist_r1 = new Restriction_r
            {
                Rt = 0x08,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagAddressBookPhoneticDisplayName
                            }
                    }
            };

            Restriction_r addRestriction = new Restriction_r
            {
                Rt = 0x00,
                Res =
                    new RestrictionUnion_r
                    {
                        ResAnd = new AndRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                resExist_r, resExist_r1
                            }
                        }
                    }
            };

            Restriction_r? filter = addRestriction;

            PropertyTagArray_r propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags1;

            // Set value for propNameOfGetMatches.
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            uint sortType = stat.SortType;
            uint currentRec = stat.CurrentRec;
            int delta = stat.Delta;
            uint numPos = stat.NumPos;
            uint totalRecs = stat.TotalRecs;
            uint codePage = stat.CodePage;
            uint templateLocale = stat.TemplateLocale;
            uint sortLocale = stat.SortLocale;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            int index = 0;
            foreach (PropertyRow_r rows in rowsOfGetMatches.Value.ARow)
            {
                uint propTag = outMIds.Value.AulPropTag[index];

                // Fetch the value of PidTagEntryId.
                EphemeralEntryID entryId = AdapterHelper.ParseEphemeralEntryIDFromBytes(rows.LpProps[0].Value.Bin.Lpb);
                Site.Assert.AreEqual<uint>(propTag, entryId.Mid, "The Minimal ID of the object (index {0}) is inserted into the Explicit Table.", index);
                index++;
            }

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1144
            // The Minimal ID of the object is inserted into the Explicit Table according to the above assert, so MS-OXNSPI_R1144 can be verified directly.
            Site.CaptureRequirement(
                1144,
                "[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 13] If a specific object is located, the Minimal ID of the object is inserted into the Explicit Table.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1146");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1146
            Site.CaptureRequirementIfAreEqual<uint>(
                currentRec,
                stat.ContainerID,
                1146,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 15] If the server returns ""Success"", the server MUST set the ContainerID field of the output parameter pStat to be equal to the CurrentRec field of the input parameter pStat.");

            Site.Assert.AreEqual<uint>(sortType, stat.SortType, "The server MUST NOT modify SortType field in pStat parameter.");
            Site.Assert.AreEqual<uint>(currentRec, stat.CurrentRec, "The server MUST NOT modify CurrentRec field in pStat parameter.");
            Site.Assert.AreEqual<int>(delta, stat.Delta, "The server MUST NOT modify Delta field in pStat parameter.");
            Site.Assert.AreEqual<uint>(numPos, stat.NumPos, "The server MUST NOT modify NumPos field in pStat parameter.");
            Site.Assert.AreEqual<uint>(totalRecs, stat.TotalRecs, "The server MUST NOT modify TotalRecs field in pStat parameter.");
            Site.Assert.AreEqual<uint>(codePage, stat.CodePage, "The server MUST NOT modify CodePage field in pStat parameter.");
            Site.Assert.AreEqual<uint>(templateLocale, stat.TemplateLocale, "The server MUST NOT modify TemplateLocale field in pStat parameter.");
            Site.Assert.AreEqual<uint>(sortLocale, stat.SortLocale, "The server MUST NOT modify SortLocale field in pStat parameter.");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1147
            // The server didn't modify any other fields except ContainerID field in pStat parameter, MS-OXNSPI_R1147 can be verified directly.
            Site.CaptureRequirement(
                1147,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 15] The server MUST NOT modify any other fields in this parameter [pStat].");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1908");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1908
            // The AndRestriction_r is specified to the server and the NspiGetMatches method performs successfully, if the list of Minimal Entry IDs is not null, MS-OXNSPI_R1908 can be verified.
            Site.CaptureRequirementIfIsNotNull(
                outMIds,
                1908,
                @"[In NspiGetMatches] When AndRestriction_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1914");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1914
            // The ExistRestriction_r is specified to the server and the NspiGetMatches method performs successfully, if the list of Minimal Entry IDs is not null, MS-OXNSPI_R1914 can be verified.
            Site.CaptureRequirementIfIsNotNull(
                outMIds,
                1914,
                @"[In NspiGetMatches] When ExistRestriction_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");
            #endregion

            #region Call NspiGetMatches with ExistRestriction and OrRestriction.

            Restriction_r restrictionOr = new Restriction_r
            {
                Rt = 0x01,
                Res =
                    new RestrictionUnion_r
                    {
                        ResOr = new OrRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                resExist_r, resExist_r1
                            }
                        }
                    }
            };

            filter = restrictionOr;

            propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            propTagsOfGetMatches = propTags1;

            // Set value for propNameOfGetMatches.
            propNameOfGetMatches = null;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1908");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1909
            // The OrRestriction_r is specified to the server and the NspiGetMatches method performs successfully, if the list of Minimal Entry IDs is not null, MS-OXNSPI_R1909 can be verified.
            Site.CaptureRequirementIfIsNotNull(
                outMIds,
                1909,
                @"[In NspiGetMatches] When OrRestriction_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");
            #endregion

            #region Call NspiGetMatches with ContentRestriction.
            Restriction_r contentRestriction = new Restriction_r
            {
                Rt = 0x03,
                Res = new RestrictionUnion_r
                {
                    ResContent = new ContentRestriction_r
                    {
                        FuzzyLevel = 0x00010002 // The value stored in the TaggedValue field matches a starting portion of the value of the column property tag and the comparison does not consider case.
                    }
                }
            };

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string displayName = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName + "\0");
            }

            contentRestriction.Res.ResContent.Prop = new PropertyValue_r[] { target };
            contentRestriction.Res.ResContent.PropTag = (uint)AulProp.PidTagDisplayName;

            filter = contentRestriction;

            propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            propTagsOfGetMatches = propTags1;

            // Set value for propNameOfGetMatches.
            propNameOfGetMatches = null;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1911");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1911
            // The ContentRestriction_r is specified to the server and the NspiGetMatches method performs successfully, if the list of Minimal Entry IDs is not null, MS-OXNSPI_R1911 can be verified.
            Site.CaptureRequirementIfIsNotNull(
                outMIds,
                1911,
                @"[In NspiGetMatches] When ContentRestriction_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");

            #endregion

            #region Call NspiGetMatches with PropertyRestriction.
            Restriction_r propertyRestriction = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            displayName = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName + "\0");
            }

            propertyRestriction.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            filter = propertyRestriction;

            propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            propTagsOfGetMatches = propTags1;

            // Set null value to input parameter property names of NspiGetMatches.
            propNameOfGetMatches = null;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1912");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1912
            // The PropertyRestriction_r is specified to the server and the NspiGetMatches method performs successfully, if the list of Minimal Entry IDs is not null, MS-OXNSPI_R1912 can be verified.
            Site.CaptureRequirementIfIsNotNull(
                outMIds,
                1912,
                @"[In NspiGetMatches] When PropertyRestriction_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1913
            // AndRestriction_r, OrRestriction_r, ContentRestriction_r, PropertyRestriction_r and ExistRestriction_r are verified successfully, MS-OXNSPI_R1913 can be verified directly.
            Site.CaptureRequirement(
                1913,
                @"[In NspiGetMatches] When RestrictionUnion_r is specified to the server via the NspiGetMatches method, the server locates all the objects that meet the restriction criteria, and the list of the Minimal Entry IDs of those objects is constructed.");
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC33_NspiModPropsFaliure()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;
            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return success!");

            #endregion

            #region Call NspiGetMatches to get valid Minimal Entry IDs and rows.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName + "\0");
            }

            propertyRestriction.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r? filter = propertyRestriction;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagDisplayName,
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiModProps method with specific PidTagAddressBookX509Certificate property value.

            // Get user name.         
            uint reservedOfModProps = 0xff;
            PropertyRow_r rowOfModProps = new PropertyRow_r
            {
                LpProps = new PropertyValue_r[1]
            };
            rowOfModProps.LpProps[0].PropTag = (uint)AulProp.PidTagDisplayName;
            rowOfModProps.LpProps[0].Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName.ToUpper(System.Globalization.CultureInfo.CurrentCulture));

            PropertyTagArray_r instanceOfModProps = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagDisplayName
                }
            };
            PropertyTagArray_r? propTagsOfModProps = instanceOfModProps;

            // Set the CurrentRec field with the minimal entry ID of mail user name.
            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    stat.CurrentRec = outMIds.Value.AulPropTag[i];
                    break;
                }
            }

            this.Result = this.ProtocolAdatper.NspiModProps(reservedOfModProps, stat, propTagsOfModProps, rowOfModProps);

            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S02_TC34_NspiGetMatchesStringConversion()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;

            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches to request the string properties to be different from their native types.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                AulPropTag = new uint[]
                {
                    AdapterHelper.ConvertStringToString8((uint)AulProp.PidTagAddressBookDisplayNamePrintable),
                    AdapterHelper.ConvertString8ToString((uint)AulProp.PidTagDisplayName)
                }
            };
            propTags.CValues = (uint)propTags.AulPropTag.Length;
            PropertyTagArray_r? propTagsOfGetMatches = propTags;
            PropertyName_r? propNameOfGetMatches = null;

            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName_RO;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            Site.Assert.IsNotNull(rowsOfGetMatches, "PropertyRowSet_r value should not null. The row number is {0}.", rowsOfGetMatches == null ? 0 : rowsOfGetMatches.Value.CRows);
            Site.Assert.AreNotEqual<int>(0, rowsOfGetMatches.Value.ARow.Length, "At least one address book object should be matched.");

            PropertyRow_r rowValue = rowsOfGetMatches.Value.ARow[0];

            string displayName = System.Text.UnicodeEncoding.Unicode.GetString(rowValue.LpProps[1].Value.LpszW);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1972: The value of PidTagDisplayName is {0}.", displayName);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1972
            // The field LpszW indicates a single Unicode string value.
            Site.CaptureRequirementIfIsNotNull(
                rowValue.LpProps[1].Value.LpszW,
                1972,
                "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiGetMatches method, String values can be returned in Unicode representation in the output parameter ppRows.");

            string displayNamePrintable = System.Text.UnicodeEncoding.UTF8.GetString(rowValue.LpProps[0].Value.LpszA);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1973: The value of PidTagAddressBookDisplayNamePrintable is {0}.", displayNamePrintable);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1973
            // The field LpszA indicates a 8-bit character string value.
            Site.CaptureRequirementIfIsNotNull(
                rowValue.LpProps[0].Value.LpszA,
                1973,
                "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiGetMatches method, String values can be returned in 8-bit character representation in the output parameter ppRows.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1936");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1936
            // The native type of PidTagAddressBookDisplayNamePrintable is PtypString and the client has requested this property with PtypString8.
            Site.CaptureRequirementIfAreEqual<uint>(
                AdapterHelper.ConvertStringToString8((uint)AulProp.PidTagAddressBookDisplayNamePrintable),
                rowValue.LpProps[0].PropTag,
                1936,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiGetMatches] If the native type of a property is PtypString and the client has requested that property with the type PtypString8, the server MUST convert the Unicode representation to an 8-bit character representation in the code page specified by the CodePage field of the pStat parameter prior to returning the value.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1952");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1952
            // The native type of PidTagDisplayName is PtypString8 and the client has requested this property with PtypString.
            Site.CaptureRequirementIfAreEqual<uint>(
                AdapterHelper.ConvertString8ToString((uint)AulProp.PidTagDisplayName),
                rowValue.LpProps[1].PropTag,
                1952,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiGetMatches] If the native type of a property is PtypString8 and the client has requested that property with the type PtypString, the server MUST convert the 8-bit character representation to a Unicode representation prior to returning the value.");
            #endregion

            #region Call NspiGetMatches to request the string properties to be the same as their native types.
            propTags = new PropertyTagArray_r
            {
                AulPropTag = new uint[]
                {
                    (uint)AulProp.PidTagAddressBookDisplayNamePrintable,
                    (uint)AulProp.PidTagDisplayName
                }
            };
            propTags.CValues = (uint)propTags.AulPropTag.Length;
            propTagsOfGetMatches = propTags;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            Site.Assert.IsNotNull(rowsOfGetMatches, "PropertyRowSet_r value should not null. The row number is {0}.", rowsOfGetMatches == null ? 0 : rowsOfGetMatches.Value.CRows);
            Site.Assert.AreNotEqual<int>(0, rowsOfGetMatches.Value.ARow.Length, "At least one address book object should be matched.");

            rowValue = rowsOfGetMatches.Value.ARow[0];

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1944");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1944
            // The native type of PidTagAddressBookDisplayNamePrintable is PtypString and the client has requested this property with PtypString.
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)AulProp.PidTagAddressBookDisplayNamePrintable,
                rowValue.LpProps[0].PropTag,
                1944,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiGetMatches] If the native type of a property is PtypString and the client has requested that property with the type PtypString, the server MUST return the Unicode representation unmodified.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1960");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1960
            // The native type of PidTagDisplayName is PtypString8 and the client has requested this property with PtypString8.
            Site.CaptureRequirementIfAreEqual<uint>(
                (uint)AulProp.PidTagDisplayName,
                rowValue.LpProps[1].PropTag,
                1960,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiGetMatches] If the native type of a property is PtypString8 and the client has requested that property with the type PtypString8, the server MUST return the 8-bit character representation unmodified.");
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC34_NspiSeekEntriesFaliure()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiBind should return success!");
            #endregion

            #region Call NspiGetMatches method with specified filter and prop tags.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r contentRestriction = new Restriction_r
            {
                Rt = 0x03,
                Res = new RestrictionUnion_r
                {
                    ResContent = new ContentRestriction_r
                    {
                        FuzzyLevel = 0x00010002
                    }
                }
            };

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string displayName = Common.GetConfigurationPropertyValue("DistributionListName", this.Site);
            target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName + "\0");
            }

            contentRestriction.Res.ResContent.Prop = new PropertyValue_r[] { target };
            contentRestriction.Res.ResContent.PropTag = (uint)AulProp.PidTagDisplayName;
            Restriction_r? filter = contentRestriction;

            PropertyTagArray_r propTags1 = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[]
                {
                    (uint)AulProp.PidTagDisplayName
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags1;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return success!");
            #endregion

            #region Call NspiSeekentries method with input parameter lpETable is not set to null.
            PropertyValue_r propertyTarget = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                propertyTarget.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            }
            else
            {
                propertyTarget.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName + "\0");
            }

            target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);
            propertyTarget.PropTag = (uint)AulProp.PidTagDisplayName;
            PropertyTagArray_r? table = outMIds;
            PropertyTagArray_r? propertyTags = null;
            PropertyRowSet_r? rowsOfSeekEntries;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reserved1, ref stat, propertyTarget, table, propertyTags, out rowsOfSeekEntries, false);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1020, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1020
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1020,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 2] If the input parameter lpETable is not NULL and does not contain an Explicit Table both containing a restriction of the table specified by the input parameter pStat and sorted as specified by the SortType field of the input parameter pStat, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion

            #region Call NspiSeekentries method and the input parameter STAT block specifies SortTypePhoneticDisplayName and the property specified in the input parameter pTarget is PidTagEntryId.
            propTags1 = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[]
                {
                    (uint)AulProp.PidTagEntryId
                }
            };
            propertyTags = propTags1;

            stat.SortType = (uint)TableSortOrder.SortTypePhoneticDisplayName;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reserved1, ref stat, propertyTarget, table, propertyTags, out rowsOfSeekEntries, false);

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1045");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1045
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.GeneralFailure,
                this.Result,
                1045,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 12] If the SortType field in the input parameter pStat is SortTypePhoneticDisplayName and the property specified in the input parameter pTarget is anything other than PidTagAddressBookPhoneticDisplayName (with either the Property Type PtypString8 or PtypString), the server MUST return the value GeneralFailure.");
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        /// <summary>
        /// The NspiGetMatches method returns an Explicit Table. 
        /// </summary>
        /// <param name="reserved">A DWORD value reserved for future use.</param>
        /// <param name="stat">A STAT block describing a logical position in a specific address book container.</param>
        /// <param name="proReserved">A PropertyTagArray_r reserved for future use.</param>
        /// <param name="reserved2">A DWORD value reserved for future use. Ignored by the server.</param>
        /// <param name="filter">The value NULL or a Restriction_r value. 
        /// It holds a logical restriction to apply to the rows in the address book container specified in the stat parameter.</param>
        /// <param name="propName">The value NULL or a PropertyName_r value. 
        /// It holds the property to be opened as a restricted address book container.</param>
        /// <param name="requested">A DWORD value. It contains the maximum number of rows to return in a restricted address book container.</param>
        /// <param name="outMids">A PropertyTagArray_r value. On return, it holds a list of Minimal Entry IDs that comprise a restricted address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. 
        /// It contains a list of the proptags of the columns that client wants to be returned for each row returned.</param>
        /// <param name="rows">A reference to a PropertyRowSet_r value. It contains the address book container rows the server returns in response to the request.</param>
        /// <param name="needRetry">A Boolean value indicates if need to retry to get an expected result. This parameter is designed to avoid meaningless retry when an error response is expected.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue NspiGetMatches(uint reserved, ref STAT stat, PropertyTagArray_r? proReserved, uint reserved2, Restriction_r? filter, PropertyName_r? propName, uint requested, out PropertyTagArray_r? outMids, PropertyTagArray_r? propTags, out PropertyRowSet_r? rows, bool needRetry = true)
        {
            ErrorCodeValue result = 0;
            STAT inputStat = stat;

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                result = this.nspiRpcAdapter.NspiGetMatches(reserved, ref stat, proReserved, reserved2, filter, propName, requested, out outMids, propTags, out rows, needRetry);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.GetMatches(reserved, ref stat, proReserved, reserved2, filter, propName, requested, out outMids, propTags, out rows);
            }

            this.VerifyNspiGetMatches(result, rows, outMids, inputStat, stat);
            this.VerifyTransport();
            return result;
        }
        public void MSOXNSPI_S02_TC15_QueryRowsSuccessWithNotNullTable()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();

            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };

            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetMatches method to get a list of valid Minimal Entry IDs.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            PropertyTagArray_r propTags1 = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags1;

            // Set value for propNameOfGetMatches.
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            Site.Assert.IsTrue(rowsOfGetMatches != null && outMIds != null, "NspiGetMatches should return valid result used for NspiQueryRows!");
            #endregion

            #region Call NspiQueryRows method using the output parameter outMids of NspiGetMatches as the input parameter lpETable.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount = outMIds.Value.CValues;
            uint[] table = new uint[outMIds.Value.CValues];
            Array.Copy(outMIds.Value.AulPropTag, table, outMIds.Value.CValues);
            uint count = Constants.QueryRowsRequestedRowNumber;
            PropertyRowSet_r? rowsOfQueryRows;

            PropertyTagArray_r propTagsInstance = new PropertyTagArray_r
            {
                CValues = 4,
                AulPropTag = new uint[4]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTags = propTagsInstance;

            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return Success!");

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R974");

            bool isCorresponds = true;
            for (int i = 0; i < table.Length; i++)
            {
                if (table[i] != AdapterHelper.ParseEphemeralEntryIDFromBytes(rowsOfQueryRows.Value.ARow[i].LpProps[0].Value.Bin.Lpb).Mid)
                {
                    Site.Log.Add(
                        LogEntryKind.Debug,
                        "The row of index {0} in RowSet does not correspond to a row in the table. The row in RowSet is {1}, the row in table is {2}.",
                        i,
                        AdapterHelper.ParseEphemeralEntryIDFromBytes(rowsOfQueryRows.Value.ARow[i].LpProps[0].Value.Bin.Lpb).Mid,
                        table[i]);

                    isCorresponds = false;
                    break;
                }
            }

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R974
            Site.CaptureRequirementIfIsTrue(
                isCorresponds,
                974,
                @"[In NspiQueryRows] [Server Processing Rules: Upon receiving message NspiQueryRows, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] Each row in the RowSet corresponds to a row in the table specified by input parameters.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R975");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R975
            Site.CaptureRequirementIfIsTrue(
                isCorresponds,
                975,
                @"[In NspiQueryRows] [Server Processing Rules: Upon receiving message NspiQueryRows, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] The rows in the RowSet are in a one-to-one order preserving correspondence with the rows in the table specified by input parameters.");

            string mailUserName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            string distributionListName = Common.GetConfigurationPropertyValue("DistributionListName", this.Site);
            string forumName = Common.GetConfigurationPropertyValue("ForumName", this.Site);
            string agentName = Common.GetConfigurationPropertyValue("AgentName", this.Site);
            string remoteMailUserName = Common.GetConfigurationPropertyValue("RemoteMailUserName", this.Site);

            bool isDT_MAILUSERTypeCorrect = false;
            bool isDT_DISTLISTTypeCorrect = false;
            bool isDT_FORUMTypeCorrect = false;
            bool isDT_AGENTTypeCorrect = false;
            bool isDT_REMOTE_MAILUSERTypeCorrect = false;

            string name = string.Empty;
            DisplayTypeValue displayType = DisplayTypeValue.DT_SEARCH;

            foreach (PropertyRow_r row in rowsOfQueryRows.Value.ARow)
            {
                // Get name and the corresponding display type.
                foreach (PropertyValue_r val in row.LpProps)
                {
                    if (val.PropTag == (uint)AulProp.PidTagDisplayName)
                    {
                        name = System.Text.Encoding.UTF8.GetString(val.Value.LpszA);
                    }
                    else if (val.PropTag == (uint)AulProp.PidTagDisplayType)
                    {
                        displayType = (DisplayTypeValue)val.Value.L;
                    }
                }

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(mailUserName.ToLower(System.Globalization.CultureInfo.CurrentCulture)) && displayType == DisplayTypeValue.DT_MAILUSER)
                {
                    isDT_MAILUSERTypeCorrect = true;
                }

                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(distributionListName.ToLower(System.Globalization.CultureInfo.CurrentCulture)) && displayType == DisplayTypeValue.DT_DISTLIST)
                {
                    isDT_DISTLISTTypeCorrect = true;
                }

                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(forumName.ToLower(System.Globalization.CultureInfo.CurrentCulture)) && displayType == DisplayTypeValue.DT_FORUM)
                {
                    isDT_FORUMTypeCorrect = true;
                }

                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(agentName.ToLower(System.Globalization.CultureInfo.CurrentCulture)) && displayType == DisplayTypeValue.DT_AGENT)
                {
                    isDT_AGENTTypeCorrect = true;
                }

                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(remoteMailUserName.ToLower(System.Globalization.CultureInfo.CurrentCulture)) && displayType == DisplayTypeValue.DT_REMOTE_MAILUSER)
                {
                    isDT_REMOTE_MAILUSERTypeCorrect = true;
                }
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R48: the display name is {0}, display type is {1}", name, displayType);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R48
            Site.CaptureRequirementIfIsTrue(
                isDT_MAILUSERTypeCorrect,
                48,
                @"[In Display Type Values] DT_MAILUSER display type name with 0x00000000 means A typical messaging user.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R49: the display name is {0}, display type is {1}", name, displayType);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R49
            Site.CaptureRequirementIfIsTrue(
                isDT_DISTLISTTypeCorrect,
                49,
                @"[In Display Type Values] DT_DISTLIST display type name with 0x00000001 means A distribution list.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R50: the display name is {0}, display type is {1}", name, displayType);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R50
            Site.CaptureRequirementIfIsTrue(
                isDT_FORUMTypeCorrect,
                50,
                @"[In Display Type Values] DT_FORUM display type with 0x00000002 value means A forum, such as a bulletin board service or a public or shared folder.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R51: the display name is {0}, display type is {1}", name, displayType);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R51
            Site.CaptureRequirementIfIsTrue(
                isDT_AGENTTypeCorrect,
                51,
                @"[In Display Type Values] DT_AGENT display type with 0x00000003 value means An automated agent, such as Quote-Of-The-Day or a weather chart display.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R55: the display name is {0}, display type is {1}", name, displayType);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R55
            Site.CaptureRequirementIfIsTrue(
                isDT_REMOTE_MAILUSERTypeCorrect,
                55,
                @"[In Display Type Values] DT_REMOTE_MAILUSER display type with 0x00000006 value means An Address Book object known to be from a foreign or remote messaging system.");

            this.VerifyRowsReturnedFromNspiQueryRowsIsNotNull(rowsOfQueryRows);

            this.VerifyServerUsedTheListInNspiQueryRows(rowsOfQueryRows, propTags);

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R958: the SortType of output stat is {0}, the ContainerID of output stat is {1}, the CurrentRec of output stat is {2}, the Delta of output stat is {3}, the NumPos of output stat is {4}, the TotalRecs of output stat is {5}, the CodePage of output stat is {6}, the TemplateLocale of output stat is {7}, the SortLocale of output stat is {8};" +
                "the SortType of inputStat is {9}, the ContainerID of inputStat is {10}, the CurrentRec of inputStat is {11}, the Delta of inputStat is {12}, the NumPos of inputStat is {13}, the TotalRecs of inputStat is {13}, the CodePage of inputStat is {14}, the TemplateLocale of inputStat is {15}, the SortLocale of inputStat is {16}",
                stat.SortType,
                stat.ContainerID,
                stat.CurrentRec,
                stat.Delta,
                stat.NumPos,
                stat.TotalRecs,
                stat.CodePage,
                stat.TemplateLocale,
                stat.SortLocale,
                inputStat.SortType,
                inputStat.ContainerID,
                inputStat.CurrentRec,
                inputStat.Delta,
                inputStat.NumPos,
                inputStat.TotalRecs,
                inputStat.CodePage,
                inputStat.TemplateLocale,
                inputStat.SortLocale);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R958
            bool isVerifyR958 = inputStat.CodePage == stat.CodePage
                                || inputStat.ContainerID == stat.ContainerID
                                || inputStat.CurrentRec == stat.CurrentRec
                                || inputStat.Delta == stat.Delta
                                || inputStat.NumPos == stat.NumPos
                                || inputStat.SortLocale == stat.SortLocale
                                || inputStat.SortType == stat.SortType
                                || inputStat.TemplateLocale == stat.TemplateLocale
                                || inputStat.TotalRecs == stat.TotalRecs;

            // According to the description in section 3.1.4.1.8, if the server is using the table specified by the input parameter pStat, the server must update the status of the table. 
            // So if the returned STAT is not updated, it is believed that the server uses the table specified by the input parameter lpETable.
            Site.CaptureRequirementIfIsTrue(
                isVerifyR958,
                958,
                @"[In NspiQueryRows] [Server Processing Rules: Upon receiving message NspiQueryRows, the server MUST process the data from the message subject to the following constraints:] [Constraint 8] [If the input parameter lpETable is not NULL] The server MUST use that table when constructing the return parameter ppRows.");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1077
            // If the test case can reach here, it is believed that the mids returned by NspiGetMatches are used for NspiQueryRows to specify an Explicit Table, so this requirement can be captured directly.
            this.Site.CaptureRequirement(
                1077,
                @"[In NspiGetMatches] The NspiGetMatches method returns an Explicit Table.");
            #endregion Capture
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S04_TC04_ModLinkAttSuccessWithPidTagAddressBookPublicDelegates()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();
            bool isR2003009Enabled = Common.IsRequirementEnabled(2003009, this.Site);

            #region Call NspiBind to initiate a session between the client and the server.
            uint flags = 0;
            STAT stat = new STAT();
            stat.InitiateStat();
            FlatUID_r guid = new FlatUID_r();
            guid.Ab = new byte[16];
            FlatUID_r? serverGuid = guid;

            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");

            #endregion

            #region Call NspiGetMatches method to get valid Minimal Entry IDs and rows.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            // Create Restriction_r structure to use the display name of specific user as the filter parameter of NspiGetMatches method.
            Restriction_r propertyRestriction1 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = 0
            };
            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(userName + "\0");
            }

            propertyRestriction1.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction1.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r propertyRestriction2 = new Restriction_r
            {
                Rt = 0x04,
                Res = new RestrictionUnion_r
                {
                    ResProperty = new Propertyrestriction_r
                    {
                        Relop = 0x04
                    }
                }
            };
            string administratorName = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(administratorName);
            }
            else
            {
                target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(administratorName + "\0");
            }

            propertyRestriction2.Res.ResProperty.Prop = new PropertyValue_r[] { target };
            propertyRestriction2.Res.ResProperty.PropTag = (uint)AulProp.PidTagDisplayName;

            Restriction_r restrictionOr = new Restriction_r
            {
                Rt = 0x01,
                Res =
                    new RestrictionUnion_r
                    {
                        ResOr = new OrRestriction_r
                        {
                            CRes = 2,
                            LpRes = new Restriction_r[]
                            {
                                propertyRestriction1, propertyRestriction2
                            }
                        }
                    }
            };

            Restriction_r? filter = restrictionOr;

            PropertyName_r? propNameOfGetMatches = null;
            PropertyTagArray_r propTags = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayName,
                    unchecked((uint)AulProp.PidTagAddressBookPublicDelegates),
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region Call NspiModLinkAtt method to add the specified PidTagAddressBookPublicDelegates value.
            uint flag1 = 0x00;
            uint propTagOfModLinkAtt = (uint)AulProp.PidTagAddressBookPublicDelegates;
            uint midOfModLinkAtt = 0;
            BinaryArray_r entryId = new BinaryArray_r
            {
                CValues = 1,
                Lpbin = new Binary_r[1]
            };

            // Get user name
            string name = string.Empty;
            int i = 0;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.UTF8.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    midOfModLinkAtt = outMIds.Value.AulPropTag[i];
                    this.MidToBeModified = midOfModLinkAtt;
                }
                else if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(administratorName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    entryId.Lpbin[0] = rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.Bin;
                    this.EntryIdToBeDeleted = entryId;
                }

                if (this.MidToBeModified != 0 && this.EntryIdToBeDeleted.Lpbin[0].Cb != 0)
                {
                    break;
                }
            }

            ErrorCodeValue flag1Result;
            if (!isR2003009Enabled)
            {
                flag1Result = this.ProtocolAdatper.NspiModLinkAtt(flag1, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, flag1Result, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                flag1Result = this.ProtocolAdatper.NspiModLinkAtt(flag1, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookPublicDelegate = true;
            #endregion

            #region Call NspiGetMatches to check the NspiModLinkAtt result.
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            // PidTagAddressBookPublicDelegates proptag after adding value.
            uint addressBookPublicDelegatesTagAfterAdd = 0;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // After adding value this value should not be 0x8015000a
                    addressBookPublicDelegatesTagAfterAdd = rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag;

                    break;
                }
            }

            #endregion

            #region Call NspiModLinkAtt method to delete the specified PidTagAddressBookPublicDelegates value.
            uint flagsOfModLinkAtt = (uint)NspiModLinkAtFlag.fDelete;
            if (!isR2003009Enabled)
            {
                this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookPublicDelegate = false;
            #endregion

            #region Call NspiGetMatches to check the NspiModLinkAtt result.
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");

            #region Capture code
            // PidTagAddressBookPublicDelegates proptag after deleting value.
            uint addressBookPublicDelegatesTagAfterDelete = 0;
            for (i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[1].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    // After deleting value this value should be 0x8015000a
                    addressBookPublicDelegatesTagAfterDelete = rowsOfGetMatches.Value.ARow[i].LpProps[2].PropTag;

                    break;
                }
            }

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                @"Verify MS-OXNSPI_R2002, the property tag of address book delegate after adding value is {0}, and the property tag of it after deleting value is {1}",
                addressBookPublicDelegatesTagAfterAdd,
                addressBookPublicDelegatesTagAfterDelete);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R2002
            // The proptag of PidTagAddressBookPublicDelegates property is 0x8015101e as defined in [MS-OXPROPS]. If the last four bytes is 0x000a when returned, it means the property has no value.
            // Since the property has no value before the NspiModLinkAtt method is called to add value, and has value after that, then has no value after deleting the value, this requirement can be verified.
            Site.CaptureRequirementIfIsTrue(
                addressBookPublicDelegatesTagAfterAdd != 0x8015000a && addressBookPublicDelegatesTagAfterDelete == 0x8015000a,
                2002,
                @"[In NspiModLinkAtt] This protocol supports modifying the value of the PidTagAddressBookPublicDelegates ([MS-OXPROPS] section 2.557) property of an address book object with display type DT_MAILUSER.");

            #endregion
            #endregion

            #region Call NspiModLinkAtt method twice with different flag value.
            flag1 = 0xff;
            uint flag2 = 0xfe;

            if (!isR2003009Enabled)
            {
                flag1Result = this.ProtocolAdatper.NspiModLinkAtt(flag1, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, flag1Result, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                flag1Result = this.ProtocolAdatper.NspiModLinkAtt(flag1, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookPublicDelegate = true;

            ErrorCodeValue flag2Result;
            if (!isR2003009Enabled)
            {
                flag2Result = this.ProtocolAdatper.NspiModLinkAtt(flag2, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, flag2Result, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                flag2Result = this.ProtocolAdatper.NspiModLinkAtt(flag2, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1927");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1927
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                flag1Result,
                flag2Result,
                1927,
                @"[In NspiModLinkAtt] If dwFlags is set to different values other than the bit flag fDelete, server will return the same result.");
            #endregion

            #region Call NspiModLinkAtt method to delete the specified PidTagAddressBookPublicDelegates value.
            if (!isR2003009Enabled)
            {
                this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId);
                Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiModLinkAtt method should return Success.");
            }
            else
            {
                this.Result = this.ProtocolAdatper.NspiModLinkAtt(flagsOfModLinkAtt, propTagOfModLinkAtt, midOfModLinkAtt, entryId, false);
            }

            this.IsRequireToDeleteAddressBookPublicDelegate = false;
            #endregion

            #region Call NspiUnbind method to destroy the context handle.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }
        public void MSOXNSPI_S05_TC02_OperationsWithUnicodeCodePage()
        {
            this.CheckProductSupported();
            this.CheckMAPIHTTPTransportSupported();

            #region Call NspiBind to initiate a session between the client and the server. The CodePage field of the input parameter pStat in this request is set to “CP_WINUNICODE”.
            STAT stat = new STAT();
            stat.InitiateStat();
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            FlatUID_r guid = new FlatUID_r
            {
                Ab = new byte[16]
            };
            FlatUID_r? serverGuid = guid;

            uint flags = 0x0;
            this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R680, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R680
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                680,
                @"[In NspiBind] [Server Processing Rules: Upon receiving message NspiBind, the server MUST process the data from the message subject to the following constraints:] [constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R696, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R696
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.InvalidCodepage,
                this.Result,
                696,
                @"[In NspiBind] [Server Processing Rules: Upon receiving message NspiBind, the server MUST process the data from the message subject to the following constraints:] [constraint 5] If the server will not service connections using that code page, the server MUST return the error code ""InvalidCodepage"".");

            #endregion

            #endregion

            #region Call NspiBind to initiate a session between the client and the server.

            // Previous Bind operation should be failed, the following Bind operation may fail several times for same reason, so need retry.
            int tryTimes = Convert.ToInt32(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
            stat.InitiateStat();
            for (int i = 0; i < tryTimes; i++)
            {
                this.Result = this.ProtocolAdatper.NspiBind(flags, stat, ref serverGuid);
                if (this.Result == ErrorCodeValue.Success)
                {
                    break;
                }
            }

            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiBind should return Success!");
            #endregion

            #region Call NspiGetSpecialTable with the CodePage field of the input parameter pStat in this request is set to “CP_WINUNICODE”.
            uint version = 0;
            PropertyRowSet_r? rows;

            // Set flags not to containing the flag NspiUnicodeStrings (0x04) and NspiAddressCreationTemplates (0x02).
            uint flagsOfGetSpecialTable = 0;

            // Set CodePage field of pStat to containing the value CP_WINUNICODE
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiGetSpecialTable(flagsOfGetSpecialTable, ref stat, ref version, out rows, false);

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R732, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R732
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                732,
                @"[In NspiGetSpecialTable] [Server Processing Rules: Upon receiving message NspiGetSpecialTable, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the input parameter dwFlags does not contain the value ""NspiUnicodeStrings"", and the input parameter dwFlags does not contain the value ""NspiAddressCreationTemplates"", and the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiGetSpecialTable with the CodePage field of the input parameter pStat in this request is set to an invalid code page.
            stat.CodePage = 0xff;
            this.Result = this.ProtocolAdatper.NspiGetSpecialTable(flagsOfGetSpecialTable, ref stat, ref version, out rows, false);
            Site.Assert.AreNotEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetSpecialTable should not return Success!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R736");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R736
            Site.CaptureRequirementIfIsNull(
                rows,
                736,
                @"[In NspiGetSpecialTable] [Server Processing Rules: Upon receiving message NspiGetSpecialTable, the server MUST process the data from the message subject to the following constraints:] [Constraint 2] If the server returns any return value other than ""Success"", the server MUST return a NULL for the output parameter ppRows.");
            #endregion

            #region Call NspiUpdateStat with CP_WINUNICODE CodePage.
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            uint reserved = 0;
            int? delta = 0;
            stat.Delta = 2;
            ErrorCodeValue result1 = this.ProtocolAdatper.NspiUpdateStat(reserved, ref stat, ref delta, false);

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R780, the value of the result1 is {0}", result1);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R780
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), result1),
                780,
                @"[In NspiUpdateStat] [Server Processing Rules: Upon receiving message NspiUpdateStat, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiGetProps with CP_WINUNICODE CodePage.

            PropertyTagArray_r? propTags;
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                PropertyTagArray_r? prop = null;
                propTags = prop;
            }
            else
            {
                PropertyTagArray_r prop = new PropertyTagArray_r
                {
                    CValues = 2
                };
                prop.AulPropTag = new uint[prop.CValues];
                prop.AulPropTag[0] = (uint)AulProp.PidTagEntryId;
                prop.AulPropTag[1] = (uint)AulProp.PidTagDisplayName;
                propTags = prop;
            }

            uint flagsOfGetProps = (uint)RetrievePropertyFlag.fEphID;
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            PropertyRow_r? row;
            this.Result = this.ProtocolAdatper.NspiGetProps(flagsOfGetProps, stat, propTags, out row, false);

            #region Capture code
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R873, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R873
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                873,
                @"[In NspiGetProps] [Server Processing Rules: Upon receiving message NspiGetProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat is set to the value CP_WINUNICODE and the type of the proptags in the input parameter pPropTags is PtypString8, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiGetProps with invalid CodePage.
            stat.CodePage = 0xff;
            ErrorCodeValue invalidCodePageNspiGetProps = this.ProtocolAdatper.NspiGetProps(flagsOfGetProps, stat, propTags, out row, false);
            Site.Assert.AreNotEqual<ErrorCodeValue>(ErrorCodeValue.Success, invalidCodePageNspiGetProps, "NspiGetProps should not return Success!");
            Site.Assert.AreNotEqual<ErrorCodeValue>(ErrorCodeValue.ErrorsReturned, invalidCodePageNspiGetProps, "NspiGetProps should not return ErrorsReturned!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R877");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R877
            Site.CaptureRequirementIfIsNull(
                row,
                877,
                @"[In NspiGetProps] [Server Processing Rules: Upon receiving message NspiGetProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 2] If the server returns any return values other than""ErrorsReturned"" (0x00040380) or ""Success"" (0x00000000), the server MUST return a NULL for the output parameter ppRows.");

            #endregion

            #region Call NspiQueryRows with CP_WINUNICODE CodePage.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount = 0;
            uint[] table = null;
            uint count = 10;
            PropertyRowSet_r? rowsOfQueryRows;

            PropertyTagArray_r propTagsInstance = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagDisplayName,
                }
            };
            propTags = propTagsInstance;

            // Set the CodePage field of the input parameter pStat to containing the value CP_WINUNICODE.
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R935, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R935
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                935,
                @"[In NspiQueryRows] [Server Processing Rules: Upon receiving message NspiQueryRows, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion Capture
            #endregion

            #region Call NspiQueryRows with invalid CodePage.
            stat.CodePage = 0xff;

            // Here use the same input parameter to call NspiQueryRows.
            ErrorCodeValue invalidCodePageNspiQueryRows = this.ProtocolAdatper.NspiQueryRows(flagsOfGetProps, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows, false);
            Site.Assert.AreNotEqual<ErrorCodeValue>(ErrorCodeValue.Success, invalidCodePageNspiQueryRows, "NspiGetProps should not return Success!");
            Site.Assert.AreNotEqual<ErrorCodeValue>(ErrorCodeValue.ErrorsReturned, invalidCodePageNspiQueryRows, "NspiGetProps should not return ErrorsReturned!");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R982");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R982
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                invalidCodePageNspiGetProps,
                invalidCodePageNspiQueryRows,
                982,
                @"[In NspiQueryRows] [Server Processing Rules: Upon receiving message NspiQueryRows, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] If a call to the NspiGetProps method with these parameters [hRpc, dwFlags, pStat and pPropTags] would return any value other than ""Success"" or ""ErrorsReturned"", the server MUST return that error code as the return value for the NspiQueryRows method.");

            #endregion

            #region Call NspiSeekEntries with CP_WINUNICODE CodePage.
            uint reservedOfSeekEntries = 0;
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = 0x3001001F,
                Reserved = (uint)0x00
            };

            // Set property PidTagDisplayName (0x3001) with PtypString type (0x001F).
            string displayName;
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                displayName = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            }
            else
            {
                displayName = Common.GetConfigurationPropertyValue("User1Name", this.Site) + "\0";
            }

            target.Value.LpszW = System.Text.Encoding.Unicode.GetBytes(displayName);

            PropertyTagArray_r tags = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    target.PropTag
                }
            };
            PropertyTagArray_r? propTagsOfSeekEntries = tags;

            PropertyTagArray_r? tableOfSeekEntries = null;
            PropertyRowSet_r? rowsOfSeekEntries;

            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1016, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1016
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1016,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiGetMatches with CP_WINUNICODE CodePage.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = Constants.GetMatchesRequestedRowNumber;

            Restriction_r res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagEntryId
                            }
                    }
            };
            Restriction_r? filter = res_r;

            propTagsInstance = new PropertyTagArray_r
            {
                CValues = 3,
                AulPropTag = new uint[3]
                {
                    (uint)AulProp.PidTagEntryId,
                    (uint)AulProp.PidTagDisplayType,
                    (uint)AulProp.PidTagObjectType
                }
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTagsInstance;
            PropertyName_r? propNameOfGetMatches = null;

            // Output parameters.
            PropertyTagArray_r? outMIds;
            PropertyRowSet_r? rowsOfGetMatches;

            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1101, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1101
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1101,
                @"[In NspiGetMatches] [Server Processing Rules: Upon receiving message NspiGetMatches, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiResortRestriction with CP_WINUNICODE CodePage.
            #region NspiDNToMId
            reserved = 0;
            StringsArray_r names = new StringsArray_r
            {
                CValues = 3,
                LppszA = new string[3]
                {
                    Common.GetConfigurationPropertyValue("User1Essdn", this.Site),
                    Common.GetConfigurationPropertyValue("User2Essdn", this.Site),
                    Common.GetConfigurationPropertyValue("User3Essdn", this.Site),
                }
            };

            PropertyTagArray_r? mids;
            this.Result = this.ProtocolAdatper.NspiDNToMId(reserved, names, out mids);
            #endregion

            #region NspiResortRestriction

            uint reservedOfResortRestriction = 0;
            PropertyTagArray_r inmids = new PropertyTagArray_r();
            inmids = mids.Value;

            // If the object specified by the CurrentRec field of the input parameter pStat is in the constructed Explicit Table, the NumPos field of the output parameter pStat is set to the numeric position in the Explicit Table.
            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName;
            outMIds = null;
            this.Result = this.ProtocolAdatper.NspiResortRestriction(reservedOfResortRestriction, ref stat, inmids, ref outMIds, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1181, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1181
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1181,
                @"[In NspiResortRestriction] [Server Processing Rules: Upon receiving message NspiResortRestriction, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion
            #endregion

            #region Call NspiCompareMIds with CP_WINUNICODE CodePage.
            #region NspiDNToMId
            reserved = 0;
            names = new StringsArray_r
            {
                CValues = 2,
                LppszA = new string[2]
            };
            names.LppszA[0] = Common.GetConfigurationPropertyValue("User3Essdn", this.Site);
            names.LppszA[1] = Common.GetConfigurationPropertyValue("User1Essdn", this.Site);
            this.Result = this.ProtocolAdatper.NspiDNToMId(reserved, names, out mids);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiDnToMId should return Success!");
            #endregion

            #region NspiCompareMIds
            uint mid1 = mids.Value.AulPropTag[0];
            uint mid2 = mids.Value.AulPropTag[1];
            uint reservedOfCompareMIds = 0;
            int results;

            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiCompareMIds(reservedOfCompareMIds, stat, mid1, mid2, out results, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1223, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1223
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1223,
                @"[In NspiCompareMIds] [Server Processing Rules: Upon receiving message NspiCompareMIds, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion
            #endregion

            #region Call NspiModProps with CP_WINUNICODE CodePage.
            #region NspiGetMatches
            // Call NspiGetMatches to get valid MIDs and rows.
            reserved1 = 0;
            reserver2 = 0;
            proReserved = null;
            requested = Constants.GetMatchesRequestedRowNumber;

            res_r = new Restriction_r
            {
                Rt = 0x8,
                Res =
                    new RestrictionUnion_r
                    {
                        ResExist =
                            new ExistRestriction_r
                            {
                                Reserved1 = 0,
                                Reserved2 = 0,
                                PropTag = (uint)AulProp.PidTagDisplayName
                            }
                    }
            };
            filter = res_r;

            propNameOfGetMatches = null;
            propTagsInstance = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagDisplayName,
                }
            };
            propTagsOfGetMatches = propTagsInstance;

            stat.CodePage = (uint)RequiredCodePage.CP_TELETEX;
            this.Result = this.ProtocolAdatper.NspiGetMatches(reserved1, ref stat, proReserved, reserver2, filter, propNameOfGetMatches, requested, out outMIds, propTagsOfGetMatches, out rowsOfGetMatches);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetMatches should return Success!");
            #endregion

            #region NspiModProps
            // Call NspiModProps method with specific PidTagAddressBookX509Certificate tag.
            uint reservedOfModProps = 0;
            BinaryArray_r certificate = new BinaryArray_r();
            PropertyRow_r rowOfModProps = new PropertyRow_r
            {
                LpProps = new PropertyValue_r[1]
            };
            rowOfModProps.LpProps[0].PropTag = (uint)AulProp.PidTagAddressBookX509Certificate;
            rowOfModProps.LpProps[0].Value.MVbin = certificate;

            PropertyTagArray_r instanceOfModProps = new PropertyTagArray_r
            {
                CValues = 1,
                AulPropTag = new uint[1]
                {
                    (uint)AulProp.PidTagAddressBookX509Certificate
                }
            };
            PropertyTagArray_r? propTagsOfModProps = instanceOfModProps;

            // Get user name.
            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);

            // Set the CurrentRec field with the minimal entry ID of mail user name.
            for (int i = 0; i < rowsOfGetMatches.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfGetMatches.Value.ARow[i].LpProps[0].Value.LpszA);

                // Server will ignore cases when comparing string according to section 2.2.6 in Open Specification MS-OXNSPI.
                if (name.ToLower(System.Globalization.CultureInfo.CurrentCulture).Equals(userName.ToLower(System.Globalization.CultureInfo.CurrentCulture)))
                {
                    stat.CurrentRec = outMIds.Value.AulPropTag[i];
                    break;
                }
            }

            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiModProps(reservedOfModProps, stat, propTagsOfModProps, rowOfModProps, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1280, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1280
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1280,
                @"[In NspiModProps] [Server Processing Rules: Upon receiving message NspiModProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion

            #endregion
            #endregion

            #region Call NspiResolveNames with CP_WINUNICODE CodePage.
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                StringsArray_r strArray;
                strArray.CValues = 2;
                strArray.LppszA = new string[strArray.CValues];
                strArray.LppszA[0] = Common.GetConfigurationPropertyValue("User1Name", this.Site);
                strArray.LppszA[1] = string.Empty;

                propTags = null;
                PropertyRowSet_r? rowOfResolveNames;

                stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
                this.Result = this.ProtocolAdatper.NspiResolveNames((uint)0, stat, propTags, strArray, out mids, out rowOfResolveNames, false);

                #region Capture
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1359, the value of the result is {0}", this.Result);

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R1359
                Site.CaptureRequirementIfIsTrue(
                    Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                    1359,
                    @"[In NspiResolveNames] [Server Processing Rules: Upon receiving message NspiResolveNames, the server MUST process the data from the message subject to the following constraints:] 
                [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, 
                UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark,
                AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.2.");

                #endregion
            }
            #endregion

            #region Call NspiResolveNamesW with CP_WINUNICODE CodePage.
            uint reservedOfResolveNamesW = 0;
            WStringsArray_r wstrArray;
            wstrArray.CValues = 2;
            wstrArray.LppszW = new string[wstrArray.CValues];
            wstrArray.LppszW[0] = Common.GetConfigurationPropertyValue("User1Name", this.Site);
            wstrArray.LppszW[1] = Common.GetConfigurationPropertyValue("User2Name", this.Site);

            propTags = null;
            PropertyRowSet_r? rowOfResolveNamesW;

            stat.CodePage = (uint)RequiredCodePage.CP_WINUNICODE;
            this.Result = this.ProtocolAdatper.NspiResolveNamesW(reservedOfResolveNamesW, stat, propTags, wstrArray, out mids, out rowOfResolveNamesW, false);

            #region Capture
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1410, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1410
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1410,
                @"[In NspiResolveNamesW] [Server Processing Rules: Upon receiving message NspiResolveNamesW, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the CodePage field of the input parameter pStat contains the value CP_WINUNICODE, the server MUST return one of the return values [Success, UnbindSuccess, UnbindFailure, ErrorsReturned, GeneralFailure, NotSupported, InvalidObject, OutOfResources, NotFound, LogonFailed, TooComplex, InvalidCodepage, InvalidLocale, TableTooBig, InvalidBookmark, AccessDenied, NotEnoughMemory and InvalidParameter] specified in section 2.2.1.2.");
            #endregion
            #endregion

            #region Call NspiUnbind to destroy the session between the client and the server.
            uint returnValue = this.ProtocolAdatper.NspiUnbind(0);
            Site.Assert.AreEqual<uint>(1, returnValue, "NspiUnbind method should return 1 (Success).");
            #endregion
        }