public void MSOXNSPI_S02_TC35_NspiSeekEntriesStringConversion()
        {
            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 NspiUpdateStat to update the STAT block that represents the position in a table to reflect positioning changes requested by the client.
            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 NspiGetPropList method with dwFlags set to fEphID and CodePage field of STAT block not set to CP_WINUNICODE.
            uint flagsOfGetPropList = (uint)RetrievePropertyFlag.fEphID;
            PropertyTagArray_r? propTagsOfGetPropList;
            uint codePage = (uint)RequiredCodePage.CP_TELETEX;

            this.Result = this.ProtocolAdatper.NspiGetPropList(flagsOfGetPropList, stat.CurrentRec, codePage, out propTagsOfGetPropList);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetPropList should return Success!");
            #endregion

            #region Call NspiSeekentries to request the string properties to be different with their native types.
            uint reservedOfSeekEntries = 0;

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = AdapterHelper.ConvertString8ToString((uint)AulProp.PidTagDisplayName),
                Reserved = (uint)0x00,
            };
            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 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? propTagsOfSeekEntries = propTags;

            PropertyTagArray_r? tableOfSeekEntries = null;
            PropertyRowSet_r? rowsOfSeekEntries;

            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiSeekEntries should return Success!");
            Site.Assert.IsNotNull(rowsOfSeekEntries, "PropertyRowSet_r value should not null. The row number is {0}.", rowsOfSeekEntries == null ? 0 : rowsOfSeekEntries.Value.CRows);
            Site.Assert.AreNotEqual<int>(0, rowsOfSeekEntries.Value.ARow.Length, "At least one address book object should be matched.");
            PropertyRow_r rowValue = rowsOfSeekEntries.Value.ARow[0];

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

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1974
            // The field LpszW indicates a single Unicode string value.
            Site.CaptureRequirementIfIsNotNull(
                rowValue.LpProps[1].Value.LpszW,
                1974,
                "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiSeekEntries 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_R1975: The value of PidTagAddressBookDisplayNamePrintable is {0}.", displayNamePrintable);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1975
            // The field LpszA indicates a 8-bit character string value.
            Site.CaptureRequirementIfIsNotNull(
                rowValue.LpProps[0].Value.LpszA,
                1975,
                "[In Conversion Rules for String Values Specified by the Server to the Client] In NspiSeekEntries 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_R1937");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1937
            // 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,
                1937,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiSeekEntries] 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_R1953");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1953
            // 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,
                1953,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiSeekEntries] 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 NspiSeekEntries to request the string properties to be the same as their native types.

            target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00,
            };
            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.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);

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

            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiSeekEntries should return Success!");
            Site.Assert.IsNotNull(rowsOfSeekEntries, "PropertyRowSet_r value should not null. The row number is {0}.", rowsOfSeekEntries == null ? 0 : rowsOfSeekEntries.Value.CRows);
            Site.Assert.AreNotEqual<int>(0, rowsOfSeekEntries.Value.ARow.Length, "At least one address book object should be matched.");

            rowValue = rowsOfSeekEntries.Value.ARow[0];

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1945
            // 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,
                1945,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiSeekEntries] 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_R1961");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1961
            // 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,
                1961,
                "[In Conversion Rules for String Values Specified by the Server to the Client] [For method NspiSeekEntries] 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_S02_TC36_NspiSeekEntriesWithpPropTagsSetNull()
        {
            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 NspiQueryRows method with propTags set to null.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fSkipObjects;
            uint tableCount = 0;
            uint[] table = null;
            uint count = Constants.QueryRowsRequestedRowNumber;
            PropertyRowSet_r? rowsOfQueryRows;
            string displayName = Common.GetConfigurationPropertyValue("AgentName", this.Site);

            PropertyTagArray_r? propTags = null;
            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.");
            Site.Assert.IsNotNull(rowsOfQueryRows.Value.ARow, "The returned rows should not be empty. The row number is {0}", rowsOfQueryRows == null ? 0 : rowsOfQueryRows.Value.CRows);

            uint[] outMids1 = new uint[rowsOfQueryRows.Value.CRows];
            uint position = 0xffffffff;
            for (uint i = 0; i < rowsOfQueryRows.Value.CRows; i++)
            {
                string name = System.Text.Encoding.UTF8.GetString(rowsOfQueryRows.Value.ARow[i].LpProps[3].Value.LpszA);
                if (displayName.Equals(name, StringComparison.CurrentCultureIgnoreCase))
                {
                    position = i;
                }

                outMids1[i] = (uint)rowsOfQueryRows.Value.ARow[i].LpProps[0].Value.L;
            }
            #endregion

            #region Call NspiUpdateStat to update the STAT block that represents the position in a table to reflect positioning changes requested by the client.
            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 NspiSeekEntries method with requesting 1 prop tag.
            uint reservedOfSeekEntries = 0;
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            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");
            }

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

            PropertyTagArray_r table1 = new PropertyTagArray_r
            {
                AulPropTag = outMids1
            };
            table1.CValues = (uint)table1.AulPropTag.Length;
            PropertyTagArray_r? tableOfSeekEntries = table1;
            PropertyRowSet_r? rowsOfSeekEntries;

            stat.CurrentRec = 0;
            stat.NumPos = 0;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiSeekEntries should return Success!");

            Site.CaptureRequirementIfAreEqual<uint>(
                position,
                stat.NumPos,
                1052,
                "[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] If the server is using the table specified by the input parameter lpETable, the server MUST set the NumPos field of the parameter pStat to the accurate numeric position of the qualifying row in the table.");

            #endregion

            #region Call NspiQueryRows method using parameters of NspiSeekEntries method.
            uint flagsOfQueryRows1 = (uint)RetrievePropertyFlag.fEphID;

            // Create a new table used as the NspiQueryRows input parameter.
            uint[] newTable = new uint[outMids1.Length - stat.NumPos];
            Array.Copy(outMids1, stat.NumPos, newTable, 0, newTable.Length);
            uint tableCount1 = (uint)newTable.Length;
            uint count1 = tableCount1;
            PropertyRowSet_r? rowsOfQueryRows1;
            PropertyTagArray_r? propTags1 = tags;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows1, ref stat, tableCount1, newTable, count1, propTags1, out rowsOfQueryRows1);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return Success!");

            // The returned rows may be empty for the NspiSeekEntries method as indicated in section 3.1.4.1.9 of the specification MS-OXNSPI. SO if it is empty, this method needs to be called again.
            if (rowsOfSeekEntries == null || rowsOfSeekEntries.Value.ARow.Length != rowsOfQueryRows1.Value.ARow.Length)
            {
                this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
                Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiSeekEntries should return Success!");
            }

            Site.Assert.IsNotNull(rowsOfSeekEntries, "The NspiSeekEntries method should return rows when called again!");

            #region Capture
            foreach (PropertyRow_r row in rowsOfSeekEntries.Value.ARow)
            {
                Site.Assert.AreEqual<int>(1, row.LpProps.Length, "The input parameter pPropTags specified 1 property tag.");
                Site.Assert.AreEqual<uint>((uint)AulProp.PidTagDisplayName, row.LpProps[0].PropTag, "The input parameter pPropTags specified property tag PidTagDisplayName.");
            }

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1058
            // All the property tag returned in ppRows were checked and same as specified by the client, MS-OXNSPI_R1058 can be verified directly.
            Site.CaptureRequirement(
                1058,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 15] Subject to the prior constraints [If the input parameter pPropTags is not NULL], the server MUST construct an PropertyRowSet_r to return to the client in the output parameter ppRows.");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1755
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rowsOfSeekEntries, rowsOfQueryRows1),
                1755,
                @"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 NspiSeekEntries parameter hRpc is used as the NspiQueryRows parameter hRpc.
