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

            #region Call NspiBind to initiate a session between a 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 NspiQueryRows to get the DN of specified user.
            uint flagsOfQueryRows = (uint)RetrievePropertyFlag.fSkipObjects;
            uint tableCount = 0;
            uint[] table = null;
            uint count = Constants.QueryRowsRequestedRowNumber;
            PropertyRowSet_r? rowsOfQueryRows;

            PropertyTagArray_r propTagsInstance = new PropertyTagArray_r();
            propTagsInstance.CValues = 3;
            propTagsInstance.AulPropTag = new uint[3]
            {
                (uint)AulProp.PidTagEntryId,
                (uint)AulProp.PidTagDisplayName,
                (uint)AulProp.PidTagDisplayType,
            };
            PropertyTagArray_r? propTags = propTagsInstance;
            this.Result = this.ProtocolAdatper.NspiQueryRows(flagsOfQueryRows, ref stat, tableCount, table, count, propTags, out rowsOfQueryRows);
            Site.Assert.AreEqual(ErrorCodeValue.Success, this.Result, "NspiQueryRows should return success!");

            string userName = Common.GetConfigurationPropertyValue("User2Name", this.Site);
            string userESSDN = string.Empty;

            for (int i = 0; i < rowsOfQueryRows.Value.CRows; i++)
            {
                string name = System.Text.Encoding.Default.GetString(rowsOfQueryRows.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)))
                {
                    PermanentEntryID administratorEntryID = AdapterHelper.ParsePermanentEntryIDFromBytes(rowsOfQueryRows.Value.ARow[i].LpProps[0].Value.Bin.Lpb);
                    userESSDN = administratorEntryID.DistinguishedName;

                    break;
                }
            }
            #endregion

            #region Call NspiDNToMId to get the MIDs of specified user.
            uint reserved = 0;
            StringsArray_r names = new StringsArray_r();
            names.LppszA = new string[]
            {
                userESSDN
            };
            names.CValues = (uint)names.LppszA.Length;
            PropertyTagArray_r? mids;
            this.Result = this.ProtocolAdatper.NspiDNToMId(reserved, names, out mids);
            #endregion

            #region Call NspiGetMatches to get the specific PidTagAddressBookX509Certificate property to be modified.
            uint reserved1 = 0;
            uint reserver2 = 0;
            PropertyTagArray_r? proReserved = null;
            uint requested = 1;
            stat.CurrentRec = mids.Value.AulPropTag[0];
            Restriction_r? filter = null;
            PropertyTagArray_r propTags1 = new PropertyTagArray_r();
            propTags1.CValues = 2;
            propTags1.AulPropTag = new uint[2]
            {
                (uint)AulProp.PidTagAddressBookX509Certificate,
                (uint)AulProp.PidTagUserX509Certificate
            };
            PropertyTagArray_r? propTagsOfGetMatches = propTags1;

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

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

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

            #region Call NspiModProps method with specific PidTagAddressBookX509Certificate property value.
            uint reservedOfModProps = 1;
            BinaryArray_r emptyValue = new BinaryArray_r();
            PropertyRow_r rowOfModProps = new PropertyRow_r();
            rowOfModProps.LpProps = new PropertyValue_r[2];
            rowOfModProps.LpProps[0].PropTag = (uint)AulProp.PidTagAddressBookX509Certificate;
            rowOfModProps.LpProps[0].Value.MVbin = emptyValue;
            rowOfModProps.LpProps[1].PropTag = (uint)AulProp.PidTagUserX509Certificate;
            rowOfModProps.LpProps[1].Value.MVbin = emptyValue;

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

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

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

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

            // If the codes can reach here, the requirement based on this must have been captured, so it can be captured directly.
            Site.CaptureRequirement(
                "MS-OXPROPS",
                5309,
                @"[In PidTagAddressBookX509Certificate] Property ID: 0x8C6A.");

            // If the codes can reach here, the requirement based on this must have been captured, so it can be captured directly.
            Site.CaptureRequirement(
                "MS-OXPROPS",
                5310,
                @"[In PidTagAddressBookX509Certificate] Data type: PtypMultipleBinary, 0x1102.");

            // If the codes can reach here, the requirement based on this must have been captured, so it can be captured directly.
            Site.CaptureRequirement(
                "MS-OXPROPS",
                8875,
                @"[In PidTagUserX509Certificate] Property ID: 0x3A70.");

            // If the codes can reach here, the requirement based on this must have been captured, so it can be captured directly.
            Site.CaptureRequirement(
                "MS-OXPROPS",
                8876,
                @"[In PidTagUserX509Certificate] Data type: PtypMultipleBinary, 0x1102.");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1267
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.Success,
                this.Result,
                1267,
                @"[In NspiModProps] The NspiModProps method is used to modify the properties of an object in the address book.");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1268
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.Success,
                this.Result,
                1268,
                @"[In NspiModProps] This protocol supports the PidTagUserX509Certificate ([MS-OXPROPS] section 2.1044) and PidTagAddressBookX509Certificate ([MS-OXPROPS] section 2.566) properties.");

            bool isR1289Verified = reservedOfModProps != 0 && ErrorCodeValue.Success == this.Result;

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1289
            Site.CaptureRequirementIfIsTrue(
                isR1289Verified,
                1289,
                @"[In NspiModProps] [Server Processing Rules: Upon receiving message NspiModProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 4] If the Reserved input parameter contains any value other than 0, the server MUST ignore the 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
        }
        /// <summary>
        /// The NspiModProps method is used to modify the properties of an object in the address book. 
        /// </summary>
        /// <param name="reserved">A DWORD value reserved for future use.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r. 
        /// It contains a list of the proptags of the columns from which the client requests all the values to be removed.</param>
        /// <param name="row">A PropertyRow_r value. It contains an address book row.</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 NspiModProps(uint reserved, STAT stat, PropertyTagArray_r? propTags, PropertyRow_r row, bool needRetry = true)
        {
            ErrorCodeValue result;
            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                result = this.nspiRpcAdapter.NspiModProps(reserved, stat, propTags, row, needRetry);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.ModProps(stat, propTags, row);
            }

            this.VerifyNspiModProps(result);
            this.VerifyTransport();
            return result;
        }
        /// <summary>
        /// The NspiGetTemplateInfo method returns information about template objects.
        /// </summary>
        /// <param name="flags">A DWORD value that contains a set of bit flags.</param>
        /// <param name="type">A DWORD value. It specifies the display type of the template for which the information is requested.</param>
        /// <param name="dn">The value NULL or the DN of the template requested. The value is NULL-terminated.</param>
        /// <param name="codePage">A DWORD value. It specifies the code page of the template for which the information is requested.</param>
        /// <param name="localeID">A DWORD value. It specifies the LCID of the template for which the information is requested.</param>
        /// <param name="data">A reference to a PropertyRow_r value. On return, it contains the information requested.</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 NspiGetTemplateInfo(uint flags, uint type, string dn, uint codePage, uint localeID, out PropertyRow_r? data, bool needRetry = true)
        {
            ErrorCodeValue result;

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                result = this.nspiRpcAdapter.NspiGetTemplateInfo(flags, type, dn, codePage, localeID, out data, needRetry);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.GetTemplateInfo(flags, type, dn, codePage, localeID, out data);
            }

            this.VerifyNspiGetTemplateInfo(result, flags, data);
            this.VerifyTransport();
            return result;
        }
        /// <summary>
        /// Verify that the string values can be represented as Unicode string or 8-bit character string values.
        /// </summary>
        /// <param name="returnedRows">The returned rows.</param>
        private void VerifyStringOrString8Value(PropertyRow_r returnedRows)
        {
            bool isString8ValueAllowed = false;
            bool isStringValueAllowed = false;
            for (int i = 0; i < returnedRows.LpProps.Length; i++)
            {
                // The first four bytes are the property ID and the last four bytes are the property type.
                // According to MS-OXPROPS, the native type of property PidTagDisplayName is Unicode string.
                // According to MS-OXCDATA, property errors appear in two different contexts. When an error occurs in getting a property of an object or a column of a table 
                // from the server, the type of the returned property value is ErrorCode (0x000A).
                // So the Unicode string or 8-bit character string values can only be verified when the property is returned successfully. 
                if ((returnedRows.LpProps[i].PropTag & 0xFFFF0000) == 0x30010000 && (returnedRows.LpProps[i].PropTag & 0x0000FFFF) != 0x0000000A)
                {
                    // 0x0000001E means that it is a 8-bit character string value.
                    if ((returnedRows.LpProps[i].PropTag & 0x0000FFFF) == 0x0000001E)
                    {
                        isString8ValueAllowed = true;
                    }

                    // 0x0000001F means that it is a Unicode string value.
                    if ((returnedRows.LpProps[i].PropTag & 0x0000FFFF) == 0x0000001F)
                    {
                        isStringValueAllowed = true;
                    }

                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R433. isString8ValueAllowed is {0}, isStringValueAllowed is {1}.", isString8ValueAllowed, isStringValueAllowed);

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R433
                    this.Site.CaptureRequirementIfIsTrue(
                        isString8ValueAllowed || isStringValueAllowed,
                        433,
                        @"[In String Handling] The Exchange Server NSPI Protocol allows string values to be represented as 8-bit character strings or Unicode strings.");
                }
            }
        }
        /// <summary>
        /// The NspiGetProps method returns an address book row that contains a set of the properties
        /// and values that exist on an object.
        /// </summary>
        /// <param name="flags">A DWORD value that contains a set of bit flags.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. 
        /// It contains a list of the proptags of the properties that the client wants to be returned.</param>
        /// <param name="rows">A nullable PropertyRow_r value. 
        /// It contains the address book container row 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 NspiGetProps(uint flags, STAT stat, PropertyTagArray_r? propTags, out PropertyRow_r? rows, bool needRetry = true)
        {
            ErrorCodeValue result;

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                result = this.nspiRpcAdapter.NspiGetProps(flags, stat, propTags, out rows, needRetry);
            }
            else
            {
                result = this.nspiMapiHttpAdapter.GetProps(flags, stat, propTags, out rows);
            }

            this.VerifyNspiGetProps(result, rows);
            this.VerifyTransport();
            return result;
        }
        /// <summary>
        /// The capture code in NspiGetProps.
        /// </summary>
        /// <param name="returnValue">The return value of NspiGetProps.</param>
        /// <param name="propertyRow">The row that the server returns.</param>
        private void VerifyNspiGetProps(ErrorCodeValue returnValue, PropertyRow_r? propertyRow)
        {
            // The IDL code parses the return value. If the IDL code can return success, the server must return the right result.
            this.Site.CaptureRequirement(
                869,
                @"[In NspiGetProps] Return Values: The server returns a long value specifying the return status of the method.");

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                // The following IDL definition is used to generate the stub class, which is used to communicate with server. So if the operation can be called successfully, the following requirement can be captured directly.
                this.Site.CaptureRequirement(
                    1679,
                    @"[In NspiGetProps] The interface definition is:
                long NspiGetProps(
                    [in] NSPI_HANDLE hRpc,
                    [in] DWORD dwFlags,
                    [in] STAT* pStat,
                    [in, unique] PropertyTagArray_r* pPropTags,
                    [out] PropertyRow_r** ppRows
                );");
            }

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R867
            // 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(
                867,
                @"[In NspiGetProps] ppRows: A reference to a PropertyRow_r value.");

            this.VerifyReturnValues(returnValue);
            if (propertyRow != null)
            {
                this.VerifyPropertyRowStructure(propertyRow.Value);
                this.VerifyStringOrString8Value(propertyRow.Value);
            }
        }
        /// <summary>
        /// The capture code in NspiGetTemplateInfo.
        /// </summary>
        /// <param name="returnValue">The return value of NspiGetTemplateInfo.</param>
        /// <param name="flags">The flags parameter of NspiGetTemplateInfo.</param>
        /// <param name="data">The mids parameter of NspiGetTemplateInfo.</param>
        private void VerifyNspiGetTemplateInfo(ErrorCodeValue returnValue, uint flags, PropertyRow_r? data)
        {
            // The IDL code parses the return value. If the IDL code can return success, the server must return the right result.
            this.Site.CaptureRequirement(
                1458,
                @"[In NspiGetTemplateInfo] Return Values: The server returns a long value that specifies the return status of the method.");

            if (this.transport == "ncacn_http" || this.transport == "ncacn_ip_tcp")
            {
                // The following IDL definition is used to generate the stub class, which is used to communicate with server. So if the operation can be called successfully, the following requirement can be captured directly.
                this.Site.CaptureRequirement(
                    1690,
                    @"[In NspiGetTemplateInfo] The interface definition is:

                long NspiGetTemplateInfo(
                    [in] NSPI_HANDLE hRpc,
                    [in] DWORD dwFlags,
                    [in] DWORD ulType,
                    [string, in, unique] char* pDN,
                    [in] DWORD dwCodePage,
                    [in] DWORD dwLocaleID,
                    [out] PropertyRow_r** ppData
                );");
            }

            this.VerifyReturnValues(returnValue);

            if (returnValue == ErrorCodeValue.Success)
            {
                if (data != null)
                {
                    this.VerifyStringOrString8Value(data.Value);

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R1456
                    // 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(
                        1456,
                        @"[In NspiGetTemplateInfo] ppData: A reference to a PropertyRow_r value.");

                    this.VerifyPropertyRowStructure(data.Value);
                }

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

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R1478
                // This structure is returned from the server. If it's not null, 
                // it illustrates that the server must have constructed a PropertyRow_r value.
                this.Site.CaptureRequirementIfIsNotNull(
                    data,
                    1478,
                    @"[In NspiGetTemplateInfo] [Server Processing Rules: Upon receiving message NspiGetTemplateInfo, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] The server constructs a PropertyRow_r value.");

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

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R1490
                // This structure is returned from the server. If it is not null, it illustrates that the 
                // server has returned the PropertyRow_r structure in the output parameter ppData.
                this.Site.CaptureRequirementIfIsNotNull(
                    data,
                    1490,
                    @"[In NspiGetTemplateInfo] [Server Processing Rules: Upon receiving message NspiGetTemplateInfo, the server MUST process the data from the message subject to the following constraints:] [Constraint 7] The server MUST return the constructed PropertyRow_r structure in the output parameter ppData.");

                if ((flags & 0x00000004) == 0x00000004)
                {
                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXOABKT_R303");

                    bool isPidTagScriptDataAdded = false;
                    foreach (PropertyValue_r propertyValue in data.Value.LpProps)
                    {
                        if (propertyValue.PropTag == 0x00040102)
                        {
                            isPidTagScriptDataAdded = true;
                            this.Site.Log.Add(LogEntryKind.Debug, "The property tag is {0}.", propertyValue.PropTag);
                            break;
                        }
                    }

                    // Verify MS-OXOABKT requirement: MS-OXOABKT_R303
                    this.Site.CaptureRequirementIfIsTrue(
                        isPidTagScriptDataAdded,
                        "MS-OXOABKT",
                        303,
                        @"[In NspiGetTemplateInfo PropertyRow_r format] The Property Added to PropertyRow_r of the flag TI_SCRIPT 0x00000004 is PidTagScriptData 0x00040102.");

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

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R1484
                    this.Site.CaptureRequirementIfIsTrue(
                        isPidTagScriptDataAdded,
                        1484,
                        @"[In NspiGetTemplateInfo] [Server Processing Rules: Upon receiving message NspiGetTemplateInfo, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] The server MUST place this data [the script data for the template] into the PropertyRow_r structure.");
                }
                else if ((flags & 0x00000001) == 0x00000001)
                {
                    // Add the debug information
                    this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXOABKT_R302");

                    bool isPidTagTemplateDataAdded = false;
                    foreach (PropertyValue_r propertyValue in data.Value.LpProps)
                    {
                        if (propertyValue.PropTag == 0x00010102)
                        {
                            isPidTagTemplateDataAdded = true;
                            this.Site.Log.Add(LogEntryKind.Debug, "The property tag is {0}.", propertyValue.PropTag);
                            break;
                        }
                    }

                    // Verify MS-OXOABKT requirement: MS-OXOABKT_R302
                    this.Site.CaptureRequirementIfIsTrue(
                        isPidTagTemplateDataAdded,
                        "MS-OXOABKT",
                        302,
                        @"[In NspiGetTemplateInfo PropertyRow_r format] The Property Added to PropertyRow_r of the flag TI_TEMPLATE 0x00000001 is PidTagTemplateData 0x00010102.");

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

                    // Verify MS-OXNSPI requirement: MS-OXNSPI_R1486
                    this.Site.CaptureRequirementIfAreEqual<uint>(
                        (uint)AulProp.PidTagTemplateData,
                        data.Value.LpProps[0].PropTag,
                        1486,
                        @"[In NspiGetTemplateInfo] [Server Processing Rules: Upon receiving message NspiGetTemplateInfo, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] [If the input parameter dwFlags has the TI_TEMPLATE bit set] The server MUST place this data [the user interface data for the template] into the PropertyRow_r structure.");
                }
            }
        }
        /// <summary>
        /// The NspiGetTemplateInfo method returns information about template objects.
        /// </summary>
        /// <param name="flags">A DWORD value that contains a set of bit flags.</param>
        /// <param name="type">A DWORD value. It specifies the display type of the template for which the information is requested.</param>
        /// <param name="dn">The value NULL or the DN of the template requested. The value is NULL-terminated.</param>
        /// <param name="codePage">A DWORD value. It specifies the code page of the template for which the information is requested.</param>
        /// <param name="localeID">A DWORD value. It specifies the LCID of the template for which the information is requested.</param>
        /// <param name="data">A reference to a PropertyRow_r value. On return, it contains the information requested.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue GetTemplateInfo(uint flags, uint type, string dn, uint codePage, uint localeID, out PropertyRow_r? data)
        {
            ErrorCodeValue result;
            byte[] auxIn = new byte[] { };
            GetTemplateInfoRequestBody getTemplateInfoRequestBody = new GetTemplateInfoRequestBody()
            {
                Flags = flags,
                DisplayType = type,
                CodePage = codePage,
                LocaleId = localeID,
                AuxiliaryBuffer = auxIn,
                AuxiliaryBufferSize = (uint)auxIn.Length
            };

            if (!string.IsNullOrEmpty(dn))
            {
                getTemplateInfoRequestBody.HasTemplateDn = true;
                getTemplateInfoRequestBody.TemplateDn = dn;
            }

            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(getTemplateInfoRequestBody, RequestType.GetTemplateInfo);
            GetTemplateInfoResponseBody getTemplateInfoResponseBody = GetTemplateInfoResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)getTemplateInfoResponseBody.ErrorCode;
            if (getTemplateInfoResponseBody.HasRow)
            {
                PropertyRow_r propertyRow = AdapterHelper.ParsePropertyRow_r(getTemplateInfoResponseBody.Row.Value);
                data = propertyRow;
            }
            else
            {
                data = null;
            }

            return result;
        }
        /// <summary>
        /// Verify PropertyRow_r structure.
        /// </summary>
        /// <param name="propertyRow">A PropertyRow_r value to be verified.</param>
        private void VerifyPropertyRowStructure(PropertyRow_r propertyRow)
        {
            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1574
            // Because the underlying parser code has parsed out the structure which contains it, this requirement can be captured directly.
            this.Site.CaptureRequirement(
                1574,
                @"[In PropertyRow_r Structure] [The type is defined as following:] typedef struct _PropertyRow_r {
                    DWORD Reserved;
                    [range(0,100000)] DWORD cValues;
                    [size_is(cValues)] PropertyValue_r* lpProps;
                } PropertyRow_r;");

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

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

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

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R72
            this.Site.CaptureRequirement(
                "MS-OXCDATA",
                72,
                @"[In StandardPropertyRow Structure] Flag (1 byte): An unsigned integer.");

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

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R73
            // Consider the Flag in StandardPropertyRow structure has the same value with propertyRow.Reserved
            this.Site.CaptureRequirementIfAreEqual<uint>(
                0x0,
                propertyRow.Reserved,
                "MS-OXCDATA",
                73,
                @"[In StandardPropertyRow Structure] Flag (1 byte): This value MUST be set to 0x00 to indicate that all property values are present and without error.");

            // Check whether cValues represents the number of PropertyValue_r structures.
            bool iscValuesRepresented = false;
            if (propertyRow.LpProps == null)
            {
                if (propertyRow.CValues == 0)
                {
                    iscValuesRepresented = true;
                }
                else
                {
                    iscValuesRepresented = false;
                }
            }
            else
            {
                if (propertyRow.LpProps.Length == (int)propertyRow.CValues)
                {
                    iscValuesRepresented = true;
                }
                else
                {
                    iscValuesRepresented = false;
                }
            }

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R229. cValues is {0}", propertyRow.CValues);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R229
            this.Site.CaptureRequirementIfIsTrue(
                iscValuesRepresented,
                229,
                @"[In PropertyRow_r Structure] cValues: The number of PropertyValue_r structures represented in the PropertyRow_r structure.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R230: [In PropertyRow_r Structure] [cValues] This value is {0}.", propertyRow.CValues);

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R230
            this.Site.CaptureRequirementIfIsTrue(
                propertyRow.CValues <= 100000,
                230,
                @"[In PropertyRow_r Structure] [cValues] This value MUST NOT exceed 100,000.");

            if (propertyRow.LpProps != null)
            {
                foreach (PropertyValue_r propertyValue in propertyRow.LpProps)
                {
                    this.VerifyPropertyValueStructure(propertyValue);
                }

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

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R231
                // The PropertyValue_r should be the encoding of the ValueArray field of the StandardPropertyRow data structure
                this.Site.CaptureRequirement(
                    231,
                    @"[In PropertyRow_r Structure] lpProps: Encodes the ValueArray field of the StandardPropertyRow data structure.");
            }

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R82
            // 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",
                82,
                @"[In PropertyRow_r Structure] Reserved (4 bytes): Servers MUST set this value to 0x00000000.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R83
            // 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",
                83,
                @"[In PropertyRow_r Structure] ValueCount (4 bytes):  The number of property values represented in the ValueArray field.");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R84
            // 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",
                84,
                @"[In PropertyRow_r Structure] ValueCount (4 bytes):This value[ValueCount (4 bytes)] MUST NOT exceed 100,000.");
        }
        /// <summary>
        /// The NspiGetProps method returns an address book row that contains a set of the properties
        /// and values that exist on an object.
        /// </summary>
        /// <param name="flags">A DWORD value that contains a set of bit flags.</param>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r value. 
        /// It contains a list of the proptags of the properties that the client wants to be returned.</param>
        /// <param name="rows">A nullable PropertyRow_r value. 
        /// It contains the address book container row the server returns in response to the request.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue GetProps(uint flags, STAT stat, PropertyTagArray_r? propTags, out PropertyRow_r? rows)
        {
            ErrorCodeValue result;
            GetPropsRequestBody getPropertyRequestBody = null;
            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);
                }

                getPropertyRequestBody = this.BuildGetPropsRequestBody(flags, true, stat, true, propetyTags);
            }
            else
            {
                getPropertyRequestBody = this.BuildGetPropsRequestBody(flags, true, stat, false, propetyTags);
            }

            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(getPropertyRequestBody, RequestType.GetProps);
            GetPropsResponseBody getPropsResponseBody = GetPropsResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)getPropsResponseBody.ErrorCode;
            if (getPropsResponseBody.HasPropertyValues)
            {
                PropertyRow_r propertyRow = AdapterHelper.ParsePropertyRow_r(getPropsResponseBody.PropertyValues.Value);
                rows = propertyRow;
            }
            else
            {
                rows = null;
            }

            return result;
        }
        /// <summary>
        /// The NspiModProps method is used to modify the properties of an object in the address book. 
        /// </summary>
        /// <param name="stat">A STAT block that describes a logical position in a specific address book container.</param>
        /// <param name="propTags">The value NULL or a reference to a PropertyTagArray_r. 
        /// It contains a list of the proptags of the columns from which the client requests all the values to be removed.</param>
        /// <param name="row">A PropertyRow_r value. It contains an address book row.</param>
        /// <returns>Status of NSPI method.</returns>
        public ErrorCodeValue ModProps(STAT stat, PropertyTagArray_r? propTags, PropertyRow_r row)
        {
            ErrorCodeValue result;
            ModPropsRequestBody modPropsRequestBody = new ModPropsRequestBody();
            modPropsRequestBody.HasState = true;
            modPropsRequestBody.State = stat;
            if (propTags != null)
            {
                LargePropTagArray largePropTagArray = new LargePropTagArray();
                largePropTagArray.PropertyTagCount = propTags.Value.CValues;
                largePropTagArray.PropertyTags = new PropertyTag[propTags.Value.CValues];
                for (int i = 0; i < propTags.Value.CValues; i++)
                {
                    largePropTagArray.PropertyTags[i].PropertyId = (ushort)((propTags.Value.AulPropTag[i] & 0xFFFF0000) >> 16);
                    largePropTagArray.PropertyTags[i].PropertyType = (ushort)(propTags.Value.AulPropTag[i] & 0x0000FFFF);
                }

                modPropsRequestBody.HasPropertyTagsToRemove = true;
                modPropsRequestBody.PropertyTagsToRemove = largePropTagArray;
            }
            else
            {
                modPropsRequestBody.HasPropertyTagsToRemove = false;
            }

            modPropsRequestBody.HasPropertyValues = true;
            AddressBookPropValueList addressBookPropValueList = new AddressBookPropValueList();
            addressBookPropValueList.PropertyValueCount = row.CValues;
            addressBookPropValueList.PropertyValues = new TaggedPropertyValue[row.CValues];
            for (int i = 0; i < row.CValues; i++)
            {
                addressBookPropValueList.PropertyValues[i] = new TaggedPropertyValue();
                byte[] propertyBytes = new byte[row.LpProps[i].Serialize().Length - 8];
                Array.Copy(row.LpProps[i].Serialize(), 8, propertyBytes, 0, row.LpProps[i].Serialize().Length - 8);
                addressBookPropValueList.PropertyValues[i].Value = propertyBytes;
                PropertyTag propertyTagOfRow = new PropertyTag();
                propertyTagOfRow.PropertyId = (ushort)((row.LpProps[i].PropTag & 0xFFFF0000) >> 16);
                propertyTagOfRow.PropertyType = (ushort)(row.LpProps[i].PropTag & 0x0000FFFF);
                addressBookPropValueList.PropertyValues[i].PropertyTag = propertyTagOfRow;
            }

            modPropsRequestBody.PropertyVaules = addressBookPropValueList;

            byte[] auxIn = new byte[] { };
            modPropsRequestBody.AuxiliaryBuffer = auxIn;
            modPropsRequestBody.AuxiliaryBufferSize = (uint)auxIn.Length;

            ChunkedResponse chunkedResponse = this.SendAddressBookRequest(modPropsRequestBody, RequestType.ModProps);
            ModPropsResponseBody modPropsResponseBody = ModPropsResponseBody.Parse(chunkedResponse.ResponseBodyRawData);
            result = (ErrorCodeValue)modPropsResponseBody.ErrorCode;
            return result;
        }
        /// <summary>
        /// Verify whether uses the list specified by pPropTags.
        /// </summary>
        /// <param name="propTags">The PropertyRow_r must following this.</param>
        /// <param name="propRow">It must follows the PropertyTagArray_r.</param>
        private void VerifyServerUsesListSpecifiedBypPropTagsInNspiGetProps(PropertyTagArray_r? propTags, PropertyRow_r? propRow)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R886");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R886
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.IsRowSubjectToPropTags(propTags, propRow),
                886,
                @"[In NspiGetProps] [Constraint 5] [If the input parameter pPropTags is not NULL] The server MUST use this list [input parameter pPropTags].");
        }
        /// <summary>
        /// Check whether ppData field is null.
        /// </summary>
        /// <param name="data">Contain the information requested by calling NspiGetTemplateInfo.</param>
        private void VerifyWhetherppDataIsNullForNspiGetTemplateInfo(PropertyRow_r? data)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXNSPI_R1462");

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1462
            Site.CaptureRequirementIfIsNull(
                data,
                1462,
                @"[In NspiGetTemplateInfo] [Server Processing Rules: Upon receiving message NspiGetTemplateInfo, the server MUST process the data from the message subject to the following constraints:] [Constraint 1] If the server returns any return value other than ""Success"", the server MUST return the value NULL in the return parameters ppData.");
        }
        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_TC24_ModPropsFailedWithInvalidParameter()
        {
            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 NspiGetSpecialTable method to get a special table from the server.
            uint version = 0;
            PropertyRowSet_r? rows;

            // Set flags to the value "NspiUnicodeStrings".
            uint flagsOfGetSpecialTable = (uint)NspiGetSpecialTableFlags.NspiUnicodeStrings;
            this.Result = this.ProtocolAdatper.NspiGetSpecialTable(flagsOfGetSpecialTable, ref stat, ref version, out rows);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetSpecialTable should return Success!");
            #endregion

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R750
            Site.CaptureRequirementIfAreNotEqual<uint>(
                0,
                version,
                750,
                @"[In NspiGetSpecialTable] [Server Processing Rules: Upon receiving message NspiGetSpecialTable, the server MUST process the data from the message subject to the following constraints:] [Constraint 8] If the client is requesting the rows of the server's address book hierarchy table and the server returns the value ""Success"", the server MUST set the output parameter lpVersion to the version of the server's address book hierarchy table.");

            #endregion

            #region Call NspiModProps with pPropTags set to NULL.
            uint reservedOfModProps = 0;
            PropertyRow_r rowOfModProps = rows.Value.ARow[0];
            PropertyTagArray_r? propTagsOfModProps = null;
            if (this.Transport == "ncacn_http" || this.Transport == "ncacn_ip_tcp")
            {
                this.Result = this.ProtocolAdatper.NspiModProps(reservedOfModProps, stat, propTagsOfModProps, rowOfModProps);

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

                // Verify MS-OXNSPI requirement: MS-OXNSPI_R1291
                Site.CaptureRequirementIfIsTrue(
                    propTagsOfModProps == null && this.Result == ErrorCodeValue.InvalidParameter,
                    1291,
                    @"[In NspiModProps] [Server Processing Rules: Upon receiving message NspiModProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 5] If the input parameter pPropTags is NULL, the server MUST return the value ""InvalidParameter"".");

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

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R903
                Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                    ErrorCodeValue.InvalidParameter,
                    this.Result,
                    "MS-OXCDATA",
                    903,
                    @"[In Error Codes] InvalidParameter(E_INVALIDARG, MAPI_E_INVALID_PARAMETER, ecInvalidParam, ecInvalidSession, ecBadBuffer,
                SYNC_E_INVALID_PARAMETER) will be returned, if an invalid parameter was passed to a remote procedure call (RPC).");

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

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R904
                Site.CaptureRequirementIfAreEqual<uint>(
                    0x80070057,
                    (uint)this.Result,
                    "MS-OXCDATA",
                    904,
                    @"[In Error Codes] The numeric value (hex) for error code InvalidParameter is 0x80070057, %x57.00.07.80.");
                #endregion
            }
            #endregion

            #region Call NspiGetSpecialTable method to get the special table again.
            PropertyRowSet_r? rows1;
            this.Result = this.ProtocolAdatper.NspiGetSpecialTable(flagsOfGetSpecialTable, ref stat, ref version, out rows1);
            Site.Assert.AreEqual<ErrorCodeValue>(ErrorCodeValue.Success, this.Result, "NspiGetSpecialTable should return Success!");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1284
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rows, rows1),
                1284,
                @"[In NspiModProps] [Server Processing Rules: Upon receiving message NspiModProps, 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 NOT modify any properties of any objects in the address book.");

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R750001
            Site.CaptureRequirementIfIsTrue(
                AdapterHelper.AreTwoPropertyRowSetEqual(rows, rows1),
                750001,
                @"[In NspiGetSpecialTable] The Exchange server behavior is considered special as the Ipversion here does not impact any search results. ");
            #endregion
            #endregion

            #region Call NspiModProps again with the CurrentRec field of the input parameter pStat set to an invalid value, so that the server cannot locate the object specified by the invalid CurrentRec.
            reservedOfModProps = 0;
            BinaryArray_r certificate = new BinaryArray_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
                }
            };
            propTagsOfModProps = instanceOfModProps;

            // Set CurrentRec to a value which server is unable to locate.
            stat.CurrentRec = (uint)MinimalEntryID.MID_CURRENT;
            this.Result = this.ProtocolAdatper.NspiModProps(reservedOfModProps, stat, propTagsOfModProps, rowOfModProps);

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

            // Verify MS-OXNSPI requirement: MS-OXNSPI_R1293
            Site.CaptureRequirementIfAreEqual<ErrorCodeValue>(
                ErrorCodeValue.InvalidParameter,
                this.Result,
                1293,
                @"[In NspiModProps] [Server Processing Rules: Upon receiving message NspiModProps, the server MUST process the data from the message subject to the following constraints:] [Constraint 6] If the server is unable to locate the object specified by the CurrentRec field of the input parameter pStat, the server MUST return the value ""InvalidParameter"".");
            #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_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
        }