The value fEphID is used as the NspiQueryRows parameter dwFlags.
The NspiSeekEntries output parameter pStat (as modified by the prior constraints) is used as the NspiQueryRows parameter pStat.
If the NspiSeekEntries input parameter lpETable is not NULL, the server constructs an explicit table from the table specified by lpETable by copying rows in order from lpETable to the new explicit table. The server begins copying from the row specified by the NumPos field of the pStat parameter (as modified by the prior constraints), and continues until all remaining rows are added to the new table. The number of rows in this new table is used as the NspiQueryRows parameter dwETableCount, and the new table is used as the NspiQueryRows lpETable parameter.
The list of Minimal Entry IDs in the input parameter lpETable starting with the qualifying row is used as the NspiQueryRows parameter lpETable. These Minimal Entry IDs [the list of Minimal Entry IDs in the input parameter lpETable] are expressed as a simple array of DWORD values rather than as a PropertyTagArray_r value. Note that the qualifying row is included in this list, and that the order of the Minimal Entry IDs from the input parameter lpETable is preserved in this list.
If the NspiSeekEntries input parameter lpETable is not NULL, the value used for the NspiQueryRows parameter dwETableCount is used for the NspiQueryRows parameter Count.
The NspiSeekEntries parameter pPropTags is used as the NspiQueryRows parameter pPropTags.");
            #endregion Capture
            #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_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_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_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_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
        }
        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>
        /// Verify PropertyValue_r structure.
        /// </summary>
        /// <param name="propertyValue">A PropertyValue_r value to be verified.</param>
        private void VerifyPROP_VAL_UNION(PropertyValue_r propertyValue)
        {
            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1572
            // Because the underlying parser code has parsed out the structure which contains it, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                1572,
                @"[In PROP_VAL_UNION Structure] [The type is defined as following:] typedef 
                    [switch_type(long)] 
                    union _PV_r {
                    [case(0x00000002)] 
                    short int i;
                    [case(0x00000003)] 
                    long l;
                    [case(0x0000000B)] 
                    unsigned short int b;
                    [case(0x0000001E)] 
                    [string] char* lpszA;
                    [case(0x00000102)] 
                    Binary_r bin;
                    [case(0x0000001F)] 
                    [string] wchar_t* lpszW;
                    [case(0x00000048)] 
                    FlatUID_r* lpguid;
                    [case(0x00000040)] 
                    FILETIME ft;
                    [case(0x0000000A)] 
                    long err;
                    [case(0x00001002)] 
                    ShortArray_r MVi;
                    [case(0x00001003)] 
                    LongArray_r MVl;
                    [case(0x0000101E)] 
                    stringArray_r MVszA;
                    [case(0x00001102)] 
                    BinaryArray_r MVbin;
                    [case(0x00001048)] 
                    FlatUIDArray_r MVguid;
                    [case(0x0000101F)] 
                    WstringArray_r MVszW;
                    [case(0x00001040)] 
                    DateTimeArray_r MVft;
                    [case(0x00000001, 0x0000000D)] 
                    long lReserved;
                } PROP_VAL_UNION;");

            this.VerifyPropertyStructures();

            switch (propertyValue.PropTag & 0x0000FFFF)
            {
                case 0x00000003:

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R181
                    // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                    this.Site.CaptureRequirement(
                        181,
                        @"[In PROP_VAL_UNION Structure] l: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single 32-bit integer value.");
                    break;

                case 0x0000000B:

                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R183: b: PROP_VAL_UNION, the value is {0}.", propertyValue.Value.B);

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R183
                    this.Site.CaptureRequirementIfIsTrue(
                          (propertyValue.Value.B == 1) || (propertyValue.Value.B == 0),
                          183,
                          @"[In PROP_VAL_UNION Structure] [b] The client and server MUST NOT set this to values other than 1 or 0.");

                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R182. b: PROP_VAL_UNION, the value is {0}.", propertyValue.Value.B);

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R182
                    this.Site.CaptureRequirementIfIsTrue(
                        (propertyValue.Value.B == 1) || (propertyValue.Value.B == 0),
                        182,
                        @"[In PROP_VAL_UNION Structure] b: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single Boolean value.");

                    break;
                case 0x0000001E:

                    if (propertyValue.Value.LpszA != null)
                    {
                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R184
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            184,
                            @"[In PROP_VAL_UNION Structure] lpszA: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single 8-bit character string value.");

                        // The parser code parses the strings based on the string that is ended with null If all the codes can reach here, it illustrates that it is parsed correctly.
                        this.Site.CaptureRequirement(
                            185,
                            @"[In PROP_VAL_UNION Structure] [lpszA] This value is NULL-terminated.");
                    }

                    break;

                case 0x00000102:

                    if (propertyValue.Value.Bin.Lpb != null)
                    {
                        // Add the debug information
                        this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R187: the current number of bytes that be encoded is {0}.", propertyValue.Value.Bin.Lpb.Length);

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R187
                        this.Site.CaptureRequirementIfIsTrue(
                            propertyValue.Value.Bin.Lpb.Length <= 2097152,
                            187,
                            @"[In PROP_VAL_UNION Structure] [bin] The number of bytes that can be encoded in this structure is 2,097,152.");

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R186
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            186,
                            @"[In PROP_VAL_UNION Structure] bin: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single binary data value.");

                        this.VerifyBinary_r(propertyValue.Value.Bin);
                    }

                    break;

                case 0x0000001F:

                    if (propertyValue.Value.LpszW != null && propertyValue.Value.LpszW.Length != 0)
                    {
                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R188
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            188,
                            @"[In PROP_VAL_UNION Structure] lpszW: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single Unicode string value.");

                        // The parser code parses the strings based on the string that is ended with null If all the codes can reach here, it illustrates that it is parsed correctly.
                        this.Site.CaptureRequirement(
                            189,
                            @"[In PROP_VAL_UNION Structure] [lpszW] This value is NULL-terminated.");
                    }

                    break;

                case 0x00000048:
                    this.VerifyFlatUID_r();
                    break;

                case 0x00000040:
                    if (propertyValue.Value.Ft.ToString() != null)
                    {
                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R193
                        // Because the underlying parser code has parsed out the structure which contains it, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            193,
                            @"[In PROP_VAL_UNION Structure] [ft] The value is encoded as a FILETIME structure.");

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R192
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            192,
                            @"[In PROP_VAL_UNION Structure] ft: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single 64-bit integer value.");
                    }

                    break;

                case 0x0000000A:

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R194
                    // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                    this.Site.CaptureRequirement(
                        194,
                        @"[In PROP_VAL_UNION Structure] err: PROP_VAL_UNION contains an encoding of the value of a property that can contain a single PtypErrorCode value.");

                    break;

                case 0x0000101E:

                    if (propertyValue.Value.MVszA.LppszA != null)
                    {
                        // Add the debug information
                        this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R201: the current number of values that be encoded is {0}.", propertyValue.Value.MVszA.LppszA.Length);

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R201
                        this.Site.CaptureRequirementIfIsTrue(
                            propertyValue.Value.MVszA.LppszA.Length <= 100000,
                            201,
                            @"[In PROP_VAL_UNION Structure] [MVszA] The number of values that can be encoded in this structure is 100,000.");

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R199
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            199,
                            @"[In PROP_VAL_UNION Structure] MVszA: PROP_VAL_UNION contains an encoding of the values of a property that can contain multiple 8-bit character string values.");

                        // The parser code parses the strings based on the string that is ended with null. If all the codes can reach here, it illustrates that it is parsed correctly.
                        this.Site.CaptureRequirement(
                            200,
                            @"[In PROP_VAL_UNION Structure] [MVszA] These string values [values of a property] are NULL-terminated.");

                        this.VerifystringArray_r(propertyValue.Value.MVszA);
                    }

                    break;

                case 0x00001102:

                    if (propertyValue.Value.MVbin.Lpbin != null)
                    {
                        for (int i = 0; i < propertyValue.Value.MVbin.Lpbin.Length; i++)
                        {
                            if (propertyValue.Value.MVbin.Lpbin.Length > 2097152)
                            {
                                this.Site.Assert.Fail("The number of bytes that be encoded is {0}, which is large than 2,097,152.", propertyValue.Value.MVbin.Lpbin.Length);
                            }
                        }

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R203
                        this.Site.CaptureRequirement(
                            203,
                            @"[In PROP_VAL_UNION Structure] [MVbin] The number of bytes that can be encoded in each value of this structure is 2,097,152.");

                        // Add the debug information.
                        this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R204: [In PROP_VAL_UNION Structure] [MVbin] The number of values that be encoded in structure PROP_VAL_UNION is {0}", propertyValue.Value.MVbin.CValues);

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R204
                        this.Site.CaptureRequirementIfIsTrue(
                            propertyValue.Value.MVbin.CValues <= 100000,
                            204,
                            @"[In PROP_VAL_UNION Structure] [MVbin] The number of values that can be encoded in this structure is 100,000.");

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R202
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            202,
                            @"[In PROP_VAL_UNION Structure] MVbin: PROP_VAL_UNION contains an encoding of the values of a property that can contain multiple binary data values.");

                        this.VerifyBinaryArray_r(propertyValue.Value.MVbin);
                    }

                    break;

                case 0x0000101F:
                    if (propertyValue.Value.MVszW.LppszW != null)
                    {
                        // Add the debug information
                        this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R210: [In PROP_VAL_UNION Structure] [MVszW] The number of values that be encoded in this structure is {0}", propertyValue.Value.MVszW.CValues);

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R210
                        this.Site.CaptureRequirementIfIsTrue(
                            propertyValue.Value.MVszW.CValues <= 100000,
                            210,
                            @"[In PROP_VAL_UNION Structure] [MVszW] The number of values that can be encoded in this structure is 100,000.");

                        // Verify MS-OXNSPI requirement: MS-OXNSPI_R208
                        // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
                        this.Site.CaptureRequirement(
                            208,
                            @"[In PROP_VAL_UNION Structure] MVszW: PROP_VAL_UNION contains an encoding of the values of a property that can contain multiple Unicode string values.");

                        // The parser code parses the strings based on the string that is ended with null. If all the codes can reach here, it illustrates that it is parsed correctly.
                        this.Site.CaptureRequirement(
                            209,
                            @"[In PROP_VAL_UNION Structure] [MVszW] These string values [values of a property] are NULL-terminated.");

                        this.VerifyWstringArray_r(propertyValue.Value.MVszW);
                    }

                    break;

                // As described in [MS-OXNSPI], these two cases have the same behavior.
                case 0x00000001:
                case 0x0000000D:

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

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R1707
                    this.Site.CaptureRequirementIfAreEqual<int>(
                        0x0,
                        propertyValue.Value.Reserved,
                        1707,
                        @"[In PROP_VAL_UNION Structure] The server under test MUST set this value[lReserved] to the constant 0x00000000.");
                    break;

                default:
                    this.Site.Log.Add(LogEntryKind.Debug, "Property tag {0} is returned by the server but is not covered by the current test suite.", propertyValue.PropTag & 0x0000FFFF);
                    break;
            }
        }
        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_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_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_TC09_SeekEntriesWithReservedNonZero()
        {
            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 NspiUpdateStat to update the STAT block that represents the position in a table to reflect positioning changes requested by the client.
            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 NspiGetPropList method with dwFlags set to fEphID and CodePage field of stat not set to CP_WINUNICODE.
            uint flagsOfGetPropList = (uint)RetrievePropertyFlag.fEphID;
            PropertyTagArray_r? propTagsOfGetPropList;
            uint codePage = (uint)RequiredCodePage.CP_TELETEX;

            this.Result = this.ProtocolAdatper.NspiGetPropList(flagsOfGetPropList, stat.CurrentRec, codePage, out propTagsOfGetPropList);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetPropList should return Success!");
            #endregion

            #region Call NspiSeekEntries with input parameter Reserved set to 1.
            uint reservedOfSeekEntries = 0x1;
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            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.LpszA = System.Text.Encoding.UTF8.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;

            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_R1024, the value of the result is {0}", this.Result);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1024
            Site.CaptureRequirementIfIsTrue(
                Enum.IsDefined(typeof(ErrorCodeValue), this.Result),
                1024,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 3] If the input parameter Reserved 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 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_TC08_SeekEntriesFailedWithGeneralFailure()
        {
            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 NspiSeekEntries with the SortType field of the input parameter pStat that has the value SortTypePhoneticDisplayName.
            // If the input parameter Reserved contains any value other than 0, the server MUST return one of the return values specified in section 2.2.2. 
            uint reservedOfSeekEntries = 0;

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            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.LpszA = System.Text.Encoding.UTF8.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;

            // If the server does not support the SortTypePhoneticDisplayName and the SortType field of the input parameter pStat has the value SortTypePhoneticDisplayName, the server MUST return the value GeneralFailure.
            stat.SortType = (uint)TableSortOrder.SortTypePhoneticDisplayName;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries, false);

            #region Capture

            this.VerifyParametersRelatedWithNspiSeekEntries(this.Result, rowsOfSeekEntries, inputStat, stat);

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1039
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.GeneralFailure,
                this.Result,
                1039,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 9] If the server does not support the SortTypePhoneticDisplayName and the SortType field of the input parameter pStat has the value SortTypePhoneticDisplayName, the server MUST return the value GeneralFailure.");

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

            // This requirement is abstracted from DTD, which is a general description for many Open Specifications. In MS-OXNSPI, it returns GeneralFailure in specific conditions.
            // Verify MS-OXCDATA requirement: MS-OXCDATA_R899
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.GeneralFailure,
                this.Result,
                "MS-OXCDATA",
                899,
                @"[In Error Codes] GeneralFailure (E_FAIL, MAPI_E_CALL_FAILED, ecError, SYNC_E_ERROR) will be returned, if the operation failed for an unspecified reason.");

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

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R900
            Site.CaptureRequirementIfAreEqual<uint>(
                0x80004005,
                (uint)this.Result,
                "MS-OXCDATA",
                900,
                @"[In Error Codes] The numeric value (hex) for error code GeneralFailure is 0x80004005, %x05.40.00.80.");

            #endregion Capture
            #endregion

            #region Call NspiSeekEntries with the SortType field of the input parameter pStat that has a value that is not SortTypeDisplayName or SortTypePhoneticDisplayName.
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName_RO;
            inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries, false);

            #region Capture

            this.VerifyParametersRelatedWithNspiSeekEntries(this.Result, rowsOfSeekEntries, inputStat, stat);

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1041
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.GeneralFailure,
                this.Result,
                1041,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 10] If the SortType field in the input parameter pStat has any value other than SortTypeDisplayName or SortTypePhoneticDisplayName, the server MUST return the value GeneralFailure.");

            #endregion Capture
            #endregion

            #region Call NspiSeekEntries with the SortType field in the input parameter pStat that is SortTypeDisplayName and the property specified in the input parameter pTarget that is not PidTagDisplayName.
            // If the SortType field in the input parameter pStat is SortTypeDisplayName and the property specified in the input parameter pTarget is anything other than PidTagDisplayName (with either the Property Type PtypString8 or PtypString), the server MUST return the value GeneralFailure.
            stat.SortType = (uint)TableSortOrder.SortTypeDisplayName;
            target.PropTag = (uint)AulProp.PidTagDisplayType;
            target.Reserved = 0;
            target.Value.L = 0;

            tags.CValues = 1;
            tags.AulPropTag[0] = target.PropTag;
            propTagsOfSeekEntries = tags;

            inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries, false);

            #region Capture

            this.VerifyParametersRelatedWithNspiSeekEntries(this.Result, rowsOfSeekEntries, inputStat, stat);

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

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

            #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
        }
        /// <summary>
        /// The NspiSeekEntries method searches for and sets the logical position in a specific table
        /// to the first entry greater than or equal to a specified value. 
        /// </summary>
        /// <param name="reserved">A DWORD value that is reserved for future use. Ignored by the server.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="target">A PropertyValue_r value holding the value that is being sought.</param>
        /// <param name="table">The value NULL or a PropertyTagArray_r value. 
        /// It holds a list of Minimal Entry IDs that comprise a restricted address book container.</param>
        /// <param name="propTags">It contains a list of the proptags of the columns 
        /// that client wants to be returned for each row returned.</param>
        /// <param name="rows">It contains the address book container rows the server returns in response to the request.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue SeekEntries(uint reserved, ref STAT stat, PropertyValue_r target, PropertyTagArray_r? table, PropertyTagArray_r? propTags, out PropertyRowSet_r? rows)
        {
            ErrorCodeValue result;
            SeekEntriesRequestBody seekEntriesRequestBody = new SeekEntriesRequestBody();
            TaggedPropertyValue targetValue = new TaggedPropertyValue();
            targetValue.PropertyTag = new PropertyTag((ushort)((target.PropTag & 0xFFFF0000) >> 16), (ushort)(target.PropTag & 0x0000FFFF));
            targetValue.Value = new byte[target.Serialize().Length - 8];
            Array.Copy(target.Serialize(), 8, targetValue.Value, 0, target.Serialize().Length - 8);

            // Reserved. The client MUST set this field to 0x00000000 and the server MUST ignore this field.
            seekEntriesRequestBody.Reserved = reserved;
            seekEntriesRequestBody.HasState = true;
            seekEntriesRequestBody.State = stat;
            seekEntriesRequestBody.HasTarget = true;
            seekEntriesRequestBody.Target = targetValue;
            if (table != null)
            {
                seekEntriesRequestBody.HasExplicitTable = true;
                seekEntriesRequestBody.ExplicitTable = table.Value.AulPropTag;
            }

            LargePropTagArray propetyTags = new LargePropTagArray();
            if (propTags != null)
            {
                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);
                }

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

            seekEntriesRequestBody.AuxiliaryBufferSize = 0;
            seekEntriesRequestBody.AuxiliaryBuffer = new byte[] { };
            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(seekEntriesRequestBody, RequestType.SeekEntries);
            SeekEntriesResponseBody seekEntriesResponseBody = SeekEntriesResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)seekEntriesResponseBody.ErrorCode;
            if (seekEntriesResponseBody.HasColumnsAndRows)
            {
                PropertyRowSet_r newRows = AdapterHelper.ParsePropertyRowSet_r(seekEntriesResponseBody.Columns.Value, seekEntriesResponseBody.RowCount.Value, seekEntriesResponseBody.RowData);
                rows = newRows;
            }
            else
            {
                rows = null;
            }

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

            return result;
        }
        public void MSOXNSPI_S05_TC06_SeekEntriesFailedWithInvalidBookmark()
        {
            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 NspiSeekEntries with an invalid ContainerID field in the input parameter pStat, so that the address book container specified by the invalid ContainerID field cannot be located.
            uint reservedOfSeekEntries = 0;

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            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");
            }

            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.ContainerID = (uint)MinimalEntryID.MID_CURRENT;
            STAT inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1033
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.InvalidBookmark,
                this.Result,
                1033,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] If 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.VerifyParametersRelatedWithNspiSeekEntries(this.Result, rowsOfSeekEntries, inputStat, stat);

            #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
        }
        /// <summary>
        /// Verify PropertyValue_r structure.
        /// </summary>
        /// <param name="propertyValue">A PropertyValue_r value to be verified.</param>
        private void VerifyPropertyValueStructure(PropertyValue_r propertyValue)
        {
            this.VerifyPropertyTag(propertyValue.PropTag);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1573
            // Because the underlying parser code has parsed out the structure which contains it, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                1573,
                @"[In PropertyValue_r Structure] [The PropertyValue_r is defined as following:] typedef struct _PropertyValue_r {
                    DWORD ulPropTag;
                    DWORD ulReserved;
                    [switch_is((long)(ulPropTag & 0x0000FFFF))] 
                        PROP_VAL_UNION Value;
                } PropertyValue_r;");

            // This test suite defines PropertyValue_r structure based on the meaning of PropertyValue data structure. So if the codes can reach here, it means that the semantic meaning is unchanged.
            this.Site.CaptureRequirement(
                219,
                @"[In PropertyValue_r Structure] The semantic meaning is otherwise unchanged from the PropertyValue data structure.");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1708
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x0,
                propertyValue.Reserved,
                1708,
                @"[In PropertyValue_r Structure] The server under test MUST set this value[ulReserved] to the constant 0x00000000.");

            this.VerifyPropertyStructures();

            if (propertyValue.PropTag == (uint)AulProp.PidTagEntryId)
            {
                if (propertyValue.Value.Bin.Lpb[0] == 0x00)
                {
                    // 0x00 means a PermanentEntryID.
                    PermanentEntryID permanentEntryID = AdapterHelper.ParsePermanentEntryIDFromBytes(propertyValue.Value.Bin.Lpb);
                    this.VerifyPermanentEntryID(permanentEntryID);
                    this.VerifyDisplayType(permanentEntryID.DisplayTypeString);
                }
                else if (propertyValue.Value.Bin.Lpb[0] == 0x87)
                {
                    // 0x87 means an EphemeralEntryID.
                    EphemeralEntryID ephemeralEntryID = AdapterHelper.ParseEphemeralEntryIDFromBytes(propertyValue.Value.Bin.Lpb);
                    this.VerifyEphemeralEntryID(ephemeralEntryID);
                    this.VerifyDisplayType(ephemeralEntryID.DisplayType);
                }
            }

            // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                224,
                @"[In PropertyValue_r Structure] [Value] The type value held is specified by the property type of the proptag in the ulPropTag field.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R456
            // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                "MS-OXCDATA",
                456,
                @"[In PropertyValue_r Structure] PropertyTag (4 bytes): This value encodes the property tag with the value represented by the PropertyValue_r structure.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R457
            // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                "MS-OXCDATA",
                457,
                @"[In PropertyValue_r Structure] Reserved (4 bytes):  All clients and servers MUST set this value to 0x00000000.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R458
            // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                "MS-OXCDATA",
                458,
                @"[In PropertyValue_r Structure] PropertyValue (variable): This value encodes the PropertyValue field of the PropertyValue structure, as specified in section 2.11.2.1.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R75
            // This test suite parses code according to this definition. So if the codes can reach here, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                "MS-OXCDATA",
                75,
                @"[In StandardPropertyRow Structure] ValueArray (variable): At each position of the array, the structure will either be a PropertyValue structure, as specified in section 2.11.2.1, if the type of the corresponding property tag was specified, or a TypedPropertyValue structure, as specified in section 2.11.3, if the type of the corresponding property tag was PtypUnspecified (section 2.11.1).");

            this.VerifyPROP_VAL_UNION(propertyValue);
        }
        public void MSOXNSPI_S02_TC10_SeekEntriesSuccessCompareWithNspiQueryRows()
        {
            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 NspiUpdateStat to update the STAT block that represents the position in a table to reflect positioning changes requested by the client.
            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 NspiGetPropList method with dwFlags set to fEphID and CodePage field of STAT block not set to CP_WINUNICODE.
            uint flagsOfGetPropList = (uint)RetrievePropertyFlag.fEphID;
            PropertyTagArray_r? propTagsOfGetPropList;
            uint codePage = (uint)RequiredCodePage.CP_TELETEX;

            this.Result = this.ProtocolAdatper.NspiGetPropList(flagsOfGetPropList, stat.CurrentRec, codePage, out propTagsOfGetPropList);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetPropList should return Success!");
            #endregion

            #region Call NspiSeekEntries method with requesting one property tag.
            uint reservedOfSeekEntries = 0;
            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            string displayName;
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                displayName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            }
            else
            {
                displayName = Common.GetConfigurationPropertyValue("User2Name", this.Site) + "\0";
            }

            target.Value.LpszA = System.Text.Encoding.UTF8.GetBytes(displayName);

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

            PropertyTagArray_r? tableOfSeekEntries = null;
            PropertyRowSet_r? rowsOfSeekEntries;

            uint beforePosition = stat.CurrentRec;

            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiSeekEntries method should succeed.");

            #region Capture

            bool isTheValueGreaterThanOrEqualTo = true;
            for (int i = 0; i < rowsOfSeekEntries.Value.CRows; i++)
            {
                // Check whether the returned property value is greater than or equal to the input property PidTagDisplayName.
                string dispalyNameReturnedFromServer = System.Text.Encoding.UTF8.GetString(rowsOfSeekEntries.Value.ARow[i].LpProps[0].Value.LpszA);

                displayName = displayName.TrimEnd('\0');

                // Value Condition greater than zero indicates the returned property value follows the input PidTagDisplayName property value.
                int result = string.Compare(dispalyNameReturnedFromServer, displayName, StringComparison.Ordinal);                
                if (result < 0)
                {
                    this.Site.Log.Add(LogEntryKind.Debug, "The display name returned from server is {0}, the expected display name is {1}", dispalyNameReturnedFromServer, displayName);

                    isTheValueGreaterThanOrEqualTo = false;
                    break;
                }
            }

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R998
            this.Site.CaptureRequirementIfIsTrue(
                isTheValueGreaterThanOrEqualTo,
                998,
                @"[In NspiSeekEntries] The NspiSeekEntries method searches for and sets the logical position in a specific table to the first entry greater than or equal to a specified value.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1050. The position before calling method NspiSeekEntries is {0}, the position after calling method NspiSeekEntries is {1}.", beforePosition, stat.CurrentRec);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1050
            this.Site.CaptureRequirementIfIsTrue(
                rowsOfSeekEntries != null && stat.CurrentRec != beforePosition,
                1050,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] If a qualifying row was found, the server MUST update the position information in the parameter pStat.");

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

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

            #endregion Capture
            #endregion

            #region Call NspiQueryRows method using parameters of NspiSeekEntries method.
            uint flagsOfQueryRows1 = (uint)RetrievePropertyFlag.fEphID;
            uint tableCount1 = 0;
            uint[] table1 = null;
            uint count1 = rowsOfSeekEntries.Value.CRows;
            PropertyRowSet_r? rowsOfQueryRows1;
            PropertyTagArray_r? propTags1 = tags;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows1, ref stat, tableCount1, table1, count1, propTags1, out rowsOfQueryRows1);
            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_R1695");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1695
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rowsOfSeekEntries, rowsOfQueryRows1),
                1695,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [constraint 15] 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 NspiSeekEntries parameter hRpc is used as the NspiQueryRows parameter hRpc.
                The value fEphID is used as the NspiQueryRows parameter dwFlags.
                The NspiSeekEntries output parameter pStat (as modified by the prior constraints) is used as the NspiQueryRows parameter pStat.
                If the NspiSeekEntries input parameter lpETable is NULL, the value 0 is used as the NspiQueryRows parameter dwETableCount, and the value NULL is used as the NspiQueryRows parameter lpETable.
                If the NspiSeekEntries input parameter lpETable is NULL, the server MUST choose a value for the NspiQueryRows parameter Count. The Exchange Server NSPI Protocol does not prescribe any particular algorithm. The server MUST use a value greater than 0.
                The NspiSeekEntries parameter pPropTags is used as the NspiQueryRows parameter pPropTags.");
            #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
        }
        /// <summary>
        /// The NspiSeekEntries method searches for and sets the logical position in a specific table
        /// to the first entry greater than or equal to a specified value. 
        /// </summary>
        /// <param name="reserved">A DWORD value that is reserved for future use. Ignored by the server.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="target">A PropertyValue_r value holding the value that is being sought.</param>
        /// <param name="table">The value NULL or a PropertyTagArray_r value. 
        /// It holds a list of Minimal Entry IDs that comprise a restricted address book container.</param>
        /// <param name="propTags">It contains a list of the proptags of the columns 
        /// that client wants to be returned for each row returned.</param>
        /// <param name="rows">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 NspiSeekEntries(uint reserved, ref STAT stat, PropertyValue_r target, PropertyTagArray_r? table, 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.NspiSeekEntries(reserved, ref stat, target, table, propTags, out rows, needRetry);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.SeekEntries(reserved, ref stat, target, table, propTags, out rows);
            }

            this.VerifyNspiSeekEntries(result, rows, inputStat, stat);
            this.VerifyTransport();
            return result;
        }
        public void MSOXNSPI_S02_TC11_SeekEntriesSuccessWithNullTable()
        {
            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 NspiSeekentries method with input parameter Reserved set to 0 and input parameter lpETable set to null.
            uint reservedOfSeekEntries = 0;

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00
            };
            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.LpszA = System.Text.Encoding.UTF8.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 inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiSeekEntries method should succeed.");

            #region Capture

            // Add the debug information
            Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXNSPI_R1055: 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_R1055
            bool isVerifyR1055 = inputStat.CodePage == stat.CodePage
                                && inputStat.ContainerID == stat.ContainerID
                                && inputStat.Delta == stat.Delta
                                && inputStat.SortLocale == stat.SortLocale
                                && inputStat.SortType == stat.SortType
                                && inputStat.TemplateLocale == stat.TemplateLocale;

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1055,
                1055,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] The server MUST NOT modify any other fields [CodePage, ContainerID, Delta, SortLocale, SortType, TemplateLocale] of the parameter pStat.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1051, the CurrentRec of stat is {0}", stat.CurrentRec);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1051
            // According to section 2.3.8.1 of Open Specification MS-OXNSPI, Minimal Entry IDs with values less than 0x00000010 are used by clients as signals to 
            // trigger specific behaviors in specific NSPI methods. So if the stat.CurrentRec >= 0x10, it indicates that the Minimal Entry ID is returned by server, and then MS-OXNSPI_R1051 can be verified.
            Site.CaptureRequirementIfIsTrue(
                stat.CurrentRec >= 0x10,
                1051,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] [If a qualifying row was found,] The server MUST set CurrentRec field of the parameter pStat to the Minimal Entry ID of the qualifying row.");

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

            uint objectNum = this.SutControlAdapter.GetNumberOfAddressBookObject();

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1054
            Site.CaptureRequirementIfAreEqual<uint>(
                objectNum,
                stat.TotalRecs,
                1054,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 14] The TotalRecs field of the parameter pStat MUST be set to the accurate number of records in the table used.");

            #endregion
            #endregion

            #region Call NspiSeekentries method again with input parameter Reserved set to 1.
            PropertyRowSet_r? rowsOfSeekEntries1;
            reservedOfSeekEntries = 0x1;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref inputStat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries1);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiSeekEntries should return Success!");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1702
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rowsOfSeekEntries, rowsOfSeekEntries1),
                1702,
                @"[In NspiSeekEntries] If this field[Reserved] is set to different values, the server will return the same result.");
            #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_TC07_SeekEntriesFailedWithNotFound()
        {
            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 NspiSeekEntries with an invalid input parameter pTarget, so that the row specified by the invalid pTarget cannot be found.
            // If the input parameter Reserved contains any value other than 0, the server MUST return one of the return values specified in section 2.2.2.
            uint reservedOfSeekEntries = 0;

            PropertyValue_r target = new PropertyValue_r
            {
                PropTag = (uint)AulProp.PidTagDisplayName,
                Reserved = (uint)0x00,
            };
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                target.Value.LpszA = new byte[] { 0xff, 0xff, 0xff, 0xff };
            }
            else
            {
                target.Value.LpszA = new byte[] { 0xff, 0xff, 0xff, 0xff, 0x00 };
            }

            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 inputStat = stat;
            this.Result = this.ProtocolAdatper.NspiSeekEntries(reservedOfSeekEntries, ref stat, target, tableOfSeekEntries, propTagsOfSeekEntries, out rowsOfSeekEntries);

            #region Capture

            this.VerifyParametersRelatedWithNspiSeekEntries(this.Result, rowsOfSeekEntries, inputStat, stat);

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1048
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.NotFound,
                this.Result,
                1048,
                @"[In NspiSeekEntries] [Server Processing Rules: Upon receiving message NspiSeekEntries, the server MUST process the data from the message subject to the following constraints:] [Constraint 13] If no such row [the first row in the specified table that has a value equal to or greater than the value specified in the input parameter pTarget] exists, the server MUST return the value NotFound.");

            #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
        }